All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.polaris.core.script.GroovyCompiler Maven / Gradle / Ivy
package io.polaris.core.script;
import io.polaris.core.crypto.digest.Digests;
import io.polaris.core.string.Strings;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import lombok.Getter;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.runtime.InvokerHelper;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Qt
* @since 1.8
*/
public class GroovyCompiler {
private String defaultClassNamePrefix = "DefGvy_";
private String defaultClassNameSuffix = ".groovy";
private MyGroovyClassLoader groovyClassLoader;
private Map classCache = new ConcurrentHashMap<>();
private static class Holder {
private static final Map COMPILERS = new ConcurrentHashMap<>();
public static GroovyCompiler get(ClassLoader classLoader) {
return COMPILERS.computeIfAbsent(classLoader, loader -> new GroovyCompiler(classLoader));
}
}
public GroovyCompiler(ClassLoader classLoader) {
CompilerConfiguration config = CompilerConfiguration.DEFAULT;
this.groovyClassLoader = new MyGroovyClassLoader(classLoader, config);
}
public static GroovyCompiler getInstance() {
return GroovyCompiler.Holder.get(Thread.currentThread().getContextClassLoader());
}
public static GroovyCompiler getInstance(ClassLoader classLoader) {
return GroovyCompiler.Holder.get(classLoader);
}
private static String sha1(String content) {
return Base64.getEncoder().encodeToString(Digests.sha1(content != null ? content.trim() : ""));
}
private String buildDefaultScriptName(String str) {
return defaultClassNamePrefix + str + defaultClassNameSuffix;
}
public void clearScript(String scriptName) {
if (Strings.isNotBlank(scriptName)) {
ClassEntry entry = classCache.get(scriptName);
if (entry != null) {
classCache.remove(scriptName);
groovyClassLoader.clearCache(entry.getValue());
}
}
}
public void clearScript(String scriptName, String scriptSource) {
if (Strings.isBlank(scriptName)) {
String hash = sha1(scriptSource);
scriptName = buildDefaultScriptName(hash);
}
clearScript(scriptName);
}
public Script compileScript(String scriptName, String scriptSource) {
try {
Class klass = compile(scriptName, scriptSource);
return createScript(klass);
} catch (Throwable e) {
return new ErrorScript(e);
}
}
public Script createScript(Class klass) {
if (klass == null) {
return new NullScript();
}
if (Script.class.isAssignableFrom(klass)) {
try {
return (Script) klass.newInstance();
} catch (ReflectiveOperationException e) {
throw new ScriptEvalException("初始化脚本类失败", e);
}
}
try {
return (variables) -> {
groovy.lang.Script script = InvokerHelper.createScript(klass, null);
script.setBinding(new Binding(variables));
return script.run();
};
} catch (Exception e) {
throw new ScriptEvalException("初始化脚本类失败", e);
}
}
public GroovyClassLoader getClassLoader() {
return groovyClassLoader;
}
public Class compile(String content) {
return compile(null, content);
}
public Class compile(String name, String content) {
String hash = sha1(content);
if (Strings.isBlank(name)) {
name = buildDefaultScriptName(hash);
}
ClassEntry entry = classCache.get(name);
if (entry != null) {
if (entry.getHash().equals(hash)) {
return entry.getValue();
}
groovyClassLoader.clearCache(entry.getValue());
}
GroovyCodeSource codeSource = new GroovyCodeSource(content, name, "/groovy/script");
codeSource.setCachable(false);
Class klass = groovyClassLoader.parseClass(codeSource);
classCache.put(name, new ClassEntry(hash, klass));
return klass;
}
public groovy.lang.Script createGroovyScript(Class scriptClass, Binding binding) {
return InvokerHelper.createScript(scriptClass, binding);
}
public groovy.lang.Script compileGroovyScript(String name, String content, Binding binding) {
Class clazz = compile(name, content);
groovy.lang.Script script = createGroovyScript(clazz, binding);
return script;
}
public groovy.lang.Script compileGroovyScript(String name, String content, Map variables) {
return compileGroovyScript(name, content, new Binding(variables));
}
public groovy.lang.Script compileGroovyScript(String content, Map variables) {
return compileGroovyScript(null, content, new Binding(variables));
}
public groovy.lang.Script compileGroovyScript(String name, String content, String... args) {
return compileGroovyScript(name, content, new Binding(args));
}
public groovy.lang.Script compileGroovyScript(String content, String... args) {
return compileGroovyScript(null, content, new Binding(args));
}
public Object runScript(String content, String name, Map variables) {
return compileGroovyScript(name, content, variables).run();
}
public Object runScript(String content, Map variables) {
return compileGroovyScript(content, variables).run();
}
public Object runScript(String content, String name, String... args) {
return compileGroovyScript(name, content, args).run();
}
public Object runScript(String content, String... args) {
return compileGroovyScript(content, args).run();
}
public Object runScript(String content, String name, Binding binding) {
return compileGroovyScript(name, content, binding).run();
}
@Getter
private static class ClassEntry {
private String hash;
private Class value;
public ClassEntry(String hash, Class value) {
this.hash = hash;
this.value = value;
}
}
private static class MyGroovyClassLoader extends GroovyClassLoader {
public MyGroovyClassLoader(ClassLoader classLoader, CompilerConfiguration config) {
super(classLoader, config);
}
public MyGroovyClassLoader(CompilerConfiguration config) {
super(Thread.currentThread().getContextClassLoader(), config);
}
public void clearCache(Class cls) {
Class removed = classCache.remove(cls.getName());
if (removed != null) {
InvokerHelper.removeClass(removed);
}
}
}
}