KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > SignatureConverter


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2003,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;
21
22 import org.apache.bcel.classfile.JavaClass;
23 import org.apache.bcel.classfile.Method;
24 import org.apache.bcel.generic.ConstantPoolGen;
25 import org.apache.bcel.generic.InvokeInstruction;
26 import org.apache.bcel.generic.MethodGen;
27
28 /**
29  * Convert part or all of a Java type signature into something
30  * closer to what types look like in the source code.
31  * Both field and method signatures may be processed by this class.
32  * For a field signature, just call parseNext() once.
33  * For a method signature, parseNext() must be called multiple times,
34  * and the parens around the arguments must be skipped manually
35  * (by calling the skip() method).
36  *
37  * @author David Hovemeyer
38  */

39
40 public class SignatureConverter {
41     private String JavaDoc signature;
42
43     /**
44      * Constructor.
45      *
46      * @param signature the field or method signature to convert
47      */

48     public SignatureConverter(String JavaDoc signature) {
49         this.signature = signature;
50     }
51
52     /**
53      * Get the first character of the remaining part of the signature.
54      */

55     public char getFirst() {
56         return signature.charAt(0);
57     }
58
59     /**
60      * Skip the first character of the remaining part of the signature.
61      */

62     public void skip() {
63         signature = signature.substring(1);
64     }
65
66     /**
67      * Parse a single type out of the signature, starting at the beginning
68      * of the remaining part of the signature. For example, if the first
69      * character of the remaining part is "I", then this method will return
70      * "int", and the "I" will be consumed. Arrays, reference types,
71      * and basic types are all handled.
72      *
73      * @return the parsed type string
74      */

75     public String JavaDoc parseNext() {
76         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
77
78         if (signature.startsWith("[")) {
79             int dimensions = 0;
80             do {
81                 ++dimensions;
82                 signature = signature.substring(1);
83             } while (signature.charAt(0) == '[');
84             result.append(parseNext());
85
86             while (dimensions-- > 0) {
87                 result.append("[]");
88             }
89         } else if (signature.startsWith("L")) {
90             int semi = signature.indexOf(';');
91             if (semi < 0)
92                 throw new IllegalStateException JavaDoc("missing semicolon in signature " + signature);
93             result.append(signature.substring(1, semi).replace('/', '.'));
94             signature = signature.substring(semi + 1);
95         } else {
96             switch (signature.charAt(0)) {
97             case 'B':
98                 result.append("byte");
99                 break;
100             case 'C':
101                 result.append("char");
102                 break;
103             case 'D':
104                 result.append("double");
105                 break;
106             case 'F':
107                 result.append("float");
108                 break;
109             case 'I':
110                 result.append("int");
111                 break;
112             case 'J':
113                 result.append("long");
114                 break;
115             case 'S':
116                 result.append("short");
117                 break;
118             case 'Z':
119                 result.append("boolean");
120                 break;
121             default:
122                 throw new IllegalStateException JavaDoc("bad signature " + signature);
123             }
124             skip();
125         }
126
127         return result.toString();
128     }
129
130     /**
131      * Convenience method for generating a method signature in
132      * human readable form.
133      *
134      * @param javaClass the class
135      * @param method the method
136      */

137     public static String JavaDoc convertMethodSignature(JavaClass javaClass, Method method) {
138         return convertMethodSignature(javaClass.getClassName(), method.getName(), method.getSignature());
139     }
140
141     /**
142      * Convenience method for generating a method signature in
143      * human readable form.
144      *
145      * @param methodGen the method to produce a method signature for
146      */

147     public static String JavaDoc convertMethodSignature(MethodGen methodGen) {
148         return convertMethodSignature(methodGen.getClassName(), methodGen.getName(), methodGen.getSignature());
149     }
150
151     /**
152      * Convenience method for generating a method signature in
153      * human readable form.
154      *
155      * @param inv an InvokeInstruction
156      * @param cpg the ConstantPoolGen for the class the instruction belongs to
157      */

158     public static String JavaDoc convertMethodSignature(InvokeInstruction inv, ConstantPoolGen cpg) {
159         return convertMethodSignature(inv.getClassName(cpg), inv.getName(cpg), inv.getSignature(cpg));
160     }
161
162     /**
163      * Convenience method for generating a method signature in
164      * human readable form.
165      *
166      * @param className name of the class containing the method
167      * @param methodName the name of the method
168      * @param methodSig the signature of the method
169      */

170     public static String JavaDoc convertMethodSignature(String JavaDoc className, String JavaDoc methodName, String JavaDoc methodSig) {
171         return convertMethodSignature(className, methodName, methodSig, "");
172     }
173
174     /**
175      * Convenience method for generating a method signature in
176      * human readable form.
177      *
178      * @param xmethod an XMethod
179      * @return the formatted version of that signature
180      */

181     public static String JavaDoc convertMethodSignature(XMethod xmethod) {
182         return convertMethodSignature(xmethod.getClassName(), xmethod.getName(), xmethod.getSignature());
183     }
184     
185     /**
186      * Convenience method for generating a method signature in
187      * human readable form.
188      *
189      * @param className name of the class containing the method
190      * @param methodName the name of the method
191      * @param methodSig the signature of the method
192      * @param pkgName the name of the package the method is in (used to shorten
193      * class names)
194      */

195     public static String JavaDoc convertMethodSignature(String JavaDoc className, String JavaDoc methodName, String JavaDoc methodSig, String JavaDoc pkgName) {
196         StringBuffer JavaDoc args = new StringBuffer JavaDoc();
197         SignatureConverter converter = new SignatureConverter(methodSig);
198
199         converter.skip();
200         args.append('(');
201
202         while (converter.getFirst() != ')') {
203             if (args.length() > 1)
204                 args.append(", ");
205             args.append(shorten(pkgName, converter.parseNext()));
206         }
207         converter.skip();
208         args.append(')');
209
210         // Ignore return type
211

212         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
213         result.append(className);
214         result.append('.');
215         result.append(methodName);
216         result.append(args.toString());
217
218         return result.toString();
219     }
220
221     /**
222      * Convenience method for converting a single signature component to
223      * human-readable form.
224      *
225      * @param signature the signature
226      */

227     public static String JavaDoc convert(String JavaDoc signature) {
228         return new SignatureConverter(signature).parseNext();
229     }
230
231     public static String JavaDoc shorten(String JavaDoc pkgName, String JavaDoc typeName) {
232         int index = typeName.lastIndexOf('.');
233         if (index >= 0) {
234             String JavaDoc otherPkg = typeName.substring(0, index);
235             if (otherPkg.equals(pkgName) || otherPkg.equals("java.lang"))
236                 typeName = typeName.substring(index + 1);
237         }
238         return typeName;
239     }
240 }
241
242 // vim:ts=4
243
Popular Tags