如何编译 Groovy 源而不是从文件系统

How compile Groovy source but not from filesystem

我使用 GroovyClassLoader.parseClass(src) 编译单个 groovy 源模块 "in fly",一切正常。

但问题是当这个源模块导入其他 类 时,这些还没有编译。当我开始编译一个源代码但其他源代码在源路径上需要并准备就绪时,传统编译也会被编译。

我如何将 GroovyClassLoader 与目标一起使用来编译所有其他所需的源而不是来自文件系统。 我的来源例如在数据库中,通过 URI 的远程 http 等。

关键是进行自定义 URL 处理——您必须实施 URLStreamHandler and a URLConnection

如果您 google 周围有一些关于如何实现流处理程序和连接的很好的文档 类——但是对于您正在做的事情,您实际上只需要虚拟实现。

这里有一些源代码 bootstrap 你 -- 它演示了如何将各个部分连接起来。如果您提供 lookupScriptCodeWithJDBCorWhatever 的一些实现,您就可以开始了。

import groovy.lang.GroovyResourceLoader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

public class CustomGroovyResourceLoader implements GroovyResourceLoader {

    private final GroovyResourceLoader parentLoader;

    public CustomGroovyResourceLoader(GroovyResourceLoader parentLoader) {
        this.parentLoader = parentLoader;
    }

    @Override
    public URL loadGroovySource(String filename) throws MalformedURLException {
        URL resourceURL = null;

        if (parentLoader != null) {
            resourceURL = parentLoader.loadGroovySource(filename);
        }

        if (resourceURL == null) {
            resourceURL = createURL(filename);
        }

        return resourceURL;
    }

    public URL createURL(String resourceName) throws MalformedURLException {

        String scriptSourceCode = lookupScriptCodeWithJDBCorWhatever(resourceName);

        return new URL(null, "groovy:///" + resourceName,
                new GroovyResourceStreamHandler(scriptSourceCode));

    }

    private String lookupScriptCodeWithJDBCorWhatever(String resourceName) {

        //TODO: blah blah blah
        return null;
    }

    class GroovyResourceConnection extends URLConnection {

        private final String urlData;

        protected GroovyResourceConnection(URL url, String logic) {
            super(url);
            this.urlData = logic;
        }

        @Override
        public void connect() throws IOException {}

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(urlData.getBytes());
        }
    }

    class GroovyResourceStreamHandler extends URLStreamHandler {

        private final String scriptSource;

        public GroovyResourceStreamHandler(String scriptSource) {
            this.scriptSource = scriptSource;
        }

        @Override
        protected URLConnection openConnection(URL u) throws IOException {
            GroovyResourceConnection connection = new GroovyResourceConnection(u, scriptSource);
            return connection;

        }
    }

}

然后您使用如下所示的一些代码安装这个东西:

GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
groovyClassLoader.setResourceLoader( new CustomGroovyResourceLoader( groovyClassLoader.getResourceLoader() ) );