/*
* 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 All the class names appearing in the class file are tested
* with This method may return 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 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 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 The 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 The For example,
*
* This code adds an This method is equivalent to:
* See the description of This method is equivalent to:
* This method is equivalent to:
* If this method is used to obtain a byte array representing
* the class file, 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");
}
}
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
.
*
* 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.
*
* 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.
*
* 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.
*
* 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.
*
* 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.
*
* CtField
belonging to another
* CtClass
cannot be directly added to this class.
* Only a field created for this class can be added.
*
*
* cc.addField(f, "0") // the initial value is 0.
* cc.addField(f, "i + 1") // i + 1.
* cc.addField(f, "new Point()"); // a Point object.
*
*
* 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.
*
* CtField
belonging to another
* CtClass
cannot be directly added to this class.
* Only a field created for this class can be added.
*
*
* CtClass cc = ...;
* addField(new CtField(CtClass.intType, "i", cc),
* CtField.Initializer.constant(1));
*
*
* 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.getClassPool().writeAsClass(this.getName())
*
* 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.getClassPool().write(this.getName())
*
* @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.getClassPool().writeFile(this.getName())
*
* @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.
*
* Translator.onWrite()
is never
* called on this class. ClassPool.write()
should
* be used.
*
*