1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm.commons; 60 61 import java.util.HashMap; 62 import java.util.Map; 63 64 import jdk.internal.org.objectweb.asm.Type; 65 66 /** 67 * A named method descriptor. 68 * 69 * @author Juozas Baliuka 70 * @author Chris Nokleberg 71 * @author Eric Bruneton 72 */ 73 public class Method { 74 75 /** 76 * The method name. 77 */ 78 private final String name; 79 80 /** 81 * The method descriptor. 82 */ 83 private final String desc; 84 85 /** 86 * Maps primitive Java type names to their descriptors. 87 */ 88 private static final Map<String, String> DESCRIPTORS; 89 90 static { 91 DESCRIPTORS = new HashMap<String, String>(); 92 DESCRIPTORS.put("void", "V"); 93 DESCRIPTORS.put("byte", "B"); 94 DESCRIPTORS.put("char", "C"); 95 DESCRIPTORS.put("double", "D"); 96 DESCRIPTORS.put("float", "F"); 97 DESCRIPTORS.put("int", "I"); 98 DESCRIPTORS.put("long", "J"); 99 DESCRIPTORS.put("short", "S"); 100 DESCRIPTORS.put("boolean", "Z"); 101 } 102 103 /** 104 * Creates a new {@link Method}. 105 * 106 * @param name 107 * the method's name. 108 * @param desc 109 * the method's descriptor. 110 */ 111 public Method(final String name, final String desc) { 112 this.name = name; 113 this.desc = desc; 114 } 115 116 /** 117 * Creates a new {@link Method}. 118 * 119 * @param name 120 * the method's name. 121 * @param returnType 122 * the method's return type. 123 * @param argumentTypes 124 * the method's argument types. 125 */ 126 public Method(final String name, final Type returnType, 127 final Type[] argumentTypes) { 128 this(name, Type.getMethodDescriptor(returnType, argumentTypes)); 129 } 130 131 /** 132 * Creates a new {@link Method}. 133 * 134 * @param m 135 * a java.lang.reflect method descriptor 136 * @return a {@link Method} corresponding to the given Java method 137 * declaration. 138 */ 139 public static Method getMethod(java.lang.reflect.Method m) { 140 return new Method(m.getName(), Type.getMethodDescriptor(m)); 141 } 142 143 /** 144 * Creates a new {@link Method}. 145 * 146 * @param c 147 * a java.lang.reflect constructor descriptor 148 * @return a {@link Method} corresponding to the given Java constructor 149 * declaration. 150 */ 151 public static Method getMethod(java.lang.reflect.Constructor<?> c) { 152 return new Method("<init>", Type.getConstructorDescriptor(c)); 153 } 154 155 /** 156 * Returns a {@link Method} corresponding to the given Java method 157 * declaration. 158 * 159 * @param method 160 * a Java method declaration, without argument names, of the form 161 * "returnType name (argumentType1, ... argumentTypeN)", where 162 * the types are in plain Java (e.g. "int", "float", 163 * "java.util.List", ...). Classes of the java.lang package can 164 * be specified by their unqualified name; all other classes 165 * names must be fully qualified. 166 * @return a {@link Method} corresponding to the given Java method 167 * declaration. 168 * @throws IllegalArgumentException 169 * if <code>method</code> could not get parsed. 170 */ 171 public static Method getMethod(final String method) 172 throws IllegalArgumentException { 173 return getMethod(method, false); 174 } 175 176 /** 177 * Returns a {@link Method} corresponding to the given Java method 178 * declaration. 179 * 180 * @param method 181 * a Java method declaration, without argument names, of the form 182 * "returnType name (argumentType1, ... argumentTypeN)", where 183 * the types are in plain Java (e.g. "int", "float", 184 * "java.util.List", ...). Classes of the java.lang package may 185 * be specified by their unqualified name, depending on the 186 * defaultPackage argument; all other classes names must be fully 187 * qualified. 188 * @param defaultPackage 189 * true if unqualified class names belong to the default package, 190 * or false if they correspond to java.lang classes. For instance 191 * "Object" means "Object" if this option is true, or 192 * "java.lang.Object" otherwise. 193 * @return a {@link Method} corresponding to the given Java method 194 * declaration. 195 * @throws IllegalArgumentException 196 * if <code>method</code> could not get parsed. 197 */ 198 public static Method getMethod(final String method, 199 final boolean defaultPackage) throws IllegalArgumentException { 200 int space = method.indexOf(' '); 201 int start = method.indexOf('(', space) + 1; 202 int end = method.indexOf(')', start); 203 if (space == -1 || start == -1 || end == -1) { 204 throw new IllegalArgumentException(); 205 } 206 String returnType = method.substring(0, space); 207 String methodName = method.substring(space + 1, start - 1).trim(); 208 StringBuffer sb = new StringBuffer(); 209 sb.append('('); 210 int p; 211 do { 212 String s; 213 p = method.indexOf(',', start); 214 if (p == -1) { 215 s = map(method.substring(start, end).trim(), defaultPackage); 216 } else { 217 s = map(method.substring(start, p).trim(), defaultPackage); 218 start = p + 1; 219 } 220 sb.append(s); 221 } while (p != -1); 222 sb.append(')'); 223 sb.append(map(returnType, defaultPackage)); 224 return new Method(methodName, sb.toString()); 225 } 226 227 private static String map(final String type, final boolean defaultPackage) { 228 if ("".equals(type)) { 229 return type; 230 } 231 232 StringBuffer sb = new StringBuffer(); 233 int index = 0; 234 while ((index = type.indexOf("[]", index) + 1) > 0) { 235 sb.append('['); 236 } 237 238 String t = type.substring(0, type.length() - sb.length() * 2); 239 String desc = DESCRIPTORS.get(t); 240 if (desc != null) { 241 sb.append(desc); 242 } else { 243 sb.append('L'); 244 if (t.indexOf('.') < 0) { 245 if (!defaultPackage) { 246 sb.append("java/lang/"); 247 } 248 sb.append(t); 249 } else { 250 sb.append(t.replace('.', '/')); 251 } 252 sb.append(';'); 253 } 254 return sb.toString(); 255 } 256 257 /** 258 * Returns the name of the method described by this object. 259 * 260 * @return the name of the method described by this object. 261 */ 262 public String getName() { 263 return name; 264 } 265 266 /** 267 * Returns the descriptor of the method described by this object. 268 * 269 * @return the descriptor of the method described by this object. 270 */ 271 public String getDescriptor() { 272 return desc; 273 } 274 275 /** 276 * Returns the return type of the method described by this object. 277 * 278 * @return the return type of the method described by this object. 279 */ 280 public Type getReturnType() { 281 return Type.getReturnType(desc); 282 } 283 284 /** 285 * Returns the argument types of the method described by this object. 286 * 287 * @return the argument types of the method described by this object. 288 */ 289 public Type[] getArgumentTypes() { 290 return Type.getArgumentTypes(desc); 291 } 292 293 @Override 294 public String toString() { 295 return name + desc; 296 } 297 298 @Override 299 public boolean equals(final Object o) { 300 if (!(o instanceof Method)) { 301 return false; 302 } 303 Method other = (Method) o; 304 return name.equals(other.name) && desc.equals(other.desc); 305 } 306 307 @Override 308 public int hashCode() { 309 return name.hashCode() ^ desc.hashCode(); 310 } 311 }