use of act.app.util.EnvMatcher in project actframework by actframework.
the class AppClassLoader method asmEnhance.
private byte[] asmEnhance(String className, byte[] bytecode) {
if (!enhanceEligible(className))
return bytecode;
$.Var<ClassWriter> cw = $.var(null);
ByteCodeVisitor enhancer = Act.enhancerManager().appEnhancer(app, className, cw);
if (null == enhancer) {
return bytecode;
}
EnvMatcher matcher = new EnvMatcher();
matcher.setDownstream(enhancer);
cw.set(new ClassWriter(ClassWriter.COMPUTE_FRAMES));
enhancer.commitDownstream();
ClassReader r = new ClassReader(bytecode);
try {
r.accept(matcher, ClassReader.EXPAND_FRAMES);
} catch (EnvNotMatchException e) {
return bytecode;
} catch (AsmException e) {
logger.error(e, "error enhancing bytecode at %s", e.context());
throw ActErrorResult.enhancingError(e);
}
return cw.get().toByteArray();
}
use of act.app.util.EnvMatcher in project actframework by actframework.
the class AppClassLoader method scanByteCode.
/**
* This method implement a event listener based scan process:
* <ol>
* <li>First loop: through all cached bytecode. Chain all scanner's bytecode visitor</li>
* <li>Rest loops: through dependencies. Thus if some bytecode missed by a certain scanner
* due to the context is not established can be captured eventually</li>
* </ol>
*/
protected void scanByteCode(Iterable<String> classes, $.Function<String, byte[]> bytecodeProvider) {
logger.debug("start to scan bytecode ...");
final AppCodeScannerManager scannerManager = app().scannerManager();
Map<String, List<AppByteCodeScanner>> dependencies = new HashMap<>();
for (String className : classes) {
logger.debug("scanning %s ...", className);
dependencies.remove(className);
byte[] ba = bytecodeProvider.apply(className);
if (null == ba) {
logger.warn("Cannot find any bytecode for class: %s. You might have an empty Java source file for that.", className);
continue;
}
libClsCache.put(className, ba);
act.metric.Timer timer = metric.startTimer("act:classload:scan:bytecode:" + className);
List<ByteCodeVisitor> visitors = new ArrayList<>();
List<AppByteCodeScanner> scanners = new ArrayList<>();
for (AppByteCodeScanner scanner : scannerManager.byteCodeScanners()) {
if (scanner.start(className)) {
// LOGGER.trace("scanner %s added to the list", scanner.getClass().getName());
visitors.add(scanner.byteCodeVisitor());
scanners.add(scanner);
}
}
if (visitors.isEmpty()) {
continue;
}
ByteCodeVisitor theVisitor = ByteCodeVisitor.chain(visitors);
EnvMatcher matcher = new EnvMatcher();
matcher.setDownstream(theVisitor);
ClassReader cr = new ClassReader(ba);
try {
cr.accept(matcher, 0);
} catch (EnvNotMatchException e) {
continue;
} catch (AsmException e) {
Throwable t = e.getCause();
if (t instanceof ClassNotFoundException) {
continue;
} else {
logger.error(e, "Error scanning bytecode at %s", e.context());
ActErrorResult error = ActErrorResult.scanningError(e);
if (Act.isDev()) {
app.setBlockIssue(error);
} else {
throw error;
}
}
}
for (AppByteCodeScanner scanner : scanners) {
scanner.scanFinished(className);
Map<Class<? extends AppByteCodeScanner>, Set<String>> ss = scanner.dependencyClasses();
if (ss.isEmpty()) {
// LOGGER.trace("no dependencies found for %s by scanner %s", className, scanner);
continue;
}
for (Class<? extends AppByteCodeScanner> scannerClass : ss.keySet()) {
AppByteCodeScanner scannerA = scannerManager.byteCodeScannerByClass(scannerClass);
for (String dependencyClass : ss.get(scannerClass)) {
logger.trace("dependencies[%s] found for %s by scanner %s", dependencyClass, className, scannerA);
List<AppByteCodeScanner> l = dependencies.get(dependencyClass);
if (null == l) {
l = new ArrayList<>();
dependencies.put(dependencyClass, l);
}
if (!l.contains(scanner))
l.add(scannerA);
}
}
}
timer.stop();
}
// loop through dependencies until it's all processed
while (!dependencies.isEmpty()) {
String className = dependencies.keySet().iterator().next();
act.metric.Timer timer = metric.startTimer("act:classload:scan:bytecode:" + className);
List<AppByteCodeScanner> scanners = dependencies.remove(className);
List<ByteCodeVisitor> visitors = new ArrayList<>();
for (AppByteCodeScanner scanner : scanners) {
scanner.start(className);
visitors.add(scanner.byteCodeVisitor());
}
ByteCodeVisitor theVisitor = ByteCodeVisitor.chain(visitors);
byte[] bytes = bytecodeProvider.apply(className);
libClsCache.put(className, bytes);
ClassReader cr = new ClassReader(bytes);
try {
cr.accept(theVisitor, 0);
} catch (AsmException e) {
throw ActErrorResult.of(e);
}
for (AppByteCodeScanner scanner : scanners) {
scanner.scanFinished(className);
Map<Class<? extends AppByteCodeScanner>, Set<String>> ss = scanner.dependencyClasses();
if (ss.isEmpty()) {
logger.trace("no dependencies found for %s by scanner %s", className, scanner);
continue;
}
for (Class<? extends AppByteCodeScanner> scannerClass : ss.keySet()) {
AppByteCodeScanner scannerA = scannerManager.byteCodeScannerByClass(scannerClass);
for (String dependencyClass : ss.get(scannerClass)) {
logger.trace("dependencies[%s] found for %s by scanner %s", dependencyClass, className, scannerA);
List<AppByteCodeScanner> l = dependencies.get(dependencyClass);
if (null == l) {
l = new ArrayList<>();
dependencies.put(dependencyClass, l);
}
if (!l.contains(scanner))
l.add(scannerA);
}
}
}
timer.stop();
}
}
Aggregations