001 package org.shiftone.jrat.inject.bytecode.asm; 002 003 004 import org.objectweb.asm.ClassReader; 005 import org.objectweb.asm.ClassVisitor; 006 import org.objectweb.asm.ClassWriter; 007 import org.objectweb.asm.commons.SerialVersionUIDAdder; 008 import org.shiftone.jrat.inject.bytecode.InjectorStrategy; 009 import org.shiftone.jrat.inject.bytecode.TransformerOptions; 010 011 012 public class AsmInjectorStrategy implements InjectorStrategy { 013 014 public byte[] inject(byte[] rawClassData, TransformerOptions options) throws Exception { 015 016 ClassReader reader = new ClassReader(rawClassData); 017 ClassWriter classWriter = new ClassWriter(true); 018 ClassVisitor target = classWriter; 019 020 // target = new DebugClassVisitor(target); 021 ClassInitClassVisitor classInitClassVisitor = new ClassInitClassVisitor(target); 022 SerialVersionUIDAdder serialVersionUIDAdder = new SerialVersionUIDAdder(classInitClassVisitor); 023 InjectClassVisitor injectClassVisitor = new InjectClassVisitor(serialVersionUIDAdder); 024 MethodCriteriaClassVisitor criteriaClassVisitor = new MethodCriteriaClassVisitor(injectClassVisitor, 025 serialVersionUIDAdder); 026 ClassVisitor visitor = new IfInterfaceClassVisitor(target, criteriaClassVisitor); 027 028 criteriaClassVisitor.setCriteria(options.getCriteria()); 029 030 // * IfInterfaceClassVisitor delegates to either ClassWriter or 031 // InjectClassVisitor 032 // this causes interface classes to be skipped (not be processed) 033 // * InjectClassVisitor will column a proxy method for each method in 034 // the class 035 // it also adds a "jrat static init" method 036 // * SerialVersionUIDAdder will add a serialVersionUID method if it is 037 // missing 038 // most likely this will cause a static initializer to be added 039 // * ClassInitClassVisitor will add to the static initializer or add on 040 // the result is the class will have one that calls the jrat static init 041 // method 042 reader.accept(visitor, false); 043 044 return classWriter.toByteArray(); 045 } 046 047 048 public String toString() { 049 return "ASM"; 050 } 051 }