package com.blogspot.hypefree.fastexpr;
import java.io.ByteArrayInputStream;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
import java.util.concurrent.atomic.AtomicLong;
import org.codehaus.janino.ClassLoaderIClassLoader;
import org.codehaus.janino.Parser;
import org.codehaus.janino.Scanner;
import org.codehaus.janino.UnitCompiler;
import org.codehaus.janino.util.ClassFile;
public final class JaninoFastexpr {
private final static AtomicLong COMPILED_CLASS_INDEX = new AtomicLong();
private final static class JaninoRestrictedClassLoader extends
SecureClassLoader {
Class<?> defineClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length, new ProtectionDomain(null,
new Permissions(), this, null));
}
}
public UnaryDoubleFunction compile(String expression) throws Exception {
if (!java.util.regex.Pattern.matches(
"^[a-zA-Z0-9+\\-()/\\* \t^%\\.\\?]+$", expression)) {
throw new SecurityException();
}
String classPackage = getClass().getPackage().getName() + ".compiled";
String className = "JaninoCompiledFastexpr"
+ COMPILED_CLASS_INDEX.incrementAndGet();
String source = "package " + classPackage + ";\n"
+ "import static java.lang.Math.*;\n" + "public final class "
+ className + " implements "
+ UnaryDoubleFunction.class.getCanonicalName() + " {\n"
+ "public double evaluate(double x) {\n"
+ "return (" + expression + ");\n" + "}\n" + "}";
Scanner scanner = new Scanner(null, new ByteArrayInputStream(
source.getBytes("UTF-8")), "UTF-8");
JaninoRestrictedClassLoader cl = new JaninoRestrictedClassLoader();
UnitCompiler unitCompiler = new UnitCompiler(
new Parser(scanner).parseCompilationUnit(),
new ClassLoaderIClassLoader(cl));
ClassFile[] classFiles = unitCompiler.compileUnit(true, true, true);
Class<?> clazz = cl.defineClass(classPackage + "." + className,
classFiles[0].toByteArray());
return (UnaryDoubleFunction) clazz.newInstance();
}
}