1 package net.sourceforge.importscrubber; 2 3 import java.io.*; 4 import java.util.*; 5 import org.apache.bcel.classfile.ClassParser; 6 import org.apache.bcel.classfile.Constant; 7 import org.apache.bcel.classfile.ConstantClass; 8 import org.apache.bcel.classfile.ConstantPool; 9 import org.apache.bcel.classfile.ConstantString; 10 import org.apache.bcel.classfile.ConstantUtf8; 11 import org.apache.bcel.classfile.DescendingVisitor; 12 import org.apache.bcel.classfile.EmptyVisitor; 13 import org.apache.bcel.classfile.JavaClass; 14 15 18 public class ClassParserWrapper 19 { 20 private static final char[] SIGNATURE_CHARS = new char[] {'L', 'Z', '(', ')', '[', ']', 'I', 'C', 'D'}; 21 private static final String STD_PREAMBLE = "\"CONSTANT_Utf8[1](\""; 22 23 private static class ClassRefVisitor extends EmptyVisitor 24 { 25 private IReferenceFoundListener listener; 26 private ConstantPool constantPool; 27 private List excludedIndexes; 28 29 public ClassRefVisitor(ConstantPool constantPool, IReferenceFoundListener aListener, List excludedIndexes) 30 { 31 this.listener = aListener; 32 this.constantPool = constantPool; 33 this.excludedIndexes = excludedIndexes; 34 } 35 36 public void visitConstantClass(ConstantClass obj) 37 { 38 String current = constantPool.constantToString(obj); 39 if (current.indexOf(';') != -1) { 40 current = cleanSignature(current); 41 } 42 if (current.indexOf('(') != -1 || current.indexOf(')') != -1 || inJavaLang(current)) { 43 return; 44 } 45 listener.referenceFound(current); 46 } 47 48 public void visitConstantUtf8(ConstantUtf8 obj) 49 { 50 for(Iterator iter = excludedIndexes.iterator(); iter.hasNext();) { 52 Constant constant = constantPool.getConstant(((Integer )iter.next()).intValue()); 53 if(constant.equals(obj)) { 54 return; 55 } 56 } 57 58 if (obj.toString().indexOf('$') != -1) { 59 String current = removePreamble(obj).replace('$', '.'); 60 if (current.startsWith("class.")) { 61 current = current.substring("class.".length()); 62 } 63 if (current.length() == 0 || current.startsWith("array") || current.startsWith("access") || current.startsWith("this") || current.startsWith(".") || current.startsWith("constructor") || current.startsWith("L") || current.endsWith(".0") || current.endsWith(".1") || current.endsWith(".2") || current.endsWith(".3") || current.endsWith(".4") || current.endsWith(".5")) { 64 return; 65 } 66 for (int i=0; i<SIGNATURE_CHARS.length; i++) { 67 if (current.charAt(0) == SIGNATURE_CHARS[i]) { 68 return; 69 } 70 } 71 if (isGoodReference(current)) { 72 listener.referenceFound(current); 73 } 74 return; 75 } 76 77 if (obj.toString().indexOf('/') == -1) { 78 return; 79 } 80 81 String name = removePreamble(obj); 82 83 if (name.startsWith(".")) { 84 return; 85 } 86 87 if (name.indexOf(';') != -1) { 88 StringTokenizer st = new StringTokenizer(name, ";"); 89 while (st.hasMoreTokens()) { 90 String current = dropType(st.nextToken()); 91 if (isGoodReference(current)) { 92 listener.referenceFound(current); 93 } 94 } 95 return; 96 } 97 if (isGoodReference(name)) { 98 listener.referenceFound(name); 99 } 100 } 101 102 private boolean isGoodReference(String in) 103 { 104 if (in == null || in.length() == 0) { 105 return false; 106 } 107 if (inJavaLang(in)) { 108 return false; 109 } 110 if (in.endsWith(".")) { 111 return false; 112 } 113 if (in.indexOf(' ') != -1 || in.indexOf('\'') != -1 || in.indexOf('*') != -1 || in.indexOf(':') != -1 || in.indexOf('(') != -1 || in.indexOf(')') != -1 || in.indexOf('<') != -1 || in.indexOf('>') != -1) { 114 return false; 115 } 116 if (Character.isUpperCase(in.charAt(0))) { 117 return false; 118 } 119 if (in.startsWith("val.")) { 120 return false; 121 } 122 return true; 123 } 124 125 private String cleanSignature(String in) 126 { 127 return dropType(slashToDot(dropSemicolon(in))); 128 } 129 private String dropSemicolon(String in) 130 { 131 return in.substring(0, in.length()-1); 132 } 133 134 private String slashToDot(String in) 135 { 136 return in.replace('/', '.'); 137 } 138 private String dropType(String in) 139 { 140 boolean foundSigChar = true; 141 while (foundSigChar) { 142 foundSigChar = false; 143 if (in.length() == 0) { 144 return in; 145 } 146 char current = in.charAt(0); 147 for (int i=0; i<SIGNATURE_CHARS.length;i++) { 148 if (current == SIGNATURE_CHARS[i]) { 149 in = in.substring(1); 150 foundSigChar = true; 151 break; 152 } 153 } 154 } 155 return in; 156 } 157 158 private String removePreamble(Constant in) 159 { 160 return in.toString().substring(STD_PREAMBLE.length()-1,in.toString().length()-2).replace('/', '.'); 161 } 162 163 private boolean inJavaLang(String in) 164 { 165 return(in.startsWith("java.lang") && in.indexOf("java.lang.reflect") == -1 && in.indexOf("java.lang.ref") == -1); 166 } 167 } 168 169 public static void parse(File file, IReferenceFoundListener aListener) throws IOException, FileNotFoundException 170 { 171 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 172 ClassParser parser = new ClassParser(bis, "hello"); 173 JavaClass clazz = parser.parse(); 174 ConstantPool pool = clazz.getConstantPool(); 175 176 List excluded = new ArrayList(); 177 for (int i=0; i< pool.getLength(); i++) { 178 if(pool.getConstant(i) instanceof ConstantString) { 179 excluded.add(new Integer (((ConstantString)pool.getConstant(i)).getStringIndex())); 180 } 181 } 182 bis.close(); 183 ClassRefVisitor visitor = new ClassRefVisitor(pool, aListener,excluded); 184 DescendingVisitor vehicle = new DescendingVisitor(clazz, visitor); 185 vehicle.visit(); 186 } 187 188 public static void main(String [] args) 189 { 190 try { 191 parse(new File("d:\\data\\importscrubber\\etc\\Hello.class"), new PrintListener()); 192 } catch (Exception e) { 195 e.printStackTrace(); 196 } 197 } 198 199 } 200 201 | Popular Tags |