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 java.io.DataInputStream;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataOutputStream;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.ArrayList;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.List;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.ListIterator;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>ClassFile</code> represents a Java <code>.class</code> file, which
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * consists of a constant pool, methods, fields, and attributes.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.CtClass#getClassFile()
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic final class ClassFile {
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int major, minor; // version number
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ConstPool constPool;
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int thisClass;
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int accessFlags;
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int superClass;
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int[] interfaces;
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ArrayList fields;
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ArrayList methods;
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ArrayList attributes;
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String thisclassname; // not JVM-internal name
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String[] cachedInterfaces;
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String cachedSuperclass;
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.1.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_1 = 45;
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.2.
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_2 = 46;
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.3.
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_3 = 47;
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.4.
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_4 = 48;
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.5.
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_5 = 49;
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.6.
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_6 = 50;
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for JDK 1.7.
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final int JAVA_7 = 51;
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The major version number of class files created
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * from scratch.  The default value is 47 (JDK 1.3)
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * or 49 (JDK 1.5) if the JVM supports <code>java.lang.StringBuilder</code>.
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static int MAJOR_VERSION = JAVA_3;
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static {
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Class.forName("java.lang.StringBuilder");
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MAJOR_VERSION = JAVA_5;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (Throwable t) {}
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a class file from a byte stream.
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ClassFile(DataInputStream in) throws IOException {
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        read(in);
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a class file including no members.
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isInterface
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            true if this is an interface. false if this is a class.
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classname
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            a fully-qualified class name
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param superclass
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            a fully-qualified super class name
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ClassFile(boolean isInterface, String classname, String superclass) {
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        major = MAJOR_VERSION;
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        minor = 0; // JDK 1.3 or later
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = new ConstPool(classname);
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisClass = constPool.getThisClassInfo();
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (isInterface)
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            accessFlags = AccessFlag.INTERFACE | AccessFlag.ABSTRACT;
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            accessFlags = AccessFlag.SUPER;
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        initSuperclass(superclass);
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        interfaces = null;
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        fields = new ArrayList();
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methods = new ArrayList();
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisclassname = classname;
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = new ArrayList();
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes.add(new SourceFileAttribute(constPool,
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                getSourcefileName(thisclassname)));
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void initSuperclass(String superclass) {
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (superclass != null) {
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.superClass = constPool.addClassInfo(superclass);
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cachedSuperclass = superclass;
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.superClass = constPool.addClassInfo("java.lang.Object");
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cachedSuperclass = "java.lang.Object";
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static String getSourcefileName(String qname) {
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = qname.lastIndexOf('.');
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (index >= 0)
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            qname = qname.substring(index + 1);
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return qname + ".java";
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Eliminates dead constant pool items. If a method or a field is removed,
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the constant pool items used by that method/field become dead items. This
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * method recreates a constant pool.
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void compact() {
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = compact0();
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = methods;
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            minfo.compact(cp);
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = fields;
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            finfo.compact(cp);
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = AttributeInfo.copyAll(attributes, cp);
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = cp;
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ConstPool compact0() {
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = new ConstPool(thisclassname);
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisClass = cp.getThisClassInfo();
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String sc = getSuperclass();
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sc != null)
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            superClass = cp.addClassInfo(getSuperclass());
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (interfaces != null) {
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = interfaces.length;
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i)
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                interfaces[i]
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    = cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return cp;
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Discards all attributes, associated with both the class file and the
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * members such as a code attribute and exceptions attribute. The unused
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * constant pool entries are also discarded (a new packed constant pool is
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * constructed).
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void prune() {
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = compact0();
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList newAttributes = new ArrayList();
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo invisibleAnnotations
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = getAttribute(AnnotationsAttribute.invisibleTag);
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (invisibleAnnotations != null) {
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            invisibleAnnotations = invisibleAnnotations.copy(cp, null);
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newAttributes.add(invisibleAnnotations);
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo visibleAnnotations
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = getAttribute(AnnotationsAttribute.visibleTag);
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (visibleAnnotations != null) {
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            visibleAnnotations = visibleAnnotations.copy(cp, null);
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newAttributes.add(visibleAnnotations);
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo signature
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = getAttribute(SignatureAttribute.tag);
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (signature != null) {
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            signature = signature.copy(cp, null);
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newAttributes.add(signature);
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = methods;
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            minfo.prune(cp);
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = fields;
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            finfo.prune(cp);
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = newAttributes;
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = cp;
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns a constant pool table.
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public ConstPool getConstPool() {
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return constPool;
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if this is an interface.
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isInterface() {
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (accessFlags & AccessFlag.INTERFACE) != 0;
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if this is a final class or interface.
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isFinal() {
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (accessFlags & AccessFlag.FINAL) != 0;
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if this is an abstract class or an interface.
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isAbstract() {
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (accessFlags & AccessFlag.ABSTRACT) != 0;
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns access flags.
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.AccessFlag
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getAccessFlags() {
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return accessFlags;
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Changes access flags.
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.AccessFlag
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setAccessFlags(int acc) {
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if ((acc & AccessFlag.INTERFACE) == 0)
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            acc |= AccessFlag.SUPER;
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        accessFlags = acc;
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns access and property flags of this nested class.
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method returns -1 if the class is not a nested class.
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>The returned value is obtained from <code>inner_class_access_flags</code>
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * of the entry representing this nested class itself
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in <code>InnerClasses_attribute</code>>.
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getInnerAccessFlags() {
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        InnerClassesAttribute ica
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (InnerClassesAttribute)getAttribute(InnerClassesAttribute.tag);
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ica == null)
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return -1;
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name = getName();
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = ica.tableLength();
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i)
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (name.equals(ica.innerClass(i)))
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return ica.accessFlags(i);
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return -1;
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the class name.
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getName() {
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return thisclassname;
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the class name. This method substitutes the new name for all
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * occurrences of the old class name in the class file.
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setName(String name) {
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        renameClass(thisclassname, name);
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the super class name.
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getSuperclass() {
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cachedSuperclass == null)
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cachedSuperclass = constPool.getClassInfo(superClass);
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return cachedSuperclass;
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the index of the constant pool entry representing the super
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * class.
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getSuperclassId() {
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return superClass;
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the super class.
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The new super class should inherit from the old super class.
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method modifies constructors so that they call constructors declared
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in the new super class.
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setSuperclass(String superclass) throws CannotCompileException {
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (superclass == null)
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            superclass = "java.lang.Object";
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.superClass = constPool.addClassInfo(superclass);
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ArrayList list = methods;
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = list.size();
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i) {
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                MethodInfo minfo = (MethodInfo)list.get(i);
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                minfo.setSuperclass(superclass);
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(e);
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedSuperclass = superclass;
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replaces all occurrences of a class name in the class file.
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If class X is substituted for class Y in the class file, X and Y must
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * have the same signature. If Y provides a method m(), X must provide it
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * even if X inherits m() from the super class. If this fact is not
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * guaranteed, the bytecode verifier may cause an error.
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param oldname
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            the replaced class name
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param newname
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            the substituted class name
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final void renameClass(String oldname, String newname) {
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list;
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n;
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (oldname.equals(newname))
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (oldname.equals(thisclassname))
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            thisclassname = newname;
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        oldname = Descriptor.toJvmName(oldname);
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        newname = Descriptor.toJvmName(newname);
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool.renameClass(oldname, newname);
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.renameClass(attributes, oldname, newname);
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = methods;
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = minfo.getDescriptor();
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.renameClass(minfo.getAttributes(), oldname, newname);
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = fields;
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = finfo.getDescriptor();
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.renameClass(finfo.getAttributes(), oldname, newname);
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replaces all occurrences of several class names in the class file.
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            specifies which class name is replaced with which new name.
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            Class names must be described with the JVM-internal
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            representation like <code>java/lang/Object</code>.
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #renameClass(String,String)
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final void renameClass(Map classnames) {
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String jvmNewThisName = (String)classnames.get(Descriptor
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                .toJvmName(thisclassname));
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (jvmNewThisName != null)
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            thisclassname = Descriptor.toJavaName(jvmNewThisName);
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool.renameClass(classnames);
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.renameClass(attributes, classnames);
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = methods;
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = minfo.getDescriptor();
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            minfo.setDescriptor(Descriptor.rename(desc, classnames));
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.renameClass(minfo.getAttributes(), classnames);
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = fields;
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = finfo.getDescriptor();
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            finfo.setDescriptor(Descriptor.rename(desc, classnames));
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.renameClass(finfo.getAttributes(), classnames);
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Internal-use only.
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>CtClass.getRefClasses()</code> calls this method.
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final void getRefClasses(Map classnames) {
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool.renameClass(classnames);
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.getRefClasses(attributes, classnames);
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = methods;
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = minfo.getDescriptor();
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Descriptor.rename(desc, classnames);
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.getRefClasses(minfo.getAttributes(), classnames);
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = fields;
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String desc = finfo.getDescriptor();
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Descriptor.rename(desc, classnames);
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo.getRefClasses(finfo.getAttributes(), classnames);
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the names of the interfaces implemented by the class.
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The returned array is read only.
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String[] getInterfaces() {
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cachedInterfaces != null)
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return cachedInterfaces;
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String[] rtn = null;
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (interfaces == null)
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            rtn = new String[0];
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = interfaces.length;
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String[] list = new String[n];
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i)
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                list[i] = constPool.getClassInfo(interfaces[i]);
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            rtn = list;
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedInterfaces = rtn;
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return rtn;
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the interfaces.
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param nameList
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            the names of the interfaces.
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setInterfaces(String[] nameList) {
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedInterfaces = null;
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (nameList != null) {
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = nameList.length;
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = new int[n];
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i)
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                interfaces[i] = constPool.addClassInfo(nameList[i]);
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends an interface to the interfaces implemented by the class.
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addInterface(String name) {
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cachedInterfaces = null;
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int info = constPool.addClassInfo(name);
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (interfaces == null) {
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = new int[1];
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces[0] = info;
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = interfaces.length;
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int[] newarray = new int[n + 1];
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            System.arraycopy(interfaces, 0, newarray, 0, n);
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            newarray[n] = info;
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = newarray;
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns all the fields declared in the class.
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return a list of <code>FieldInfo</code>.
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see FieldInfo
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public List getFields() {
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return fields;
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends a field to the class.
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws DuplicateMemberException         when the field is already included.
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addField(FieldInfo finfo) throws DuplicateMemberException {
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        testExistingField(finfo.getName(), finfo.getDescriptor());
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        fields.add(finfo);
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Just appends a field to the class.
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It does not check field duplication.
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Use this method only when minimizing performance overheads
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is seriously required.
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.13
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final void addField2(FieldInfo finfo) {
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        fields.add(finfo);
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void testExistingField(String name, String descriptor)
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws DuplicateMemberException {
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ListIterator it = fields.listIterator(0);
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (it.hasNext()) {
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo minfo = (FieldInfo)it.next();
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (minfo.getName().equals(name))
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new DuplicateMemberException("duplicate field: " + name);
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns all the methods declared in the class.
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return a list of <code>MethodInfo</code>.
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see MethodInfo
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public List getMethods() {
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return methods;
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method with the specified name. If there are multiple methods
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * with that name, this method returns one of them.
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if no such method is found.
61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MethodInfo getMethod(String name) {
61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = methods;
61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (minfo.getName().equals(name))
61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return minfo;
61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return null;
62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns a static initializer (class initializer), or null if it does not
62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * exist.
62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public MethodInfo getStaticInitializer() {
62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getMethod(MethodInfo.nameClinit);
63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends a method to the class.
63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If there is a bridge method with the same name and signature,
63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * then the bridge method is removed before a new method is added.
63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws DuplicateMemberException         when the method is already included.
63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addMethod(MethodInfo minfo) throws DuplicateMemberException {
64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        testExistingMethod(minfo);
64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methods.add(minfo);
64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Just appends a method to the class.
64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It does not check method duplication or remove a bridge method.
64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Use this method only when minimizing performance overheads
64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is seriously required.
64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.13
65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final void addMethod2(MethodInfo minfo) {
65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methods.add(minfo);
65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void testExistingMethod(MethodInfo newMinfo)
65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws DuplicateMemberException
65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name = newMinfo.getName();
66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String descriptor = newMinfo.getDescriptor();
66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ListIterator it = methods.listIterator(0);
66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (it.hasNext())
66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isDuplicated(newMinfo, name, descriptor, (MethodInfo)it.next(), it))
66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new DuplicateMemberException("duplicate method: " + name
66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                   + " in " + this.getName());
66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static boolean isDuplicated(MethodInfo newMethod, String newName,
66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        String newDesc, MethodInfo minfo,
67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        ListIterator it)
67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!minfo.getName().equals(newName))
67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = minfo.getDescriptor();
67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!Descriptor.eqParamTypes(desc, newDesc))
67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal           return false;
67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (desc.equals(newDesc)) {
68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (notBridgeMethod(minfo))
68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                it.remove();
68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return false;
68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal           return notBridgeMethod(minfo) && notBridgeMethod(newMethod);
68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* For a bridge method, see Sec. 15.12.4.5 of JLS 3rd Ed.
69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static boolean notBridgeMethod(MethodInfo minfo) {
69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0;
69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns all the attributes.  The returned <code>List</code> object
69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * is shared with this object.  If you add a new attribute to the list,
70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the attribute is also added to the classs file represented by this
70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * object.  If you remove an attribute from the list, it is also removed
70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * from the class file.
70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return a list of <code>AttributeInfo</code> objects.
70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see AttributeInfo
70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public List getAttributes() {
70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return attributes;
70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the attribute with the specified name.  If there are multiple
71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * attributes with that name, this method returns either of them.   It
71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * returns null if the specified attributed is not found.
71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name          attribute name
71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAttributes()
71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo getAttribute(String name) {
72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = attributes;
72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = list.size();
72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            AttributeInfo ai = (AttributeInfo)list.get(i);
72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (ai.getName().equals(name))
72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return ai;
72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return null;
72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Appends an attribute. If there is already an attribute with the same
73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * name, the new one substitutes for it.
73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #getAttributes()
73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addAttribute(AttributeInfo info) {
73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.remove(attributes, info.getName());
73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes.add(info);
74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the source file containing this class.
74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if this information is not available.
74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getSourceFile() {
74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        SourceFileAttribute sf
74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (SourceFileAttribute)getAttribute(SourceFileAttribute.tag);
75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sf == null)
75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sf.getFileName();
75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void read(DataInputStream in) throws IOException {
75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i, n;
75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int magic = in.readInt();
75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (magic != 0xCAFEBABE)
76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new IOException("bad magic number: " + Integer.toHexString(magic));
76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        minor = in.readUnsignedShort();
76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        major = in.readUnsignedShort();
76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = new ConstPool(in);
76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        accessFlags = in.readUnsignedShort();
76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisClass = in.readUnsignedShort();
76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool.setThisClassInfo(thisClass);
76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        superClass = in.readUnsignedShort();
76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = in.readUnsignedShort();
77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (n == 0)
77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = null;
77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = new int[n];
77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (i = 0; i < n; ++i)
77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                interfaces[i] = in.readUnsignedShort();
77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = constPool;
77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = in.readUnsignedShort();
78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        fields = new ArrayList();
78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i)
78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addField2(new FieldInfo(cp, in));
78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = in.readUnsignedShort();
78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        methods = new ArrayList();
78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i)
78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addMethod2(new MethodInfo(cp, in));
78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        attributes = new ArrayList();
79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = in.readUnsignedShort();
79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i)
79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addAttribute(AttributeInfo.read(cp, in));
79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisclassname = constPool.getClassInfo(thisClass);
79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Writes a class file represened by this object into an output stream.
79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void write(DataOutputStream out) throws IOException {
80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i, n;
80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeInt(0xCAFEBABE); // magic
80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(minor); // minor version
80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(major); // major version
80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool.write(out); // constant pool
80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(accessFlags);
80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(thisClass);
80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(superClass);
81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (interfaces == null)
81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            n = 0;
81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            n = interfaces.length;
81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(n);
81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i)
81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.writeShort(interfaces[i]);
81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList list = fields;
82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(n);
82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i) {
82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            FieldInfo finfo = (FieldInfo)list.get(i);
82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            finfo.write(out);
82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list = methods;
82969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        n = list.size();
83069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(n);
83169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (i = 0; i < n; ++i) {
83269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            MethodInfo minfo = (MethodInfo)list.get(i);
83369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            minfo.write(out);
83469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
83569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
83669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        out.writeShort(attributes.size());
83769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        AttributeInfo.writeAll(attributes, out);
83869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
83969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
84069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
84169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Get the Major version.
84269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
84369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the major version
84469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
84569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMajorVersion() {
84669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return major;
84769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
84869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
84969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
85069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Set the major version.
85169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
85269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param major
85369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            the major version
85469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
85569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setMajorVersion(int major) {
85669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this.major = major;
85769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
85869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
85969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
86069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Get the minor version.
86169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
86269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the minor version
86369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
86469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMinorVersion() {
86569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return minor;
86669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
86769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
86869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
86969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Set the minor version.
87069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
87169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param minor
87269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *            the minor version
87369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
87469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setMinorVersion(int minor) {
87569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this.minor = minor;
87669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
87769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
87869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
87969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets the major and minor version to Java 5.
88069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
88169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the major version is older than 49, Java 5
88269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * extensions such as annotations are ignored
88369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * by the JVM.
88469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
88569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setVersionToJava5() {
88669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this.major = 49;
88769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this.minor = 0;
88869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
88969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
890