/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */ package javassist; import java.io.DataOutputStream; import java.io.IOException; import javassist.bytecode.*; import java.util.Collection; import javassist.expr.ExprEditor; // Subclasses of CtClass: CtClassType, CtPrimitiveType, and CtArray /** * An instance of CtClass represents a class. * It is obtained from ClassPool. * * @see ClassPool#get(String) */ public abstract class CtClass { protected String qualifiedName; /** * The version number of this release. */ public static final String version = "2.5"; static final String javaLangObject = "java.lang.Object"; /** * The CtClass object representing * the boolean type. */ public static CtClass booleanType; /** * The CtClass object representing * the char type. */ public static CtClass charType; /** * The CtClass object representing * the byte type. */ public static CtClass byteType; /** * The CtClass object representing * the short type. */ public static CtClass shortType; /** * The CtClass object representing * the int type. */ public static CtClass intType; /** * The CtClass object representing * the long type. */ public static CtClass longType; /** * The CtClass object representing * the float type. */ public static CtClass floatType; /** * The CtClass object representing * the double type. */ public static CtClass doubleType; /** * The CtClass object representing * the void type. */ public static CtClass voidType; static CtClass[] primitiveTypes; static { primitiveTypes = new CtClass[9]; booleanType = new CtPrimitiveType("boolean", 'Z', "java.lang.Boolean", "booleanValue", "()Z", Opcode.IRETURN, Opcode.T_BOOLEAN, 1); primitiveTypes[0] = booleanType; charType = new CtPrimitiveType("char", 'C', "java.lang.Character", "charValue", "()C", Opcode.IRETURN, Opcode.T_CHAR, 1); primitiveTypes[1] = charType; byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte", "byteValue", "()B", Opcode.IRETURN, Opcode.T_BYTE, 1); primitiveTypes[2] = byteType; shortType = new CtPrimitiveType("short", 'S', "java.lang.Short", "shortValue", "()S", Opcode.IRETURN, Opcode.T_SHORT, 1); primitiveTypes[3] = shortType; intType = new CtPrimitiveType("int", 'I', "java.lang.Integer", "intValue", "()I", Opcode.IRETURN, Opcode.T_INT, 1); primitiveTypes[4] = intType; longType = new CtPrimitiveType("long", 'J', "java.lang.Long", "longValue", "()J", Opcode.LRETURN, Opcode.T_LONG, 2); primitiveTypes[5] = longType; floatType = new CtPrimitiveType("float", 'F', "java.lang.Float", "floatValue", "()F", Opcode.FRETURN, Opcode.T_FLOAT, 1); primitiveTypes[6] = floatType; doubleType = new CtPrimitiveType("double", 'D', "java.lang.Double", "doubleValue", "()D", Opcode.DRETURN, Opcode.T_DOUBLE, 2); primitiveTypes[7] = doubleType; voidType = new CtPrimitiveType("void", 'V', "java.lang.Void", null, null, Opcode.RETURN, 0, 0); primitiveTypes[8] = voidType; } protected CtClass(String name) { qualifiedName = name; } /** * Returns a ClassPool for this class. */ public ClassPool getClassPool() { return null; } /** * Returns a class file for this class. * *

This method is not available if isFrozen() * is true. */ public ClassFile getClassFile() { checkModify(); return getClassFile2(); } /** * Undocumented method. Do not use; internal-use only. */ public ClassFile getClassFile2() { return null; } /** * Returns true if the definition of the class has been modified. */ public boolean isModified() { return false; } /** * Returns true if the class has been loaded and thus it cannot be * modified any more. */ public boolean isFrozen() { return true; } void freeze() {} void checkModify() throws RuntimeException { if (isFrozen()) throw new RuntimeException("the class is frozen"); // isModified() must return true after this method is invoked. } /** * Defrosts the class so that the class can be modified. * * To avoid changes that are never reflected, * the class is frozen to be unmodifiable if it is loaded or * written out. This method should be called only in a case * that the class will be reloaded or written out later again. */ public void defrost() { throw new RuntimeException("cannot defrost " + getName()); } /** * Returns true if this object represents a primitive * Java type: boolean, byte, char, short, int, long, float, double, * or void. */ public boolean isPrimitive() { return false; } /** * Returns true if this object represents an array type. */ public boolean isArray() { return false; } /** * If this object represents an array, this method returns the component * type of the array. Otherwise, it returns null. */ public CtClass getComponentType() throws NotFoundException { return null; } /** * Returns true if this class extends or implements * clazz. It also returns true if * this class is the same as clazz. */ public boolean subtypeOf(CtClass clazz) throws NotFoundException { return this == clazz || getName().equals(clazz.getName()); } /** * Obtains the fully-qualified name of the class. */ public String getName() { return qualifiedName; } /** * Obtains the not-qualified class name. */ public final String getSimpleName() { String qname = qualifiedName; int index = qname.lastIndexOf('.'); if (index < 0) return qname; else return qname.substring(index + 1); } /** * Obtains the package name. It may be null. */ public final String getPackageName() { String qname = qualifiedName; int index = qname.lastIndexOf('.'); if (index < 0) return null; else return qname.substring(0, index); } /** * Sets the class name * * @param name fully-qualified name */ public void setName(String name) { checkModify(); if (name != null) qualifiedName = name; } /** * Substitutes newName for all occurrences of a class * name oldName in the class file. * * @param oldName replaced class name * @param newName substituted class name */ public void replaceClassName(String oldname, String newname) { checkModify(); } /** * Changes class names appearing in the class file according to the * given map. * *

All the class names appearing in the class file are tested * with map to determine whether each class name is * replaced or not. Thus this method can be used for collecting * all the class names in the class file. To do that, first define * a subclass of ClassMap so that get() * records all the given parameters. Then, make an instance of * that subclass as an empty hash-table. Finally, pass that instance * to this method. After this method finishes, that instance would * contain all the class names appearing in the class file. * * @param map the hashtable associating replaced class names * with substituted names. */ public void replaceClassName(ClassMap map) { checkModify(); } /** * Returns a collection of the names of all the classes * referenced in this class. * That collection includes the name of this class. * *

This method may return null. */ public Collection getRefClasses() { ClassFile cf = getClassFile2(); if (cf != null) { ClassMap cm = new ClassMap() { public void put(String oldname, String newname) { put0(oldname, newname); } public Object get(Object jvmClassName) { String n = toJavaName((String)jvmClassName); put0(n, n); return null; } public void fix(String name) {} }; cf.renameClass(cm); return cm.values(); } else return null; } /** * Determines whether this object represents a class or an interface. * It returns true if this object represents an interface. */ public boolean isInterface() { return false; } /** * Returns the modifiers for this class, encoded in an integer. * For decoding, use javassist.Modifier. * * @see Modifier */ public int getModifiers() { return 0; } /** * Sets the modifiers. * * @param mod modifiers encoded by * javassist.Modifier * @see Modifier */ public void setModifiers(int mod) { checkModify(); } /** * Determines whether the class directly or indirectly extends * the given class. If this class extends a class A and * the class A extends a class B, then subclassof(B) returns true. * *

This method returns true if the given class is identical to * the class represented by this object. */ public boolean subclassOf(CtClass superclass) { return false; } /** * Obtains the class object representing the superclass of the * class. * It returns null if the class is java.lang.Object. */ public CtClass getSuperclass() throws NotFoundException { return null; } /** * Changes a super class. */ public void setSuperclass(CtClass clazz) throws CannotCompileException { checkModify(); } /** * Obtains the class objects representing the interfaces of the * class. */ public CtClass[] getInterfaces() throws NotFoundException { return new CtClass[0]; } /** * Sets interfaces. * * @param list a list of the CtClass objects * representing interfaces, or * null if the class implements * no interfaces. */ public void setInterfaces(CtClass[] list) { checkModify(); } /** * Adds an interface. * * @param anInterface the added interface. */ public void addInterface(CtClass anInterface) { checkModify(); } /** * Returns an array containing CtField objects * representing all the public fields of the class. * That array includes public fields inherited from the * superclasses. */ public CtField[] getFields() { return new CtField[0]; } /** * Returns the field with the specified name. The returned field * may be a private field declared in a super class or interface. */ public CtField getField(String name) throws NotFoundException { throw new NotFoundException(name); } /** * Gets all the fields declared in the class. The inherited fields * are not included. * *

Note: the result does not include inherited fields. */ public CtField[] getDeclaredFields() { return new CtField[0]; } /** * Retrieves the field with the specified name among the fields * declared in the class. * *

Note: this method does not search the superclasses. */ public CtField getDeclaredField(String name) throws NotFoundException { throw new NotFoundException(name); } /** * Gets all the constructors and methods declared in the class. */ public CtBehavior[] getDeclaredBehaviors() { return new CtBehavior[0]; } /** * Returns an array containing CtConstructor objects * representing all the public constructors of the class. */ public CtConstructor[] getConstructors() { return new CtConstructor[0]; } /** * Returns the constructor with the given signature, * which is represented by a character string * called method descriptor. * For details of the method descriptor, see the JVM specification * or javassist.bytecode.Descriptor. * * @param name method name * @param desc method descriptor * @see javassist.bytecode.Descriptor */ public CtConstructor getConstructor(String desc) throws NotFoundException { throw new NotFoundException("no such a constructor"); } /** * Gets all the constructors declared in the class. * * @see javassist.CtConstructor */ public CtConstructor[] getDeclaredConstructors() { return new CtConstructor[0]; } /** * Returns a constructor receiving the specified parameters. * * @param params parameter types. */ public CtConstructor getDeclaredConstructor(CtClass[] params) throws NotFoundException { String desc = Descriptor.ofConstructor(params); return getConstructor(desc); } /** * Gets the class initializer (static constructor) * declared in the class. * This method returns null if * no class initializer is not declared. * * @see javassist.CtConstructor */ public CtConstructor getClassInitializer() { return null; } /** * Returns an array containing CtMethod objects * representing all the public methods of the class. * That array includes public methods inherited from the * superclasses. */ public CtMethod[] getMethods() { return new CtMethod[0]; } /** * Returns the method with the given name and signature. * The returned method may be declared in a super class. * The method signature is represented by a character string * called method descriptor, * which is defined in the JVM specification. * * @param name method name * @param desc method descriptor * @see javassist.bytecode.Descriptor */ public CtMethod getMethod(String name, String desc) throws NotFoundException { throw new NotFoundException(name); } /** * Gets all methods declared in the class. The inherited methods * are not included. * * @see javassist.CtMethod */ public CtMethod[] getDeclaredMethods() { return new CtMethod[0]; } /** * Retrieves the method with the specified name and parameter types * among the methods declared in the class. * *

Note: this method does not search the superclasses. * * @param name method name * @param params parameter types * @see javassist.CtMethod */ public CtMethod getDeclaredMethod(String name, CtClass[] params) throws NotFoundException { throw new NotFoundException(name); } /** * Retrieves the method with the specified name among the methods * declared in the class. If there are multiple methods with * the specified name, then this method returns one of them. * *

Note: this method does not search the superclasses. * * @see javassist.CtMethod */ public CtMethod getDeclaredMethod(String name) throws NotFoundException { throw new NotFoundException(name); } /** * Adds a constructor. */ public void addConstructor(CtConstructor c) throws CannotCompileException { checkModify(); } /** * Adds a method. */ public void addMethod(CtMethod m) throws CannotCompileException { checkModify(); } /** * Adds a field. * *

The CtField belonging to another * CtClass cannot be directly added to this class. * Only a field created for this class can be added. * * @see javassist.CtField#CtField(CtField,CtClass) */ public void addField(CtField f) throws CannotCompileException { addField(f, (CtField.Initializer)null); } /** * Adds a field with an initial value. * *

The CtField belonging to another * CtClass cannot be directly added to this class. * Only a field created for this class can be added. * *

The initial value is given as an expression written in Java. * Any regular Java expression can be used for specifying the initial * value. The followings are examples. * *

* *

Here, the type of variable cc is CtClass. * The type of f is CtField. * * @param init an expression for the initial value. * * @see javassist.CtField.Initializer#byExpr(String) * @see javassist.CtField#CtField(CtField,CtClass) */ public void addField(CtField f, String init) throws CannotCompileException { checkModify(); } /** * Adds a field with an initial value. * *

The CtField belonging to another * CtClass cannot be directly added to this class. * Only a field created for this class can be added. * *

For example, * *

* *

This code adds an int field named "i". The * initial value of this field is 1. * * @param init specifies the initial value of the field. * * @see javassist.CtField#CtField(CtField,CtClass) */ public void addField(CtField f, CtField.Initializer init) throws CannotCompileException { checkModify(); } /** * Obtains an attribute with the given name. * If that attribute is not found in the class file, this * method returns null. * * @param name attribute name */ public byte[] getAttribute(String name) { return null; } /** * Adds a named attribute. * An arbitrary data (smaller than 64Kb) can be saved in the class * file. Some attribute name are reserved by the JVM. * The attributes with the non-reserved names are ignored when a * class file is loaded into the JVM. * If there is already an attribute with * the same name, this method substitutes the new one for it. * * @param name attribute name * @param data attribute value */ public void setAttribute(String name, byte[] data) { checkModify(); } /** * Applies the given converter to all methods and constructors * declared in the class. This method calls instrument() * on every CtMethod and CtConstructor object * in the class. * * @param converter specifies how to modify. */ public void instrument(CodeConverter converter) throws CannotCompileException { checkModify(); } /** * Modifies the bodies of all methods and constructors * declared in the class. This method calls instrument() * on every CtMethod and CtConstructor object * in the class. * * @param editor specifies how to modify. */ public void instrument(ExprEditor editor) throws CannotCompileException { checkModify(); } /** * Converts this class to a java.lang.Class object. * Once this method is called, further modifications are not * possible any more. * *

This method is equivalent to: *

* *

See the description of ClassPool.writeAsClass() * before you use this method. * * @see javassist.ClassPool#writeAsClass(String) * @see javassist.ClassPool#forName(String) */ public Class toClass() throws NotFoundException, IOException, CannotCompileException { return getClassPool2().writeAsClass(getName()); } /** * Converts this class to a class file. * Once this method is called, further modifications are not * possible any more. * *

This method is equivalent to: *

* * @see javassist.ClassPool#write(String) */ public byte[] toBytecode() throws NotFoundException, IOException, CannotCompileException { return getClassPool2().write(getName()); } /** * Writes a class file represented by this CtClass * object in the current directory. * Once this method is called, further modifications are not * possible any more. * *

This method is equivalent to: *

* * @see javassist.ClassPool#writeFile(String) */ public void writeFile() throws NotFoundException, IOException, CannotCompileException { getClassPool2().writeFile(getName()); } private ClassPool getClassPool2() throws CannotCompileException { ClassPool cp = getClassPool(); if (cp == null) throw new CannotCompileException( "no ClassPool found. not a class?"); else return cp; } /** * Converts this class to a class file. * Once this method is called, further modifications are not * possible any more. * *

If this method is used to obtain a byte array representing * the class file, Translator.onWrite() is never * called on this class. ClassPool.write() should * be used. * *

This method dose not close the output stream in the end. * * @param out the output stream that a class file is written to. */ void toBytecode(DataOutputStream out) throws CannotCompileException, IOException { throw new CannotCompileException("not a class"); } }