1 package edu.umd.cs.findbugs.detect; 2 3 4 import edu.umd.cs.findbugs.*; 5 import edu.umd.cs.findbugs.ba.*; 6 import edu.umd.cs.findbugs.ba.ch.Subtypes; 7 import edu.umd.cs.findbugs.visitclass.PreorderVisitor; 8 import java.util.*; 9 import org.apache.bcel.Repository; 10 import org.apache.bcel.classfile.*; 11 12 public class ResolveAllReferences extends PreorderVisitor implements Detector { 13 14 private BugReporter bugReporter; 15 16 public ResolveAllReferences(BugReporter bugReporter) { 17 this.bugReporter = bugReporter; 18 19 } 20 21 Set<String > defined; 22 23 private void compute() { 24 if (defined == null) { 25 defined = new HashSet<String >(); 27 Subtypes subtypes = AnalysisContext.currentAnalysisContext() 28 .getSubtypes(); 29 Set<JavaClass> allClasses; 30 allClasses = subtypes.getAllClasses(); 31 for (JavaClass c : allClasses) 32 addAllDefinitions(c); 33 } 35 } 36 37 public void visitClassContext(ClassContext classContext) { 38 classContext.getJavaClass().accept(this); 39 40 } 41 42 public void report() { 43 } 44 45 public void addAllDefinitions(JavaClass obj) { 46 String className2 = obj.getClassName(); 47 48 defined.add(className2); 49 for (Method m : obj.getMethods()) 50 if (!m.isPrivate()) { 51 String name = getMemberName(obj, className2, m.getNameIndex(), 52 m.getSignatureIndex()); 53 defined.add(name); 54 } 55 for (Field f : obj.getFields()) 56 if (!f.isPrivate()) { 57 String name = getMemberName(obj, className2, f.getNameIndex(), f 58 .getSignatureIndex()); 59 defined.add(name); 60 } 61 } 62 63 private String getClassName(JavaClass c, int classIndex) { 64 String name = c.getConstantPool().getConstantString(classIndex, 65 CONSTANT_Class); 66 return Subtypes.extractClassName(name).replace('/','.'); 67 } 68 69 private String getMemberName(JavaClass c, String className, 70 int memberNameIndex, int signatureIndex) { 71 return className 72 + "." 73 + ((ConstantUtf8) c.getConstantPool().getConstant( 74 memberNameIndex, CONSTANT_Utf8)).getBytes() 75 + " : " 76 + ((ConstantUtf8) c.getConstantPool().getConstant( 77 signatureIndex, CONSTANT_Utf8)).getBytes(); 78 } 79 private String getMemberName(String className, 80 String memberName, String signature) { 81 return className.replace('/','.') 82 + "." 83 + memberName 84 + " : " 85 + signature; 86 } 87 private boolean find(JavaClass target, String name, String signature) throws ClassNotFoundException { 88 if (target == null) return false; 89 String ref = getMemberName(target.getClassName(), name, 90 signature); 91 if (defined.contains(ref)) return true; 92 if (find(target.getSuperClass(), name, signature)) return true; 93 for(JavaClass i : target.getInterfaces()) 94 if (find(i, name, signature)) return true; 95 return false; 96 } 97 @Override 98 public void visit(JavaClass obj) { 99 compute(); 100 ConstantPool cp = obj.getConstantPool(); 101 Constant[] constants = cp.getConstantPool(); 102 checkConstant: for (int i = 0; i < constants.length; i++) { 103 Constant co = constants[i]; 104 if (co instanceof ConstantDouble || co instanceof ConstantLong) 105 i++; 106 if (co instanceof ConstantClass) { 107 String ref = getClassName(obj, i); 108 if ((ref.startsWith("java") || ref.startsWith("org.w3c.dom")) && !defined.contains(ref)) 109 bugReporter.reportBug(new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY) 110 .addClass(obj).addString(ref)); 111 112 113 } else if (co instanceof ConstantFieldref) { 114 } else if (co instanceof ConstantCP) { 116 ConstantCP co2 = (ConstantCP) co; 117 String className = getClassName(obj, co2.getClassIndex()); 118 119 if (className.equals(obj.getClassName()) 121 || !defined.contains(className)) { 122 continue checkConstant; 124 } 125 ConstantNameAndType nt = (ConstantNameAndType) cp 126 .getConstant(co2.getNameAndTypeIndex()); 127 String name = ((ConstantUtf8) obj.getConstantPool().getConstant( 128 nt.getNameIndex(), CONSTANT_Utf8)).getBytes(); 129 String signature = ((ConstantUtf8) obj.getConstantPool().getConstant( 130 nt.getSignatureIndex(), CONSTANT_Utf8)).getBytes(); 131 132 133 try { 134 JavaClass target = Repository.lookupClass(className); 135 if (! find(target, name, signature)) 136 bugReporter.reportBug(new BugInstance(this, "VR_UNRESOLVABLE_REFERENCE", NORMAL_PRIORITY) 137 .addClass(obj).addString(getMemberName(target.getClassName(), name, 138 signature))); 139 140 } catch (ClassNotFoundException e) { 141 bugReporter.reportMissingClass(e); 142 } 143 } 144 145 } 146 } 147 148 } 149 | Popular Tags |