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