/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License *******************************************************************************/ package hydrograph.engine.expression.utils; import javax.tools.*; import javax.tools.JavaCompiler.CompilationTask; import java.io.StringWriter; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The Class CompileUtils. * * @author Bitwise */ public class CompileUtils { private static JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); private static DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); private static StandardJavaFileManager manager = compiler.getStandardFileManager(diagnostics, null, null); private static CompilationTask task; /** * @param fields * object contains all fields name w.r.t default values. * @param expression * is a construct made up of fields, operators, and method * invocations * @param packageName * contains all the imported classes. * @return a DiagnosticCollector of {@link JavaFileObject} objects which * contains all the compile time information . */ public static DiagnosticCollector<JavaFileObject> javaCompile(String fields, String expression, String packageName,String returnTypeOfExprClass) { diagnostics = new DiagnosticCollector<JavaFileObject>(); StringWriter writer = generateRuntimeClass(fields, expression, packageName,returnTypeOfExprClass); JavaFileObject file = new JavaSourceFromString("Expression", writer.toString()); final Iterable<? extends JavaFileObject> sources = Arrays.asList(file); task = compiler.getTask(null, manager, diagnostics, null, null, sources); task.call(); return diagnostics; } /** * @param fields * object contains all fields name w.r.t default values. * @param expression * is a construct made up of fields, operators, and method * invocations * @param externalJarPath * is used to include custom classes. * @param packageName * contains all the imported classes. * @return a DiagnosticCollector of {@link JavaFileObject} objects which * contains all the compile time information . */ public static DiagnosticCollector<JavaFileObject> javaCompile(String fields, String expression, String externalJarPath, String packageName,String returnTypeOfExprClass) { diagnostics = new DiagnosticCollector<JavaFileObject>(); StringWriter writer = generateRuntimeClass(fields, expression, packageName,returnTypeOfExprClass); JavaFileObject file = new JavaSourceFromString("Expression", writer.toString()); final Iterable<? extends JavaFileObject> sources = Arrays.asList(file); if ((externalJarPath != null) && (!externalJarPath.isEmpty())) { String classpath = System.getProperty("java.class.path"); List<String> optionList = new ArrayList(); optionList.addAll(Arrays.asList(new String[] { "-classpath", externalJarPath })); task = compiler.getTask(null, null, diagnostics, optionList, null, sources); task.call(); return diagnostics; } throw new RuntimeException("Missing External Jar path"); } private static StringWriter generateRuntimeClass(String fields, String expression, String packageName, String returnType) { if (returnType == null || "".equals(returnType)) returnType = "Object"; StringWriter writer = new StringWriter(); writer.append(packageName); writer.append("class Expression {"); writer.append("public static " + returnType + " validate(){ try{"); writer.append(fields != null ? fields : ""); writer.append("return " + addOrNotSemiColon(expression) +"}catch(Exception e){throw new RuntimeException(e);}}"); writer.append("public static void main(String args[]) {"); writer.append("validate();"); writer.append("}"); writer.append("}"); return writer; } private static String addOrNotSemiColon(String expression){ if(expression.endsWith(";")) return expression; else return expression+";"; } // // static Iterable<JavaSourceFromString> getJavaSourceFromString(String code) { // final JavaSourceFromString jsfs; // jsfs = new JavaSourceFromString("code", code); // return new Iterable<JavaSourceFromString>() { // public Iterator<JavaSourceFromString> iterator() { // return new Iterator<JavaSourceFromString>() { // boolean isNext = true; // // public boolean hasNext() { // return isNext; // } // // public JavaSourceFromString next() { // if (!isNext) // throw new NoSuchElementException(); // isNext = false; // return jsfs; // } // // public void remove() { // throw new UnsupportedOperationException(); // } // }; // } // }; // } } class JavaSourceFromString extends SimpleJavaFileObject { final String code; JavaSourceFromString(String name, String code) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; } public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } }