1 19 20 package edu.umd.cs.findbugs.ba.generic; 21 22 import java.util.Iterator ; 23 import java.util.NoSuchElementException ; 24 25 import org.apache.bcel.classfile.Attribute; 26 import org.apache.bcel.classfile.FieldOrMethod; 27 import org.apache.bcel.classfile.Method; 28 import org.apache.bcel.classfile.Signature; 29 import org.apache.bcel.generic.ConstantPoolGen; 30 import org.apache.bcel.generic.InvokeInstruction; 31 import org.apache.bcel.generic.ObjectType; 32 import org.apache.bcel.generic.Type; 33 34 import edu.umd.cs.findbugs.annotations.CheckForNull; 35 36 44 public class GenericSignatureParser { 45 private class ParameterSignatureIterator implements Iterator <String > { 46 private int index = 1; 47 48 public boolean hasNext() { 49 return index < signature.length() 50 && signature.charAt(index) != ')'; 51 } 52 53 public String next() { 54 if (!hasNext()) throw new NoSuchElementException (); 55 StringBuffer result = new StringBuffer (); 56 boolean done; 57 do { 58 done = true; 59 int ch = signature.charAt(index); 60 switch (ch) { 61 case 'B': 62 case 'C': 63 case 'D': 64 case 'F': 65 case 'I': 66 case 'J': 67 case 'S': 68 case 'Z': 69 case '*': result.append(signature.charAt(index)); 71 ++index; 72 break; 73 74 case 'L': 75 case 'T': 76 String tmp = ""; 77 int startsemi = index; 78 int semi = -1; 79 do { 82 semi = signature.indexOf(';', startsemi + 1); 83 if (semi < 0) 84 throw new IllegalStateException ("Invalid method signature: " + signature); 85 tmp = signature.substring(index, semi + 1); 86 startsemi = semi; 87 } while(tmp.split("<").length != tmp.split(">").length); 88 result.append(tmp); 89 index = semi + 1; 90 break; 91 92 case '[': 93 case '+': 94 case '-': 95 result.append(signature.charAt(index)); 96 ++index; 97 done = false; 98 break; 99 100 case 'V': 101 default: 102 throw new IllegalStateException ("Invalid method signature: " + signature); 103 } 104 } while (!done); 105 106 return result.toString(); 107 } 108 109 public void remove() { 110 throw new UnsupportedOperationException (); 111 } 112 } 113 114 private final String signature; 115 116 122 public GenericSignatureParser(String signature) { 123 if (signature.indexOf('(') < 0 || signature.indexOf(':') >= 0) 125 throw new IllegalArgumentException ("Bad method signature: " + signature); 126 if (!signature.startsWith("(")) 127 this.signature = signature.substring( signature.indexOf("(") ); 128 else 129 this.signature = signature; 130 } 131 132 137 public Iterator <String > parameterSignatureIterator() { 138 return new ParameterSignatureIterator(); 139 } 140 141 146 public String getReturnTypeSignature() { 147 int endOfParams = signature.lastIndexOf(')'); 148 if (endOfParams < 0) 149 throw new IllegalArgumentException ("Bad method signature: " + signature); 150 return signature.substring(endOfParams + 1); 151 } 152 153 158 public int getNumParameters() { 159 int count = 0; 160 for (Iterator <String > i = parameterSignatureIterator(); i.hasNext();) { 161 i.next(); 162 ++count; 163 } 164 return count; 165 } 166 167 174 public static int getNumParametersForInvocation(InvokeInstruction inv, ConstantPoolGen cpg) { 175 GenericSignatureParser sigParser = new GenericSignatureParser(inv.getSignature(cpg)); 176 return sigParser.getNumParameters(); 177 } 178 179 185 public static @CheckForNull Iterator <String > getGenericSignatureIterator(Method target) { 186 try { 187 GenericSignatureParser parser = null; 188 String genericSignature = null; 189 for (Attribute a : target.getAttributes()) { 190 if (a instanceof Signature) { 191 192 Signature sig = (Signature) a; 193 if ( genericSignature != null) { 194 if (!genericSignature.equals(sig.getSignature()) ) { 195 if (false) { 196 System.out.println("Inconsistent signatures: " ); 197 System.out.println(genericSignature); 198 System.out.println(sig.getSignature()); 199 } 200 return null; } 202 continue; 203 } 204 205 genericSignature = sig.getSignature(); 206 if (compareSignatures(target.getSignature(), genericSignature)) 207 parser = new GenericSignatureParser( genericSignature ); 208 } 209 } 210 Iterator <String > iter = parser == null ? null : 211 parser.parameterSignatureIterator(); 212 return iter; 213 } catch (RuntimeException e) {} return null; 215 } 216 217 221 public static boolean compareSignatures( 222 String plainSignature, String genericSignature) { 223 GenericSignatureParser plainParser = 224 new GenericSignatureParser( plainSignature ); 225 GenericSignatureParser genericParser = 226 new GenericSignatureParser( genericSignature ); 227 228 if (plainParser.getNumParameters() != genericParser.getNumParameters()) 229 return false; 230 231 return true; 232 } 233 234 235 public static void main(String [] args) { 236 if (args.length != 1) { 237 System.err.println("Usage: " + GenericSignatureParser.class.getName() + " '<method signature>'"); 238 System.exit(1); 239 } 240 GenericSignatureParser parser = new GenericSignatureParser(args[0]); 241 for (Iterator <String > i = parser.parameterSignatureIterator(); i.hasNext();){ 242 String s = i.next(); 243 System.out.println(s); 244 Type t = GenericUtilities.getType(s); 245 System.out.println("-~- " + t); 246 if (t instanceof ObjectType) 247 System.out.println("-~- " + ( (ObjectType) t).toString()); 248 System.out.println("-~- " + t.getClass()); 249 } 250 System.out.println(parser.getNumParameters() + " parameter(s)"); 251 252 253 } 254 } 255 256 | Popular Tags |