KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > generic > GenericSignatureParser


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2004, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.ba.generic;
21
22 import java.util.Iterator JavaDoc;
23 import java.util.NoSuchElementException JavaDoc;
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 /**
37  * A simple class to parse method signatures that include
38  * generic information. <p>
39  *
40  * Modified from edu.umd.cs.findbugs.ba.SignatureParser
41  *
42  * @author Nat Ayewah
43  */

44 public class GenericSignatureParser {
45     private class ParameterSignatureIterator implements Iterator JavaDoc<String JavaDoc> {
46         private int index = 1;
47
48         public boolean hasNext() {
49             return index < signature.length()
50                     && signature.charAt(index) != ')';
51         }
52
53         public String JavaDoc next() {
54             if (!hasNext()) throw new NoSuchElementException JavaDoc();
55             StringBuffer JavaDoc result = new StringBuffer JavaDoc();
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 '*': // wildcard
70
result.append(signature.charAt(index));
71                     ++index;
72                     break;
73                     
74                 case 'L':
75                 case 'T':
76                     String JavaDoc tmp = "";
77                     int startsemi = index;
78                     int semi = -1;
79                     // find the substring that ends with a semicolon and
80
// contains the same number of '<' and '>' braces
81
do {
82                         semi = signature.indexOf(';', startsemi + 1);
83                         if (semi < 0)
84                             throw new IllegalStateException JavaDoc("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 JavaDoc("Invalid method signature: " + signature);
103                 }
104             } while (!done);
105
106             return result.toString();
107         }
108
109         public void remove() {
110             throw new UnsupportedOperationException JavaDoc();
111         }
112     }
113
114     private final String JavaDoc signature;
115
116     /**
117      * Parses a generic method signature of the form:
118      * <code>(argument_signature)return_type_signature</code>
119      *
120      * @param signature the method signature to be parsed
121      */

122     public GenericSignatureParser(String JavaDoc signature) {
123         // XXX not currently handling Type parameters for class, interface or method definitions
124
if (signature.indexOf('(') < 0 || signature.indexOf(':') >= 0)
125             throw new IllegalArgumentException JavaDoc("Bad method signature: " + signature);
126         if (!signature.startsWith("("))
127             this.signature = signature.substring( signature.indexOf("(") );
128         else
129             this.signature = signature;
130     }
131
132     /**
133      * Get an Iterator over signatures of the method parameters.
134      *
135      * @return Iterator which returns the parameter type signatures in order
136      */

137     public Iterator JavaDoc<String JavaDoc> parameterSignatureIterator() {
138         return new ParameterSignatureIterator();
139     }
140     
141     /**
142      * Get the method return type signature.
143      *
144      * @return the method return type signature
145      */

146     public String JavaDoc getReturnTypeSignature() {
147         int endOfParams = signature.lastIndexOf(')');
148         if (endOfParams < 0)
149             throw new IllegalArgumentException JavaDoc("Bad method signature: " + signature);
150         return signature.substring(endOfParams + 1);
151     }
152     
153     /**
154      * Get the number of parameters in the signature.
155      *
156      * @return the number of parameters
157      */

158     public int getNumParameters() {
159         int count = 0;
160         for (Iterator JavaDoc<String JavaDoc> i = parameterSignatureIterator(); i.hasNext();) {
161             i.next();
162             ++count;
163         }
164         return count;
165     }
166     
167     /**
168      * Get the number of parameters passed to method invocation.
169      *
170      * @param inv
171      * @param cpg
172      * @return int number of parameters
173      */

174     public static int getNumParametersForInvocation(InvokeInstruction inv, ConstantPoolGen cpg) {
175         GenericSignatureParser sigParser = new GenericSignatureParser(inv.getSignature(cpg));
176         return sigParser.getNumParameters();
177     }
178
179     /**
180      * @param method
181      * @return an iterator over the parameters of the generic
182      * signature of method. Returns null if the
183      * generic signature cannot be parsed
184      */

185     public static @CheckForNull Iterator JavaDoc<String JavaDoc> getGenericSignatureIterator(Method target) {
186         try {
187             GenericSignatureParser parser = null;
188             String JavaDoc 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; // we've seen two inconsistent signatures
201
}
202                         continue;
203                     }
204                     
205                     genericSignature = sig.getSignature();
206                     if (compareSignatures(target.getSignature(), genericSignature))
207                         parser = new GenericSignatureParser( genericSignature );
208                 }
209             }
210             Iterator JavaDoc<String JavaDoc> iter = parser == null ? null :
211                 parser.parameterSignatureIterator();
212             return iter;
213         } catch (RuntimeException JavaDoc e) {} // degrade gracefully
214
return null;
215     }
216     
217     /**
218      * Compare a plain method signature to the a generic method Signature and
219      * return true if they match
220      */

221     public static boolean compareSignatures(
222             String JavaDoc plainSignature, String JavaDoc 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 JavaDoc[] 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 JavaDoc<String JavaDoc> i = parser.parameterSignatureIterator(); i.hasNext();){
242             String JavaDoc 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