1 19 20 package edu.umd.cs.findbugs.ba.bcp; 21 22 import java.util.regex.Pattern ; 23 24 import org.apache.bcel.Constants; 25 import org.apache.bcel.generic.ConstantPoolGen; 26 import org.apache.bcel.generic.Instruction; 27 import org.apache.bcel.generic.InstructionHandle; 28 import org.apache.bcel.generic.InvokeInstruction; 29 30 import edu.umd.cs.findbugs.annotations.Nullable; 31 import edu.umd.cs.findbugs.ba.AnalysisContext; 32 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 33 import edu.umd.cs.findbugs.ba.Edge; 34 import edu.umd.cs.findbugs.ba.Hierarchy; 35 import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback; 36 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 37 38 74 public class Invoke extends PatternElement { 75 76 79 public static final int INSTANCE = 1; 80 81 84 public static final int STATIC = 2; 85 86 89 public static final int CONSTRUCTOR = 4; 90 91 94 public static final int ORDINARY_METHOD = INSTANCE | STATIC; 95 96 99 public static final int ANY = INSTANCE | STATIC | CONSTRUCTOR; 100 101 private interface StringMatcher { 102 public boolean match(String s); 103 } 104 105 private static class ExactStringMatcher implements StringMatcher { 106 private String value; 107 108 public ExactStringMatcher(String value) { 109 this.value = value; 110 } 111 112 public boolean match(String s) { 113 return s.equals(value); 114 } 115 } 116 117 private static class RegexpStringMatcher implements StringMatcher { 118 private Pattern pattern; 119 120 public RegexpStringMatcher(String re) { 121 pattern = Pattern.compile(re); 122 } 123 124 public boolean match(String s) { 125 return pattern.matcher(s).matches(); 126 } 127 } 128 129 private static class SubclassMatcher implements StringMatcher { 130 private String className; 131 132 public SubclassMatcher(String className) { 133 this.className = className; 134 } 135 136 public boolean match(String s) { 137 try { 138 return Hierarchy.isSubtype(s, className); 139 } catch (ClassNotFoundException e) { 140 AnalysisContext.reportMissingClass(e); 141 return false; 142 } 143 } 144 } 145 146 private final StringMatcher classNameMatcher; 147 private final StringMatcher methodNameMatcher; 148 private final StringMatcher methodSigMatcher; 149 private final int mode; 150 151 160 public Invoke(String className, String methodName, String methodSig, int mode, 161 @Nullable RepositoryLookupFailureCallback lookupFailureCallback) { 162 this.classNameMatcher = createClassMatcher(className); 163 this.methodNameMatcher = createMatcher(methodName); 164 this.methodSigMatcher = createMatcher(methodSig); 165 this.mode = mode; 166 } 167 168 private StringMatcher createClassMatcher(String s) { 169 return s.startsWith("+") 170 ? new SubclassMatcher(s.substring(1)) 171 : createMatcher(s); 172 } 173 174 private StringMatcher createMatcher(String s) { 175 return s.startsWith("/") 176 ? (StringMatcher) new RegexpStringMatcher(s.substring(1)) 177 : (StringMatcher) new ExactStringMatcher(s); 178 } 179 180 @Override 181 public MatchResult match(InstructionHandle handle, ConstantPoolGen cpg, 182 ValueNumberFrame before, ValueNumberFrame after, BindingSet bindingSet) throws DataflowAnalysisException { 183 184 Instruction ins = handle.getInstruction(); 186 if (!(ins instanceof InvokeInstruction)) 187 return null; 188 InvokeInstruction inv = (InvokeInstruction) ins; 189 190 String methodName = inv.getMethodName(cpg); 191 boolean isStatic = inv.getOpcode() == Constants.INVOKESTATIC; 192 boolean isCtor = methodName.equals("<init>"); 193 194 int actualMode = 0; 195 196 if (isStatic) actualMode |= STATIC; 197 if (isCtor) actualMode |= CONSTRUCTOR; 198 if (!isStatic && !isCtor) actualMode |= INSTANCE; 199 200 if ((actualMode & mode) == 0) 202 return null; 203 204 if (!methodNameMatcher.match(methodName) || 206 !methodSigMatcher.match(inv.getSignature(cpg)) || 207 !classNameMatcher.match(inv.getClassName(cpg))) 208 return null; 209 210 return new MatchResult(this, bindingSet); 212 213 } 214 215 @Override 216 public boolean acceptBranch(Edge edge, InstructionHandle source) { 217 return true; 218 } 219 220 @Override 221 public int minOccur() { 222 return 1; 223 } 224 225 @Override 226 public int maxOccur() { 227 return 1; 228 } 229 } 230 231 | Popular Tags |