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