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 }