169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtPrimitiveType; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A support class for dealing with descriptors. 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>See chapter 4.3 in "The Java Virtual Machine Specification (2nd ed.)" 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Descriptor { 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Converts a class name into the internal representation used in 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the JVM. 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Note that <code>toJvmName(toJvmName(s))</code> is equivalent 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to <code>toJvmName(s)</code>. 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toJvmName(String classname) { 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return classname.replace('.', '/'); 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Converts a class name from the internal representation used in 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the JVM to the normal one used in Java. 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method does not deal with an array type name such as 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * "[Ljava/lang/Object;" and "[I;". For such names, use 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>toClassName()</code>. 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see #toClassName(String) 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toJavaName(String classname) { 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return classname.replace('/', '.'); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the internal representation of the class name in the 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * JVM. 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toJvmName(CtClass clazz) { 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz.isArray()) 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return of(clazz); 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return toJvmName(clazz.getName()); 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Converts to a Java class name from a descriptor. 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param descriptor type descriptor. 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toClassName(String descriptor) { 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int arrayDim = 0; 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 0; 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = descriptor.charAt(0); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') { 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++arrayDim; 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = descriptor.charAt(++i); 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name; 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') { 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i2 = descriptor.indexOf(';', i++); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = descriptor.substring(i, i2).replace('/', '.'); 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = i2; 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'V') 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "void"; 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'I') 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "int"; 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'B') 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "byte"; 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'J') 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "long"; 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'D') 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "double"; 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'F') 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "float"; 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'C') 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "char"; 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'S') 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "short"; 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == 'Z') 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = "boolean"; 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("bad descriptor: " + descriptor); 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i + 1 != descriptor.length()) 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("multiple descriptors?: " + descriptor); 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (arrayDim == 0) 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return name; 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(name); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal do { 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append("[]"); 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } while (--arrayDim > 0); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return sbuf.toString(); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Converts to a descriptor from a Java class name 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String of(String classname) { 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (classname.equals("void")) 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "V"; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("int")) 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "I"; 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("byte")) 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "B"; 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("long")) 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "J"; 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("double")) 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "D"; 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("float")) 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "F"; 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("char")) 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "C"; 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("short")) 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "S"; 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (classname.equals("boolean")) 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "Z"; 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "L" + toJvmName(classname) + ";"; 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Substitutes a class name 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in the given descriptor string. 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor string 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param oldname replaced JVM class name 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param newname substituted JVM class name 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see Descriptor#toJvmName(String) 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String rename(String desc, String oldname, String newname) { 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.indexOf(oldname) < 0) 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer newdesc = new StringBuffer(); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int head = 0; 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 0; 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int j = desc.indexOf('L', i); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (j < 0) 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (desc.startsWith(oldname, j + 1) 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && desc.charAt(j + oldname.length() + 1) == ';') { 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(head, j)); 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append('L'); 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(newname); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(';'); 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal head = i = j + oldname.length() + 2; 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = desc.indexOf(';', j) + 1; 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 1) 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; // ';' was not found. 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (head == 0) 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = desc.length(); 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (head < len) 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(head, len)); 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newdesc.toString(); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Substitutes class names in the given descriptor string 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * according to the given <code>map</code>. 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param map a map between replaced and substituted 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * JVM class names. 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see Descriptor#toJvmName(String) 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String rename(String desc, Map map) { 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (map == null) 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer newdesc = new StringBuffer(); 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int head = 0; 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 0; 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int j = desc.indexOf('L', i); 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (j < 0) 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int k = desc.indexOf(';', j); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (k < 0) 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = k + 1; 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = desc.substring(j + 1, k); 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name2 = (String)map.get(name); 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name2 != null) { 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(head, j)); 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append('L'); 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(name2); 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(';'); 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal head = i; 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (head == 0) 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = desc.length(); 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (head < len) 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(head, len)); 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newdesc.toString(); 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the descriptor representing the given type. 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String of(CtClass type) { 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(); 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toDescriptor(sbuf, type); 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return sbuf.toString(); 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void toDescriptor(StringBuffer desc, CtClass type) { 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type.isArray()) { 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append('['); 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toDescriptor(desc, type.getComponentType()); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append('L'); 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = type.getName(); 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(toJvmName(name.substring(0, name.length() - 2))); 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(';'); 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type.isPrimitive()) { 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)type; 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(pt.getDescriptor()); 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { // class type 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append('L'); 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(type.getName().replace('.', '/')); 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(';'); 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the descriptor representing a constructor receiving 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the given parameter types. 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramTypes parameter types 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String ofConstructor(CtClass[] paramTypes) { 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ofMethod(CtClass.voidType, paramTypes); 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the descriptor representing a method that receives 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the given parameter types and returns the given type. 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param returnType return type 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramTypes parameter types 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String ofMethod(CtClass returnType, CtClass[] paramTypes) { 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer desc = new StringBuffer(); 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append('('); 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (paramTypes != null) { 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = paramTypes.length; 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toDescriptor(desc, paramTypes[i]); 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc.append(')'); 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (returnType != null) 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toDescriptor(desc, returnType); 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc.toString(); 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the descriptor representing a list of parameter types. 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * For example, if the given parameter types are two <code>int</code>, 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then this method returns <code>"(II)"</code>. 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramTypes parameter types 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String ofParameters(CtClass[] paramTypes) { 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return ofMethod(null, paramTypes); 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Appends a parameter type to the parameter list represented 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by the given descriptor. 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>classname</code> must not be an array type. 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classname parameter type (not primitive type) 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String appendParameter(String classname, String desc) { 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = desc.indexOf(')'); 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 0) 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer newdesc = new StringBuffer(); 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(0, i)); 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append('L'); 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(classname.replace('.', '/')); 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(';'); 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(i)); 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newdesc.toString(); 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Inserts a parameter type at the beginning of the parameter 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * list represented 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by the given descriptor. 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>classname</code> must not be an array type. 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classname parameter type (not primitive type) 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String insertParameter(String classname, String desc) { 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(0) != '(') 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "(L" + classname.replace('.', '/') + ';' 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + desc.substring(1); 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Appends a parameter type to the parameter list represented 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by the given descriptor. The appended parameter becomes 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the last parameter. 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param type the type of the appended parameter. 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param descriptor the original descriptor. 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String appendParameter(CtClass type, String descriptor) { 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = descriptor.indexOf(')'); 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 0) 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return descriptor; 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer newdesc = new StringBuffer(); 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(descriptor.substring(0, i)); 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toDescriptor(newdesc, type); 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(descriptor.substring(i)); 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newdesc.toString(); 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Inserts a parameter type at the beginning of the parameter 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * list represented 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by the given descriptor. 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param type the type of the inserted parameter. 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param descriptor the descriptor of the method. 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String insertParameter(CtClass type, 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String descriptor) { 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (descriptor.charAt(0) != '(') 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return descriptor; 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return "(" + of(type) + descriptor.substring(1); 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Changes the return type included in the given descriptor. 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>classname</code> must not be an array type. 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classname return type 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String changeReturnType(String classname, String desc) { 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = desc.indexOf(')'); 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 0) 40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc; 40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer newdesc = new StringBuffer(); 41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(desc.substring(0, i + 1)); 41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append('L'); 41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(classname.replace('.', '/')); 41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal newdesc.append(';'); 41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return newdesc.toString(); 41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the <code>CtClass</code> objects representing the parameter 42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * types specified by the given descriptor. 42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp the class pool used for obtaining 42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a <code>CtClass</code> object. 42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static CtClass[] getParameterTypes(String desc, ClassPool cp) 42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException 42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(0) != '(') 43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int num = numOfParameters(desc); 43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] args = new CtClass[num]; 43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = 0; 43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 1; 43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal do { 43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = toCtClass(cp, desc, i, args, n++); 43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } while (i > 0); 44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return args; 44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if the list of the parameter types of desc1 is equal to 44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * that of desc2. 44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * For example, "(II)V" and "(II)I" are equal. 44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static boolean eqParamTypes(String desc1, String desc2) { 45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc1.charAt(0) != '(') 45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; true; ++i) { 45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc1.charAt(i); 45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c != desc2.charAt(i)) 45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ')') 45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return true; 46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the signature of the given descriptor. The signature does 46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * not include the return type. For example, the signature of "(I)V" 46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is "(I)". 46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String getParamDescriptor(String decl) { 46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return decl.substring(0, decl.indexOf(')') + 1); 47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the <code>CtClass</code> object representing the return 47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * type specified by the given descriptor. 47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp the class pool used for obtaining 47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a <code>CtClass</code> object. 47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static CtClass getReturnType(String desc, ClassPool cp) 48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException 48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = desc.indexOf(')'); 48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i < 0) 48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] type = new CtClass[1]; 48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal toCtClass(cp, desc, i + 1, type, 0); 48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return type[0]; 49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the number of the prameters included in the given 49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * descriptor. 49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int numOfParameters(String desc) { 50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = 0; 50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 1; 50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(i); 50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ')') 50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') 50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++i); 50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') { 51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = desc.indexOf(';', i) + 1; 51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i <= 0) 51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new IndexOutOfBoundsException("bad descriptor"); 51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++i; 51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++n; 51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return n; 52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns a <code>CtClass</code> object representing the type 52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * specified by the given descriptor. 52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This method works even if the package-class separator is 52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * not <code>/</code> but <code>.</code> (period). For example, 53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * it accepts <code>Ljava.lang.Object;</code> 53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * as well as <code>Ljava/lang/Object;</code>. 53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor. 53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param cp the class pool used for obtaining 53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a <code>CtClass</code> object. 53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static CtClass toCtClass(String desc, ClassPool cp) 53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException 53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] clazz = new CtClass[1]; 54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int res = toCtClass(cp, desc, 0, clazz, 0); 54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (res >= 0) 54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return clazz[0]; 54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // maybe, you forgot to surround the class name with 54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // L and ;. It violates the protocol, but I'm tolerant... 54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cp.get(desc.replace('/', '.')); 54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static int toCtClass(ClassPool cp, String desc, int i, 55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] args, int n) 55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws NotFoundException 55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i2; 55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name; 55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int arrayDim = 0; 55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(i); 56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') { 56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++arrayDim; 56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++i); 56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') { 56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i2 = desc.indexOf(';', ++i); 56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = desc.substring(i, i2++).replace('/', '.'); 56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass type = toPrimitiveClass(c); 57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type == null) 57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; // error 57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i2 = i + 1; 57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (arrayDim == 0) { 57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args[n] = type; 57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return i2; // neither an array type or a class type 57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = type.getName(); 58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (arrayDim > 0) { 58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(name); 58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (arrayDim-- > 0) 58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append("[]"); 58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal name = sbuf.toString(); 58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args[n] = cp.get(name); 59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return i2; 59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static CtClass toPrimitiveClass(char c) { 59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass type = null; 59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (c) { 59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'Z' : 59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.booleanType; 60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'C' : 60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.charType; 60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'B' : 60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.byteType; 60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'S' : 60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.shortType; 60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'I' : 61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.intType; 61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'J' : 61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.longType; 61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'F' : 61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.floatType; 61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'D' : 62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.doubleType; 62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'V' : 62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal type = CtClass.voidType; 62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return type; 62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Computes the dimension of the array represented by the given 63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * descriptor. For example, if the descriptor is <code>"[[I"</code>, 63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then this method returns 2. 63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc the descriptor. 63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return 0 if the descriptor does not represent an array type. 63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int arrayDimension(String desc) { 63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = 0; 64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (desc.charAt(dim) == '[') 64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++dim; 64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return dim; 64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the descriptor of the type of the array component. 64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * For example, if the given descriptor is 64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>"[[Ljava/lang/String;"</code> and the given dimension is 2, 65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * then this method returns <code>"Ljava/lang/String;"</code>. 65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc the descriptor. 65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param dim the array dimension. 65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toArrayComponent(String desc, int dim) { 65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return desc.substring(dim); 65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Computes the data size specified by the given descriptor. 66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * For example, if the descriptor is "D", this method returns 2. 66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If the descriptor represents a method type, this method returns 66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * (the size of the returned value) - (the sum of the data sizes 66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * of all the parameters). For example, if the descriptor is 66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>"(I)D"</code>, then this method returns 1 (= 2 - 1). 66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc descriptor 66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int dataSize(String desc) { 67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return dataSize(desc, true); 67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Computes the data size of parameters. 67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If one of the parameters is double type, the size of that parameter 67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is 2 words. For example, if the given descriptor is 67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>"(IJ)D"</code>, then this method returns 3. The size of the 67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * return type is not computed. 68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param desc a method descriptor. 68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int paramSize(String desc) { 68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -dataSize(desc, false); 68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static int dataSize(String desc, boolean withRet) { 68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = 0; 68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(0); 69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == '(') { 69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 1; 69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (;;) { 69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(i); 69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ')') { 69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(i + 1); 69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean array = false; 70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') { 70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal array = true; 70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++i); 70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') { 70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal i = desc.indexOf(';', i) + 1; 70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (i <= 0) 70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new IndexOutOfBoundsException("bad descriptor"); 70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++i; 71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!array && (c == 'J' || c == 'D')) 71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n -= 2; 71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal --n; 71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (withRet) 72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'J' || c == 'D') 72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n += 2; 72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c != 'V') 72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++n; 72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return n; 72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns a human-readable representation of the 73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * given descriptor. For example, <code>Ljava/lang/Object;</code> 73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is converted into <code>java.lang.Object</code>. 73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>(I[I)V</code> is converted into <code>(int, int[])</code> 73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * (the return type is ignored). 73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static String toString(String desc) { 73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return PrettyPrinter.toString(desc); 73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static class PrettyPrinter { 74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static String toString(String desc) { 74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(); 74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(0) == '(') { 74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = 1; 74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append('('); 74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (desc.charAt(pos) != ')') { 74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pos > 1) 74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(','); 74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = readType(sbuf, pos, desc); 75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(')'); 75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal readType(sbuf, 0, desc); 75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return sbuf.toString(); 75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static int readType(StringBuffer sbuf, int pos, String desc) { 76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(pos); 76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int arrayDim = 0; 76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') { 76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim++; 76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++pos); 76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') 77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (true) { 77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++pos); 77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ';') 77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == '/') 77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = '.'; 77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(c); 77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass t = toPrimitiveClass(c); 78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(t.getName()); 78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (arrayDim-- > 0) 78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append("[]"); 78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos + 1; 78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * An Iterator over a descriptor. 79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static class Iterator { 79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String desc; 79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int index, curPos; 79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean param; 79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs an iterator. 80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param s descriptor. 80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Iterator(String s) { 80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal desc = s; 80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = curPos = 0; 80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal param = false; 80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if the iteration has more elements. 81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean hasNext() { 81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return index < desc.length(); 81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if the current element is a parameter type. 82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean isParameter() { return param; } 82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the first character of the current element. 82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public char currentChar() { return desc.charAt(curPos); } 82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns true if the current element is double or long type. 83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean is2byte() { 83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = currentChar(); 83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return c == 'D' || c == 'J'; 83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the position of the next type character. 83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * That type character becomes a new current element. 83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int next() { 84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int nextPos = index; 84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(nextPos); 84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == '(') { 84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++index; 84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++nextPos); 84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal param = true; 84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == ')') { 85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++index; 85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++nextPos); 85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal param = false; 85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (c == '[') 85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = desc.charAt(++nextPos); 85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == 'L') { 85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal nextPos = desc.indexOf(';', nextPos) + 1; 86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (nextPos <= 0) 86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new IndexOutOfBoundsException("bad descriptor"); 86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++nextPos; 86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal curPos = index; 86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = nextPos; 86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return curPos; 86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 872