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