final class FileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> { private final ClassLoaderImpl classLoader; private final Map<URI, JavaFileObject> fileObjects = new HashMap<URI, JavaFileObject>();
public class CharSequenceCompiler<T> { private final ClassLoaderImpl classLoader; private final JavaCompiler compiler; private final List<String> options; private DiagnosticCollector<JavaFileObject> diagnostics; private final FileManagerImpl javaFileManager;
public CharSequenceCompiler(ClassLoader loader, Iterable<String> options) { compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new IllegalStateException( "Cannot find the system Java compiler. " + "Check that your class path includes tools.jar"); } classLoader = new ClassLoaderImpl(loader); diagnostics = new DiagnosticCollector<JavaFileObject>(); final JavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); javaFileManager = new FileManagerImpl(fileManager, classLoader); this.options = new ArrayList<String>(); if (options != null) { for (String option : options) { this.options.add(option); } } }
public synchronized Map<String, Class<T>> compile(final Map<String, CharSequence> classes, final DiagnosticCollector<JavaFileObject> diagnosticsList) throws CharSequenceCompilerException, ClassCastException { List<JavaFileObject> sources = new ArrayList<JavaFileObject>(); for (Entry<String, CharSequence> entry : classes.entrySet()) { String qualifiedClassName = entry.getKey(); CharSequence javaSource = entry.getValue(); if (javaSource != null) { final int dotPos = qualifiedClassName.lastIndexOf('.'); final String className = dotPos == -1 ? qualifiedClassName : qualifiedClassName.substring(dotPos + 1); final String packageName = dotPos == -1 ? "" : qualifiedClassName .substring(0, dotPos); final JavaFileObjectImpl source = new JavaFileObjectImpl(className, javaSource); sources.add(source); javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName, className + ".java", source); } } final CompilationTask task = compiler.getTask(null, javaFileManager, diagnostics, options, null, sources); final Boolean result = task.call(); if (result == null || !result.booleanValue()) { throw new CharSequenceCompilerException("Compilation failed.", classes.keySet(), diagnostics); } try { Map<String, Class<T>> compiled = new HashMap<String, Class<T>>(); for (Entry<String, CharSequence> entry : classes.entrySet()) { String qualifiedClassName = entry.getKey(); final Class<T> newClass = loadClass(qualifiedClassName); compiled.put(qualifiedClassName, newClass); } return compiled; } catch (ClassNotFoundException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } catch (IllegalArgumentException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } catch (SecurityException e) { throw new CharSequenceCompilerException(classes.keySet(), e, diagnostics); } } }
Function newFunction(final String expr) { errors.setText(""); try { // generate semi-secure unique package and class names final String packageName = PACKAGE_NAME + digits(); final String className = "Fx_" + (classNameSuffix++) + digits(); final String qName = packageName + '.' + className; // generate the source class as String final String source = fillTemplate(packageName, className, expr); // compile the generated Java source final DiagnosticCollector<JavaFileObject> errs = new DiagnosticCollector<JavaFileObject>(); Class<Function> compiledFunction = stringCompiler.compile(qName, source, errs, new Class<?>[] { Function.class }); log(errs); return compiledFunction.newInstance(); } catch (CharSequenceCompilerException e) { log(e.getDiagnostics()); } catch (InstantiationException e) { errors.setText(e.getMessage()); } catch (IllegalAccessException e) { errors.setText(e.getMessage()); } catch (IOException e) { errors.setText(e.getMessage()); } return NULL_FUNCTION; }
您通常会生成一些源类,使用它们扩展已有的基类或实现特定接口,从而可以将实例转换为已知的类型并通过一个类型安全 API 调用其方法。注意,在实例化 CharSequenceCompiler<T> 时,Function 类被作为泛型类型参数 T 使用。因此,也可以将 compiledFunction 输入作为 Class<Function> 和 compiledFunction.newInstance(),以返回 Function 实例,而不需要进行强制转换。
动态生成一个 Function 实例后,应用程序使用它针对一系列 x 值生成 y 值,然后使用开源的 JFreeChart API(参见 参考资料)描绘(x,y)值。Swing 应用程序的完整源代码可以通过 javaxtools.compiler.examples.plotter 包的 可下载源代码 部分中获得。