package org.ovirt.engine.ui.gwtaop;
import java.util.regex.Pattern;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.ControlFlowAnalyzer;
/**
* Advises GWT {@linkplain ControlFlowAnalyzer live code analyzer} to ensure that
* given Java classes, as defined by <code>{@value GWT_DONTPRUNE}</code> system
* property, are always treated as live code and never pruned from the GWT-generated
* JavaScript code.
*/
@Aspect
public class DontPrune {
/**
* The name of the system property holding a regular expression that indicates
* which types (based on their {@linkplain Class#getName binary name}) should
* not be pruned.
*/
private static final String GWT_DONTPRUNE = "gwt.dontPrune";
/**
* This pointcut captures the execution of the constructor of the liveness analyzer.
*/
@Pointcut("target(analyzer) && " +
"args(program) && " +
"execution(public com.google.gwt.dev.jjs.impl.ControlFlowAnalyzer.new(com.google.gwt.dev.jjs.ast.JProgram))")
public void createLivenessAnalyzer(ControlFlowAnalyzer analyzer, JProgram program) {
}
/**
* Right after constructing the liveness analyzer, make sure that all types
* matched by the regular expression are marked as if they were referenced
* by the GWT application code.
*/
@After("createLivenessAnalyzer(analyzer, program)")
public void afterCreateLivenessAnalyzer(ControlFlowAnalyzer analyzer, JProgram program) {
// Get the regular expression and warn the user if it's empty:
String dontPruneRe = System.getProperty(GWT_DONTPRUNE);
if (dontPruneRe == null) {
String error = "The system property '" + GWT_DONTPRUNE
+ "' that specifies the types not to be pruned wasn't set!";
System.err.println(error);
throw new RuntimeException(error);
}
// Compile the regular expression:
Pattern dontPrunePattern = Pattern.compile(dontPruneRe);
// Scan all the types and make sure that the ones matching the given regular
// expression are not pruned:
program.getDeclaredTypes().stream()
.filter(type -> dontPrunePattern.matcher(type.getName()).matches())
.forEach(type -> {
// Note: calling "analyzer.traverseFromInstantiationOf(type)"
// may cause GWT compiler to crash on NPE; don't use that method:
analyzer.traverseFromReferenceTo(type);
// Make sure that all methods of the given type are not pruned:
for (JMethod method : type.getMethods()) {
analyzer.traverseFrom(method);
}
});
}
}