rlm@10
|
1 /***
|
rlm@10
|
2 * ASM: a very small and fast Java bytecode manipulation framework
|
rlm@10
|
3 * Copyright (c) 2000-2005 INRIA, France Telecom
|
rlm@10
|
4 * All rights reserved.
|
rlm@10
|
5 *
|
rlm@10
|
6 * Redistribution and use in source and binary forms, with or without
|
rlm@10
|
7 * modification, are permitted provided that the following conditions
|
rlm@10
|
8 * are met:
|
rlm@10
|
9 * 1. Redistributions of source code must retain the above copyright
|
rlm@10
|
10 * notice, this list of conditions and the following disclaimer.
|
rlm@10
|
11 * 2. Redistributions in binary form must reproduce the above copyright
|
rlm@10
|
12 * notice, this list of conditions and the following disclaimer in the
|
rlm@10
|
13 * documentation and/or other materials provided with the distribution.
|
rlm@10
|
14 * 3. Neither the name of the copyright holders nor the names of its
|
rlm@10
|
15 * contributors may be used to endorse or promote products derived from
|
rlm@10
|
16 * this software without specific prior written permission.
|
rlm@10
|
17 *
|
rlm@10
|
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
rlm@10
|
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
rlm@10
|
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
rlm@10
|
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
rlm@10
|
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
rlm@10
|
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
rlm@10
|
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
rlm@10
|
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
rlm@10
|
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
rlm@10
|
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
rlm@10
|
28 * THE POSSIBILITY OF SUCH DAMAGE.
|
rlm@10
|
29 */
|
rlm@10
|
30 package clojure.asm.commons;
|
rlm@10
|
31
|
rlm@10
|
32 import java.util.HashMap;
|
rlm@10
|
33 import java.util.Map;
|
rlm@10
|
34
|
rlm@10
|
35 import clojure.asm.Type;
|
rlm@10
|
36
|
rlm@10
|
37 /**
|
rlm@10
|
38 * A named method descriptor.
|
rlm@10
|
39 *
|
rlm@10
|
40 * @author Juozas Baliuka
|
rlm@10
|
41 * @author Chris Nokleberg
|
rlm@10
|
42 * @author Eric Bruneton
|
rlm@10
|
43 */
|
rlm@10
|
44 public class Method{
|
rlm@10
|
45
|
rlm@10
|
46 /**
|
rlm@10
|
47 * The method name.
|
rlm@10
|
48 */
|
rlm@10
|
49 private final String name;
|
rlm@10
|
50
|
rlm@10
|
51 /**
|
rlm@10
|
52 * The method descriptor.
|
rlm@10
|
53 */
|
rlm@10
|
54 private final String desc;
|
rlm@10
|
55
|
rlm@10
|
56 /**
|
rlm@10
|
57 * Maps primitive Java type names to their descriptors.
|
rlm@10
|
58 */
|
rlm@10
|
59 private final static Map DESCRIPTORS;
|
rlm@10
|
60
|
rlm@10
|
61 static
|
rlm@10
|
62 {
|
rlm@10
|
63 DESCRIPTORS = new HashMap();
|
rlm@10
|
64 DESCRIPTORS.put("void", "V");
|
rlm@10
|
65 DESCRIPTORS.put("byte", "B");
|
rlm@10
|
66 DESCRIPTORS.put("char", "C");
|
rlm@10
|
67 DESCRIPTORS.put("double", "D");
|
rlm@10
|
68 DESCRIPTORS.put("float", "F");
|
rlm@10
|
69 DESCRIPTORS.put("int", "I");
|
rlm@10
|
70 DESCRIPTORS.put("long", "J");
|
rlm@10
|
71 DESCRIPTORS.put("short", "S");
|
rlm@10
|
72 DESCRIPTORS.put("boolean", "Z");
|
rlm@10
|
73 }
|
rlm@10
|
74
|
rlm@10
|
75 /**
|
rlm@10
|
76 * Creates a new {@link Method}.
|
rlm@10
|
77 *
|
rlm@10
|
78 * @param name the method's name.
|
rlm@10
|
79 * @param desc the method's descriptor.
|
rlm@10
|
80 */
|
rlm@10
|
81 public Method(final String name, final String desc){
|
rlm@10
|
82 this.name = name;
|
rlm@10
|
83 this.desc = desc;
|
rlm@10
|
84 }
|
rlm@10
|
85
|
rlm@10
|
86 /**
|
rlm@10
|
87 * Creates a new {@link Method}.
|
rlm@10
|
88 *
|
rlm@10
|
89 * @param name the method's name.
|
rlm@10
|
90 * @param returnType the method's return type.
|
rlm@10
|
91 * @param argumentTypes the method's argument types.
|
rlm@10
|
92 */
|
rlm@10
|
93 public Method(
|
rlm@10
|
94 final String name,
|
rlm@10
|
95 final Type returnType,
|
rlm@10
|
96 final Type[] argumentTypes){
|
rlm@10
|
97 this(name, Type.getMethodDescriptor(returnType, argumentTypes));
|
rlm@10
|
98 }
|
rlm@10
|
99
|
rlm@10
|
100 /**
|
rlm@10
|
101 * Returns a {@link Method} corresponding to the given Java method
|
rlm@10
|
102 * declaration.
|
rlm@10
|
103 *
|
rlm@10
|
104 * @param method a Java method declaration, without argument names, of the
|
rlm@10
|
105 * form "returnType name (argumentType1, ... argumentTypeN)", where
|
rlm@10
|
106 * the types are in plain Java (e.g. "int", "float",
|
rlm@10
|
107 * "java.util.List", ...). Classes of the java.lang package can be
|
rlm@10
|
108 * specified by their unqualified name; all other classes names must
|
rlm@10
|
109 * be fully qualified.
|
rlm@10
|
110 * @return a {@link Method} corresponding to the given Java method
|
rlm@10
|
111 * declaration.
|
rlm@10
|
112 * @throws IllegalArgumentException if <code>method</code> could not get
|
rlm@10
|
113 * parsed.
|
rlm@10
|
114 */
|
rlm@10
|
115 public static Method getMethod(final String method)
|
rlm@10
|
116 throws IllegalArgumentException{
|
rlm@10
|
117 return getMethod(method, false);
|
rlm@10
|
118 }
|
rlm@10
|
119
|
rlm@10
|
120 /**
|
rlm@10
|
121 * Returns a {@link Method} corresponding to the given Java method
|
rlm@10
|
122 * declaration.
|
rlm@10
|
123 *
|
rlm@10
|
124 * @param method a Java method declaration, without argument names, of the
|
rlm@10
|
125 * form "returnType name (argumentType1, ... argumentTypeN)", where
|
rlm@10
|
126 * the types are in plain Java (e.g. "int", "float",
|
rlm@10
|
127 * "java.util.List", ...). Classes of the java.lang package may be
|
rlm@10
|
128 * specified by their unqualified name, depending on the
|
rlm@10
|
129 * defaultPackage argument; all other classes names must be fully
|
rlm@10
|
130 * qualified.
|
rlm@10
|
131 * @param defaultPackage true if unqualified class names belong to the
|
rlm@10
|
132 * default package, or false if they correspond to java.lang classes.
|
rlm@10
|
133 * For instance "Object" means "Object" if this option is true, or
|
rlm@10
|
134 * "java.lang.Object" otherwise.
|
rlm@10
|
135 * @return a {@link Method} corresponding to the given Java method
|
rlm@10
|
136 * declaration.
|
rlm@10
|
137 * @throws IllegalArgumentException if <code>method</code> could not get
|
rlm@10
|
138 * parsed.
|
rlm@10
|
139 */
|
rlm@10
|
140 public static Method getMethod(
|
rlm@10
|
141 final String method,
|
rlm@10
|
142 final boolean defaultPackage) throws IllegalArgumentException{
|
rlm@10
|
143 int space = method.indexOf(' ');
|
rlm@10
|
144 int start = method.indexOf('(', space) + 1;
|
rlm@10
|
145 int end = method.indexOf(')', start);
|
rlm@10
|
146 if(space == -1 || start == -1 || end == -1)
|
rlm@10
|
147 {
|
rlm@10
|
148 throw new IllegalArgumentException();
|
rlm@10
|
149 }
|
rlm@10
|
150 // TODO: Check validity of returnType, methodName and arguments.
|
rlm@10
|
151 String returnType = method.substring(0, space);
|
rlm@10
|
152 String methodName = method.substring(space + 1, start - 1).trim();
|
rlm@10
|
153 StringBuffer sb = new StringBuffer();
|
rlm@10
|
154 sb.append('(');
|
rlm@10
|
155 int p;
|
rlm@10
|
156 do
|
rlm@10
|
157 {
|
rlm@10
|
158 String s;
|
rlm@10
|
159 p = method.indexOf(',', start);
|
rlm@10
|
160 if(p == -1)
|
rlm@10
|
161 {
|
rlm@10
|
162 s = map(method.substring(start, end).trim(), defaultPackage);
|
rlm@10
|
163 }
|
rlm@10
|
164 else
|
rlm@10
|
165 {
|
rlm@10
|
166 s = map(method.substring(start, p).trim(), defaultPackage);
|
rlm@10
|
167 start = p + 1;
|
rlm@10
|
168 }
|
rlm@10
|
169 sb.append(s);
|
rlm@10
|
170 } while(p != -1);
|
rlm@10
|
171 sb.append(')');
|
rlm@10
|
172 sb.append(map(returnType, defaultPackage));
|
rlm@10
|
173 return new Method(methodName, sb.toString());
|
rlm@10
|
174 }
|
rlm@10
|
175
|
rlm@10
|
176 private static String map(final String type, final boolean defaultPackage){
|
rlm@10
|
177 if(type.equals(""))
|
rlm@10
|
178 {
|
rlm@10
|
179 return type;
|
rlm@10
|
180 }
|
rlm@10
|
181
|
rlm@10
|
182 StringBuffer sb = new StringBuffer();
|
rlm@10
|
183 int index = 0;
|
rlm@10
|
184 while((index = type.indexOf("[]", index) + 1) > 0)
|
rlm@10
|
185 {
|
rlm@10
|
186 sb.append('[');
|
rlm@10
|
187 }
|
rlm@10
|
188
|
rlm@10
|
189 String t = type.substring(0, type.length() - sb.length() * 2);
|
rlm@10
|
190 String desc = (String) DESCRIPTORS.get(t);
|
rlm@10
|
191 if(desc != null)
|
rlm@10
|
192 {
|
rlm@10
|
193 sb.append(desc);
|
rlm@10
|
194 }
|
rlm@10
|
195 else
|
rlm@10
|
196 {
|
rlm@10
|
197 sb.append('L');
|
rlm@10
|
198 if(t.indexOf('.') < 0)
|
rlm@10
|
199 {
|
rlm@10
|
200 if(!defaultPackage)
|
rlm@10
|
201 {
|
rlm@10
|
202 sb.append("java/lang/");
|
rlm@10
|
203 }
|
rlm@10
|
204 sb.append(t);
|
rlm@10
|
205 }
|
rlm@10
|
206 else
|
rlm@10
|
207 {
|
rlm@10
|
208 sb.append(t.replace('.', '/'));
|
rlm@10
|
209 }
|
rlm@10
|
210 sb.append(';');
|
rlm@10
|
211 }
|
rlm@10
|
212 return sb.toString();
|
rlm@10
|
213 }
|
rlm@10
|
214
|
rlm@10
|
215 /**
|
rlm@10
|
216 * Returns the name of the method described by this object.
|
rlm@10
|
217 *
|
rlm@10
|
218 * @return the name of the method described by this object.
|
rlm@10
|
219 */
|
rlm@10
|
220 public String getName(){
|
rlm@10
|
221 return name;
|
rlm@10
|
222 }
|
rlm@10
|
223
|
rlm@10
|
224 /**
|
rlm@10
|
225 * Returns the descriptor of the method described by this object.
|
rlm@10
|
226 *
|
rlm@10
|
227 * @return the descriptor of the method described by this object.
|
rlm@10
|
228 */
|
rlm@10
|
229 public String getDescriptor(){
|
rlm@10
|
230 return desc;
|
rlm@10
|
231 }
|
rlm@10
|
232
|
rlm@10
|
233 /**
|
rlm@10
|
234 * Returns the return type of the method described by this object.
|
rlm@10
|
235 *
|
rlm@10
|
236 * @return the return type of the method described by this object.
|
rlm@10
|
237 */
|
rlm@10
|
238 public Type getReturnType(){
|
rlm@10
|
239 return Type.getReturnType(desc);
|
rlm@10
|
240 }
|
rlm@10
|
241
|
rlm@10
|
242 /**
|
rlm@10
|
243 * Returns the argument types of the method described by this object.
|
rlm@10
|
244 *
|
rlm@10
|
245 * @return the argument types of the method described by this object.
|
rlm@10
|
246 */
|
rlm@10
|
247 public Type[] getArgumentTypes(){
|
rlm@10
|
248 return Type.getArgumentTypes(desc);
|
rlm@10
|
249 }
|
rlm@10
|
250
|
rlm@10
|
251 public String toString(){
|
rlm@10
|
252 return name + desc;
|
rlm@10
|
253 }
|
rlm@10
|
254
|
rlm@10
|
255 public boolean equals(final Object o){
|
rlm@10
|
256 if(!(o instanceof Method))
|
rlm@10
|
257 {
|
rlm@10
|
258 return false;
|
rlm@10
|
259 }
|
rlm@10
|
260 Method other = (Method) o;
|
rlm@10
|
261 return name.equals(other.name) && desc.equals(other.desc);
|
rlm@10
|
262 }
|
rlm@10
|
263
|
rlm@10
|
264 public int hashCode(){
|
rlm@10
|
265 return name.hashCode() ^ desc.hashCode();
|
rlm@10
|
266 }
|
rlm@10
|
267 } |