package sample;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.StringLiteral;
public class ASTManuplationTest {
public static void main(String[] args) throws IOException {
String source =
"public class HelloWorld {"
+ " public static void main(String[] args) {"
// Insert the following statement.
// System.out.println("Hello, World");
+ " }"
+ "}"
;
ASTParser parser = ASTParser.newParser(AST.JLS8);
parser.setSource(source.toCharArray());
parser.setKind(ASTParser.K_COMPILATION_UNIT);
CompilationUnit unit = (CompilationUnit)parser.createAST(new NullProgressMonitor());
unit.accept(new ASTVisitor() {
@SuppressWarnings("unchecked")
public boolean visit(MethodDeclaration node) {
AST ast = node.getAST();
MethodInvocation methodInvocation = ast.newMethodInvocation();
// System.out.println("Hello, World")
QualifiedName qName =
ast.newQualifiedName(
ast.newSimpleName("System"),
ast.newSimpleName("out"));
methodInvocation.setExpression(qName);
methodInvocation.setName(ast.newSimpleName("println"));
StringLiteral literal = ast.newStringLiteral();
literal.setLiteralValue("Hello, World");
methodInvocation.arguments().add(literal);
// Append the statement
node.getBody().statements().add(ast.newExpressionStatement(methodInvocation));
return super.visit(node);
}
});
System.out.println("AST Manuplation Result");
System.out.println("--------------------------------------");
System.out.println(unit.toString());
if (compile(unit.toString())) {
execute();
}
}
static boolean compile(String code) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
String[] compileOptions = new String[] {"-d", "bin"} ;
Iterable<String> compilationOptionss = Arrays.asList(compileOptions);
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(new JavaSourceFromString("HelloWorld", code));
JavaCompiler.CompilationTask task = compiler.getTask(
null,
null,
diagnostics,
compilationOptionss,
null,
compilationUnits);
boolean success = task.call();
System.out.println("Compile... " + (success ? "success": "fail"));
return success;
}
static void execute() {
System.out.println("\nLoad and execute the compiled class...");
System.out.println("--------------------------------------");
try {
Class<?> klass = Class.forName("HelloWorld");
Method method = klass.getMethod("main", String[].class);
method.invoke(null, new Object[] { null });
} catch (ClassCastException
| ClassNotFoundException
| IllegalAccessException
| NoSuchMethodException
| SecurityException
| IllegalArgumentException
| InvocationTargetException e) {
new RuntimeException(e);
}
}
static 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;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}