001 package org.shiftone.jrat.inject.bytecode.asm;
002
003
004 import org.objectweb.asm.*;
005 import org.shiftone.jrat.core.criteria.MethodCriteria;
006 import org.shiftone.jrat.util.log.Logger;
007
008
009 /**
010 * @author jeff@shiftone.org (Jeff Drost)
011 */
012 public class MethodCriteriaClassVisitor implements ClassVisitor {
013
014 private static final Logger LOG = Logger.getLogger(MethodCriteriaClassVisitor.class);
015 private final ClassVisitor injector;
016 private final ClassVisitor bypass;
017 private MethodCriteria criteria;
018 private String className;
019 private ClassVisitor defaultClassVisitor;
020
021 public MethodCriteriaClassVisitor(ClassVisitor injector, ClassVisitor bypass) {
022 this.injector = injector;
023 this.bypass = bypass;
024 }
025
026
027 public void setCriteria(MethodCriteria criteria) {
028 this.criteria = criteria;
029 }
030
031
032 /**
033 * when this method is called MethodCriteria.isMatch(className) is checked
034 * to see if any injection is necessary. If not, then the default visitor is
035 * set to bypass the injection process.
036 */
037 public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
038
039 className = name.replace('/', '.');
040
041 if (criteria.isMatch(className, access)) {
042 defaultClassVisitor = injector;
043
044 LOG.debug("not filtering class " + className);
045 } else {
046 defaultClassVisitor = bypass;
047 }
048
049 defaultClassVisitor.visit(version, access, name, signature, superName, interfaces);
050 }
051
052
053 /**
054 * when this method is called MethodCriteria.isMatch(className, methodName,
055 * ...) is checked to see if any injection is necessary for this method. If
056 * not, then the bypass visitor is used. Otherwise, the default visitor is
057 * used (which was set in the class visit method).
058 */
059 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
060
061 if (criteria.isMatch(className, name, desc, access)) {
062 return defaultClassVisitor.visitMethod(access, name, desc, signature, exceptions);
063 } else {
064 return bypass.visitMethod(access, name, desc, signature, exceptions);
065 }
066 }
067
068
069 public void visitSource(String source, String debug) {
070 defaultClassVisitor.visitSource(source, debug);
071 }
072
073
074 public void visitOuterClass(String owner, String name, String desc) {
075 defaultClassVisitor.visitOuterClass(owner, name, desc);
076 }
077
078
079 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
080 return defaultClassVisitor.visitAnnotation(desc, visible);
081 }
082
083
084 public void visitAttribute(Attribute attr) {
085 defaultClassVisitor.visitAttribute(attr);
086 }
087
088
089 public void visitInnerClass(String name, String outerName, String innerName, int access) {
090 defaultClassVisitor.visitInnerClass(name, outerName, innerName, access);
091 }
092
093
094 public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
095 return defaultClassVisitor.visitField(access, name, desc, signature, value);
096 }
097
098
099 public void visitEnd() {
100
101 defaultClassVisitor.visitEnd();
102
103 defaultClassVisitor = null;
104 className = null;
105 }
106 }