You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1558 lines
51 KiB
1558 lines
51 KiB
/* |
|
* Javassist, a Java-bytecode translator toolkit. |
|
* Copyright (C) 1999- 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, |
|
* or the Apache License Version 2.0. |
|
* |
|
* 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 com.fr.third.javassist; |
|
|
|
import java.io.BufferedOutputStream; |
|
import java.io.ByteArrayOutputStream; |
|
import java.io.DataOutputStream; |
|
import java.io.File; |
|
import java.io.FileOutputStream; |
|
import java.io.IOException; |
|
import java.io.OutputStream; |
|
import java.net.URL; |
|
import java.security.ProtectionDomain; |
|
import java.util.Collection; |
|
|
|
import com.fr.third.javassist.bytecode.AttributeInfo; |
|
import com.fr.third.javassist.compiler.AccessorMaker; |
|
import com.fr.third.javassist.bytecode.ClassFile; |
|
import com.fr.third.javassist.bytecode.Descriptor; |
|
import com.fr.third.javassist.bytecode.Opcode; |
|
import com.fr.third.javassist.bytecode.SignatureAttribute; |
|
import com.fr.third.javassist.expr.ExprEditor; |
|
|
|
/* Note: |
|
* |
|
* This class is an abstract class and several methods just return null |
|
* or throw an exception. Those methods are overridden in subclasses |
|
* of this class. Read the source code of CtClassType if you are |
|
* interested in the implementation of Javassist. |
|
* |
|
* Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray. |
|
*/ |
|
|
|
/** |
|
* An instance of <code>CtClass</code> represents a class. |
|
* It is obtained from <code>ClassPool</code>. |
|
* |
|
* @see com.fr.third.javassist.ClassPool#get(String) |
|
*/ |
|
public abstract class CtClass { |
|
protected String qualifiedName; |
|
|
|
/** |
|
* If the value of this field is not null, then all class |
|
* files modified by Javassist are saved under the directory |
|
* specified by this variable. For example, if the value is |
|
* <code>"./debug"</code>, then all class files are saved |
|
* there. The directory name must not end with a directory |
|
* separator such as <code>/</code>. |
|
* |
|
* <p>The default value is null. |
|
* |
|
* @see #debugWriteFile(String) |
|
* @since 3.16 |
|
*/ |
|
public static String debugDump = null; |
|
|
|
/** |
|
* The version number of this release. |
|
*/ |
|
public static final String version = "3.18.2-GA"; |
|
|
|
/** |
|
* Prints the version number and the copyright notice. |
|
* |
|
* <p>The following command invokes this method: |
|
* |
|
* <ul><pre>java -jar javassist.jar</pre></ul> |
|
*/ |
|
public static void main(String[] args) { |
|
System.out.println("Javassist version " + CtClass.version); |
|
System.out.println("Copyright (C) 1999-2014 Shigeru Chiba." |
|
+ " All Rights Reserved."); |
|
} |
|
|
|
static final String javaLangObject = "java.lang.Object"; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>boolean</code> type. |
|
*/ |
|
public static CtClass booleanType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>char</code> type. |
|
*/ |
|
public static CtClass charType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>byte</code> type. |
|
*/ |
|
public static CtClass byteType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>short</code> type. |
|
*/ |
|
public static CtClass shortType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>int</code> type. |
|
*/ |
|
public static CtClass intType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>long</code> type. |
|
*/ |
|
public static CtClass longType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>float</code> type. |
|
*/ |
|
public static CtClass floatType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>double</code> type. |
|
*/ |
|
public static CtClass doubleType; |
|
|
|
/** |
|
* The <code>CtClass</code> object representing |
|
* the <code>void</code> 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; |
|
} |
|
|
|
/** |
|
* Converts the object to a string. |
|
*/ |
|
public String toString() { |
|
StringBuffer buf = new StringBuffer(getClass().getName()); |
|
buf.append("@"); |
|
buf.append(Integer.toHexString(hashCode())); |
|
buf.append("["); |
|
extendToString(buf); |
|
buf.append("]"); |
|
return buf.toString(); |
|
} |
|
|
|
/** |
|
* Implemented in subclasses to add to the {@link #toString()} result. |
|
* Subclasses should put a space before each token added to the buffer. |
|
*/ |
|
protected void extendToString(StringBuffer buffer) { |
|
buffer.append(getName()); |
|
} |
|
|
|
/** |
|
* Returns a <code>ClassPool</code> for this class. |
|
*/ |
|
public com.fr.third.javassist.ClassPool getClassPool() { return null; } |
|
|
|
/** |
|
* Returns a class file for this class. |
|
* |
|
* <p>This method is not available if <code>isFrozen()</code> |
|
* is true. |
|
*/ |
|
public ClassFile getClassFile() { |
|
checkModify(); |
|
return getClassFile2(); |
|
} |
|
|
|
/** |
|
* Returns a class file for this class (read only). |
|
* Normal applications do not need calling this method. Use |
|
* <code>getClassFile()</code>. |
|
* |
|
* <p>The <code>ClassFile</code> object obtained by this method |
|
* is read only. Changes to this object might not be reflected |
|
* on a class file generated by <code>toBytecode()</code>, |
|
* <code>toClass()</code>, etc. |
|
* |
|
* <p>This method is available even if <code>isFrozen()</code> |
|
* is true. However, if the class is frozen, it might be also |
|
* pruned. |
|
* |
|
* @see CtClass#getClassFile() |
|
* @see CtClass#isFrozen() |
|
* @see CtClass#prune() |
|
*/ |
|
public ClassFile getClassFile2() { return null; } |
|
|
|
/** |
|
* Undocumented method. Do not use; internal-use only. |
|
*/ |
|
public AccessorMaker getAccessorMaker() { |
|
return null; |
|
} |
|
|
|
/** |
|
* Returns the uniform resource locator (URL) of the class file. |
|
*/ |
|
public URL getURL() throws NotFoundException { |
|
throw new NotFoundException(getName()); |
|
} |
|
|
|
/** |
|
* Returns true if the definition of the class has been modified. |
|
*/ |
|
public boolean isModified() { return false; } |
|
|
|
/** |
|
* Returns true if the class has been loaded or written out |
|
* and thus it cannot be modified any more. |
|
* |
|
* @see #defrost() |
|
* @see #detach() |
|
*/ |
|
public boolean isFrozen() { return true; } |
|
|
|
/** |
|
* Makes the class frozen. |
|
* |
|
* @see #isFrozen() |
|
* @see #defrost() |
|
* @since 3.6 |
|
*/ |
|
public void freeze() {} |
|
|
|
/* Note: this method is overridden by CtClassType |
|
*/ |
|
void checkModify() throws RuntimeException { |
|
if (isFrozen()) |
|
throw new RuntimeException(getName() + " class is frozen"); |
|
|
|
// isModified() must return true after this method is invoked. |
|
} |
|
|
|
/** |
|
* Defrosts the class so that the class can be modified again. |
|
* |
|
* <p>To avoid changes that will be 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. |
|
* |
|
* <p>If <code>defrost()</code> will be called later, pruning |
|
* must be disallowed in advance. |
|
* |
|
* @see #isFrozen() |
|
* @see #stopPruning(boolean) |
|
* @see #detach() |
|
*/ |
|
public void defrost() { |
|
throw new RuntimeException("cannot defrost " + getName()); |
|
} |
|
|
|
/** |
|
* Returns <code>true</code> if this object represents a primitive |
|
* Java type: boolean, byte, char, short, int, long, float, double, |
|
* or void. |
|
*/ |
|
public boolean isPrimitive() { return false; } |
|
|
|
/** |
|
* Returns <code>true</code> 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 <code>null</code>. |
|
*/ |
|
public CtClass getComponentType() throws NotFoundException { |
|
return null; |
|
} |
|
|
|
/** |
|
* Returns <code>true</code> if this class extends or implements |
|
* <code>clazz</code>. It also returns <code>true</code> if |
|
* this class is the same as <code>clazz</code>. |
|
*/ |
|
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 <code>null</code>. |
|
*/ |
|
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; |
|
} |
|
|
|
/** |
|
* Returns the generic signature of the class. |
|
* |
|
* <p>The generics of Java is implemented by the erasure technique. |
|
* After compilation, all type parameters are dropped off from the |
|
* main part of a class file. However, for reflection, the type |
|
* parameters are encoded into generic signatures and attached |
|
* to a class file. |
|
* |
|
* @return null if the generic signature is not included. |
|
* @see SignatureAttribute#toClassSignature(String) |
|
* @see CtMember#getGenericSignature() |
|
* @since 3.17 |
|
*/ |
|
public String getGenericSignature() { return null; } |
|
|
|
/** |
|
* Sets the generic signature of the class. |
|
* |
|
* <p>The generics of Java is implemented by the erasure technique. |
|
* After compilation, all type parameters are dropped off from the |
|
* main part of a class file. However, for reflection, the type |
|
* parameters must be encoded into generic signatures and attached |
|
* to a class file. |
|
* |
|
* <p>For example, |
|
* |
|
* <pre>class List<T> { |
|
* T value; |
|
* T get() { return value; } |
|
* void set(T v) { value = v; } |
|
* } |
|
* </pre> |
|
* |
|
* <p>this class is generated by the following code: |
|
* |
|
* <pre> |
|
* ClassPool pool = ClassPool.getDefault(); |
|
* CtClass cc = pool.makeClass("List"); |
|
* CtClass objectClass = pool.get(CtClass.javaLangObject); |
|
* ClassSignature cs = new ClassSignature( |
|
* new TypeParameter[] { new TypeParameter("T") }); |
|
* cc.setGenericSignature(cs.encode()); // <T:Ljava/lang/Object;>Ljava/lang/Object; |
|
* |
|
* CtField f = new CtField(objClass, "value", cc); |
|
* TypeVariable tvar = new TypeVariable("T"); |
|
* f.setGenericSignature(tvar.encode()); // TT; |
|
* cc.addField(f); |
|
* |
|
* CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc); |
|
* MethodSignature ms = new MethodSignature(null, null, tvar, null); |
|
* m.setGenericSignature(ms.encode()); // ()TT; |
|
* cc.addMethod(m); |
|
* |
|
* CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc); |
|
* MethodSignature ms2 = new MethodSignature(null, new Type[] { tvar }, |
|
* new BaseType("void"), null); |
|
* m2.setGenericSignature(ms2.encode()); // (TT;)V; |
|
* cc.addMethod(m2); |
|
* |
|
* cc.writeFile(); |
|
* </pre> |
|
* |
|
* <p>The generated class file is equivalent to the following: |
|
* |
|
* <pre>class List { |
|
* Object value; |
|
* Object get() { return value; } |
|
* void set(Object v) { value = v; } |
|
* }</pre> |
|
* |
|
* <p>but it includes generic signatures for the class, the field, |
|
* and the methods so that the type variable <code>T</code> can be |
|
* accessible through reflection. |
|
* |
|
* @param sig a generic signature. |
|
* @see SignatureAttribute.ClassSignature#encode() |
|
* @see SignatureAttribute.MethodSignature#encode() |
|
* @see CtMember#setGenericSignature(String) |
|
* @since 3.17 |
|
*/ |
|
public void setGenericSignature(String sig) { checkModify(); } |
|
|
|
/** |
|
* Substitutes <code>newName</code> for all occurrences of a class |
|
* name <code>oldName</code> 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 <code>map</code>. |
|
* |
|
* <p>All the class names appearing in the class file are tested |
|
* with <code>map</code> 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 <code>ClassMap</code> so that <code>get()</code> |
|
* 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(com.fr.third.javassist.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. |
|
* |
|
* <p>This method may return <code>null</code>. |
|
* |
|
* @return a <code>Collection<String></code> object. |
|
*/ |
|
public synchronized Collection getRefClasses() { |
|
ClassFile cf = getClassFile2(); |
|
if (cf != null) { |
|
com.fr.third.javassist.ClassMap cm = new com.fr.third.javassist.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.getRefClasses(cm); |
|
return cm.values(); |
|
} |
|
else |
|
return null; |
|
} |
|
|
|
/** |
|
* Determines whether this object represents a class or an interface. |
|
* It returns <code>true</code> if this object represents an interface. |
|
*/ |
|
public boolean isInterface() { |
|
return false; |
|
} |
|
|
|
/** |
|
* Determines whether this object represents an annotation type. |
|
* It returns <code>true</code> if this object represents an annotation type. |
|
* |
|
* @since 3.2 |
|
*/ |
|
public boolean isAnnotation() { |
|
return false; |
|
} |
|
|
|
/** |
|
* Determines whether this object represents an enum. |
|
* It returns <code>true</code> if this object represents an enum. |
|
* |
|
* @since 3.2 |
|
*/ |
|
public boolean isEnum() { |
|
return false; |
|
} |
|
|
|
/** |
|
* Returns the modifiers for this class, encoded in an integer. |
|
* For decoding, use <code>javassist.Modifier</code>. |
|
* |
|
* <p>If the class is a static nested class (a.k.a. static inner class), |
|
* the returned modifiers include <code>Modifier.STATIC</code>. |
|
* |
|
* @see Modifier |
|
*/ |
|
public int getModifiers() { |
|
return 0; |
|
} |
|
|
|
/** |
|
* Returns true if the class has the specified annotation class. |
|
* |
|
* @param clz the annotation class. |
|
* @return <code>true</code> if the annotation is found, otherwise <code>false</code>. |
|
* @since 3.11 |
|
*/ |
|
public boolean hasAnnotation(Class clz) { |
|
return false; |
|
} |
|
|
|
/** |
|
* Returns the annotation if the class has the specified annotation class. |
|
* For example, if an annotation <code>@Author</code> is associated |
|
* with this class, an <code>Author</code> object is returned. |
|
* The member values can be obtained by calling methods on |
|
* the <code>Author</code> object. |
|
* |
|
* @param clz the annotation class. |
|
* @return the annotation if found, otherwise <code>null</code>. |
|
* @since 3.11 |
|
*/ |
|
public Object getAnnotation(Class clz) throws ClassNotFoundException { |
|
return null; |
|
} |
|
|
|
/** |
|
* Returns the annotations associated with this class. |
|
* For example, if an annotation <code>@Author</code> is associated |
|
* with this class, the returned array contains an <code>Author</code> |
|
* object. The member values can be obtained by calling methods on |
|
* the <code>Author</code> object. |
|
* |
|
* @return an array of annotation-type objects. |
|
* @see CtMember#getAnnotations() |
|
* @since 3.1 |
|
*/ |
|
public Object[] getAnnotations() throws ClassNotFoundException { |
|
return new Object[0]; |
|
} |
|
|
|
/** |
|
* Returns the annotations associated with this class. |
|
* This method is equivalent to <code>getAnnotations()</code> |
|
* except that, if any annotations are not on the classpath, |
|
* they are not included in the returned array. |
|
* |
|
* @return an array of annotation-type objects. |
|
* @see #getAnnotations() |
|
* @see CtMember#getAvailableAnnotations() |
|
* @since 3.3 |
|
*/ |
|
public Object[] getAvailableAnnotations(){ |
|
return new Object[0]; |
|
} |
|
|
|
/** |
|
* Returns an array of nested classes declared in the class. |
|
* Nested classes are inner classes, anonymous classes, local classes, |
|
* and static nested classes. This simply calls <code>getNestedClasses()</code>. |
|
* |
|
* @see #getNestedClasses() |
|
* @since 3.15 |
|
*/ |
|
public CtClass[] getDeclaredClasses() throws NotFoundException { |
|
return getNestedClasses(); |
|
} |
|
|
|
/** |
|
* Returns an array of nested classes declared in the class. |
|
* Nested classes are inner classes, anonymous classes, local classes, |
|
* and static nested classes. |
|
* |
|
* @since 3.2 |
|
*/ |
|
public CtClass[] getNestedClasses() throws NotFoundException { |
|
return new CtClass[0]; |
|
} |
|
|
|
/** |
|
* Sets the modifiers. |
|
* |
|
* <p>If the class is a nested class, this method also modifies |
|
* the class declaring that nested class (i.e. the enclosing |
|
* class is modified). |
|
* |
|
* @param mod modifiers encoded by |
|
* <code>javassist.Modifier</code> |
|
* @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. |
|
* |
|
* <p>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 this object represents the |
|
* <code>java.lang.Object</code> class and thus it does not have |
|
* the super class. |
|
* |
|
* <p>If this object represents an interface, this method |
|
* always returns the <code>java.lang.Object</code> class. |
|
* To obtain the super interfaces |
|
* extended by that interface, call <code>getInterfaces()</code>. |
|
*/ |
|
public CtClass getSuperclass() throws NotFoundException { |
|
return null; |
|
} |
|
|
|
/** |
|
* Changes a super class unless this object represents an interface. |
|
* The new super class must be compatible with the old one; for example, |
|
* it should inherit from the old super class. |
|
* |
|
* <p>If this object represents an interface, this method is equivalent |
|
* to <code>addInterface()</code>; it appends <code>clazz</code> to |
|
* the list of the super interfaces extended by that interface. |
|
* Note that an interface can extend multiple super interfaces. |
|
* |
|
* @see #replaceClassName(String, String) |
|
* @see #replaceClassName(ClassMap) |
|
*/ |
|
public void setSuperclass(CtClass clazz) throws com.fr.third.javassist.CannotCompileException { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Obtains the class objects representing the interfaces implemented |
|
* by the class or, if this object represents an interface, the interfaces |
|
* extended by that interface. |
|
*/ |
|
public CtClass[] getInterfaces() throws NotFoundException { |
|
return new CtClass[0]; |
|
} |
|
|
|
/** |
|
* Sets implemented interfaces. If this object represents an interface, |
|
* this method sets the interfaces extended by that interface. |
|
* |
|
* @param list a list of the <code>CtClass</code> objects |
|
* representing interfaces, or |
|
* <code>null</code> 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(); |
|
} |
|
|
|
/** |
|
* If this class is a member class or interface of another class, |
|
* then the class enclosing this class is returned. |
|
* |
|
* @return null if this class is a top-level class or an anonymous class. |
|
*/ |
|
public CtClass getDeclaringClass() throws NotFoundException { |
|
return null; |
|
} |
|
|
|
/** |
|
* Returns the immediately enclosing method of this class. |
|
* This method works only with JDK 1.5 or later. |
|
* |
|
* @return null if this class is not a local class or an anonymous |
|
* class. |
|
*/ |
|
public CtMethod getEnclosingMethod() throws NotFoundException { |
|
return null; |
|
} |
|
|
|
/** |
|
* Makes a new public nested class. If this method is called, |
|
* the <code>CtClass</code>, which encloses the nested class, is modified |
|
* since a class file includes a list of nested classes. |
|
* |
|
* <p>The current implementation only supports a static nested class. |
|
* <code>isStatic</code> must be true. |
|
* |
|
* @param name the simple name of the nested class. |
|
* @param isStatic true if the nested class is static. |
|
*/ |
|
public CtClass makeNestedClass(String name, boolean isStatic) { |
|
throw new RuntimeException(getName() + " is not a class"); |
|
} |
|
|
|
/** |
|
* Returns an array containing <code>CtField</code> objects |
|
* representing all the non-private fields of the class. |
|
* That array includes non-private 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 { |
|
return getField(name, null); |
|
} |
|
|
|
/** |
|
* Returns the field with the specified name and type. The returned field |
|
* may be a private field declared in a super class or interface. |
|
* Unlike Java, the JVM allows a class to have |
|
* multiple fields with the same name but different types. |
|
* |
|
* @param name the field name. |
|
* @param desc the type descriptor of the field. It is available by |
|
* {@link CtField#getSignature()}. |
|
* @see CtField#getSignature() |
|
*/ |
|
public CtField getField(String name, String desc) throws NotFoundException { |
|
throw new NotFoundException(name); |
|
} |
|
|
|
/** |
|
* @return null if the specified field is not found. |
|
*/ |
|
CtField getField2(String name, String desc) { return null; } |
|
|
|
/** |
|
* Gets all the fields declared in the class. The inherited fields |
|
* are not included. |
|
* |
|
* <p>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. |
|
* |
|
* <p>Note: this method does not search the super classes. |
|
*/ |
|
public CtField getDeclaredField(String name) throws NotFoundException { |
|
throw new NotFoundException(name); |
|
} |
|
|
|
/** |
|
* Retrieves the field with the specified name and type among the fields |
|
* declared in the class. Unlike Java, the JVM allows a class to have |
|
* multiple fields with the same name but different types. |
|
* |
|
* <p>Note: this method does not search the super classes. |
|
* |
|
* @param name the field name. |
|
* @param desc the type descriptor of the field. It is available by |
|
* {@link CtField#getSignature()}. |
|
* @see CtField#getSignature() |
|
*/ |
|
public CtField getDeclaredField(String name, String desc) throws NotFoundException { |
|
throw new NotFoundException(name); |
|
} |
|
|
|
/** |
|
* Gets all the constructors and methods declared in the class. |
|
*/ |
|
public com.fr.third.javassist.CtBehavior[] getDeclaredBehaviors() { |
|
return new com.fr.third.javassist.CtBehavior[0]; |
|
} |
|
|
|
/** |
|
* Returns an array containing <code>CtConstructor</code> objects |
|
* representing all the non-private 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 <code>javassist.bytecode.Descriptor</code>. |
|
* |
|
* @param desc method descriptor |
|
* @see Descriptor |
|
*/ |
|
public CtConstructor getConstructor(String desc) |
|
throws NotFoundException |
|
{ |
|
throw new NotFoundException("no such constructor"); |
|
} |
|
|
|
/** |
|
* Gets all the constructors declared in the class. |
|
* |
|
* @see 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 <code>null</code> if |
|
* no class initializer is not declared. |
|
* |
|
* @see #makeClassInitializer() |
|
* @see CtConstructor |
|
*/ |
|
public CtConstructor getClassInitializer() { |
|
return null; |
|
} |
|
|
|
/** |
|
* Returns an array containing <code>CtMethod</code> objects |
|
* representing all the non-private methods of the class. |
|
* That array includes non-private 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 CtBehavior#getSignature() |
|
* @see 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 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. |
|
* |
|
* <p>Note: this method does not search the superclasses. |
|
* |
|
* @param name method name |
|
* @param params parameter types |
|
* @see 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. |
|
* |
|
* <p>Note: this method does not search the superclasses. |
|
* |
|
* @see CtMethod |
|
*/ |
|
public CtMethod getDeclaredMethod(String name) throws NotFoundException { |
|
throw new NotFoundException(name); |
|
} |
|
|
|
/** |
|
* Makes an empty class initializer (static constructor). |
|
* If the class already includes a class initializer, |
|
* this method returns it. |
|
* |
|
* @see #getClassInitializer() |
|
*/ |
|
public CtConstructor makeClassInitializer() |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
throw new com.fr.third.javassist.CannotCompileException("not a class"); |
|
} |
|
|
|
/** |
|
* Adds a constructor. To add a class initializer (static constructor), |
|
* call <code>makeClassInitializer()</code>. |
|
* |
|
* @see #makeClassInitializer() |
|
*/ |
|
public void addConstructor(CtConstructor c) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Removes a constructor declared in this class. |
|
* |
|
* @param c removed constructor. |
|
* @throws NotFoundException if the constructor is not found. |
|
*/ |
|
public void removeConstructor(CtConstructor c) throws NotFoundException { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Adds a method. |
|
*/ |
|
public void addMethod(CtMethod m) throws com.fr.third.javassist.CannotCompileException { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Removes a method declared in this class. |
|
* |
|
* @param m removed method. |
|
* @throws NotFoundException if the method is not found. |
|
*/ |
|
public void removeMethod(CtMethod m) throws NotFoundException { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Adds a field. |
|
* |
|
* <p>The <code>CtField</code> belonging to another |
|
* <code>CtClass</code> cannot be directly added to this class. |
|
* Only a field created for this class can be added. |
|
* |
|
* @see CtField#CtField(CtField,CtClass) |
|
*/ |
|
public void addField(CtField f) throws com.fr.third.javassist.CannotCompileException { |
|
addField(f, (CtField.Initializer)null); |
|
} |
|
|
|
/** |
|
* Adds a field with an initial value. |
|
* |
|
* <p>The <code>CtField</code> belonging to another |
|
* <code>CtClass</code> cannot be directly added to this class. |
|
* Only a field created for this class can be added. |
|
* |
|
* <p>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. |
|
* |
|
* <ul><pre> |
|
* cc.addField(f, "0") // the initial value is 0. |
|
* cc.addField(f, "i + 1") // i + 1. |
|
* cc.addField(f, "new Point()"); // a Point object. |
|
* </pre></ul> |
|
* |
|
* <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>. |
|
* The type of <code>f</code> is <code>CtField</code>. |
|
* |
|
* <p>Note: do not change the modifier of the field |
|
* (in particular, do not add or remove <code>static</code> |
|
* to/from the modifier) |
|
* after it is added to the class by <code>addField()</code>. |
|
* |
|
* @param init an expression for the initial value. |
|
* |
|
* @see CtField.Initializer#byExpr(String) |
|
* @see CtField#CtField(CtField,CtClass) |
|
*/ |
|
public void addField(CtField f, String init) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Adds a field with an initial value. |
|
* |
|
* <p>The <code>CtField</code> belonging to another |
|
* <code>CtClass</code> cannot be directly added to this class. |
|
* Only a field created for this class can be added. |
|
* |
|
* <p>For example, |
|
* |
|
* <ul><pre> |
|
* CtClass cc = ...; |
|
* addField(new CtField(CtClass.intType, "i", cc), |
|
* CtField.Initializer.constant(1)); |
|
* </pre></ul> |
|
* |
|
* <p>This code adds an <code>int</code> field named "i". The |
|
* initial value of this field is 1. |
|
* |
|
* @param init specifies the initial value of the field. |
|
* |
|
* @see CtField#CtField(CtField,CtClass) |
|
*/ |
|
public void addField(CtField f, CtField.Initializer init) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Removes a field declared in this class. |
|
* |
|
* @param f removed field. |
|
* @throws NotFoundException if the field is not found. |
|
*/ |
|
public void removeField(CtField f) throws NotFoundException { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Obtains an attribute with the given name. |
|
* If that attribute is not found in the class file, this |
|
* method returns null. |
|
* |
|
* <p>This is a convenient method mainly for obtaining |
|
* a user-defined attribute. For dealing with attributes, see the |
|
* <code>javassist.bytecode</code> package. For example, the following |
|
* expression returns all the attributes of a class file. |
|
* |
|
* <ul><pre> |
|
* getClassFile().getAttributes() |
|
* </pre></ul> |
|
* |
|
* @param name attribute name |
|
* @see AttributeInfo |
|
*/ |
|
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. |
|
* |
|
* <p>This is a convenient method mainly for adding |
|
* a user-defined attribute. For dealing with attributes, see the |
|
* <code>javassist.bytecode</code> package. For example, the following |
|
* expression adds an attribute <code>info</code> to a class file. |
|
* |
|
* <ul><pre> |
|
* getClassFile().addAttribute(info) |
|
* </pre></ul> |
|
* |
|
* @param name attribute name |
|
* @param data attribute value |
|
* @see AttributeInfo |
|
*/ |
|
public void setAttribute(String name, byte[] data) { |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Applies the given converter to all methods and constructors |
|
* declared in the class. This method calls <code>instrument()</code> |
|
* on every <code>CtMethod</code> and <code>CtConstructor</code> object |
|
* in the class. |
|
* |
|
* @param converter specifies how to modify. |
|
*/ |
|
public void instrument(com.fr.third.javassist.CodeConverter converter) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Modifies the bodies of all methods and constructors |
|
* declared in the class. This method calls <code>instrument()</code> |
|
* on every <code>CtMethod</code> and <code>CtConstructor</code> object |
|
* in the class. |
|
* |
|
* @param editor specifies how to modify. |
|
*/ |
|
public void instrument(ExprEditor editor) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
checkModify(); |
|
} |
|
|
|
/** |
|
* Converts this class to a <code>java.lang.Class</code> object. |
|
* Once this method is called, further modifications are not |
|
* allowed any more. |
|
* To load the class, this method uses the context class loader |
|
* of the current thread. If the program is running on some application |
|
* server, the context class loader might be inappropriate to load the |
|
* class. |
|
* |
|
* <p>This method is provided for convenience. If you need more |
|
* complex functionality, you should write your own class loader. |
|
* |
|
* <p>Note: this method calls <code>toClass()</code> |
|
* in <code>ClassPool</code>. |
|
* |
|
* <p><b>Warining:</b> A Class object returned by this method may not |
|
* work with a security manager or a signed jar file because a |
|
* protection domain is not specified. |
|
* |
|
* @see #toClass(java.lang.ClassLoader,ProtectionDomain) |
|
* @see com.fr.third.javassist.ClassPool#toClass(CtClass) |
|
*/ |
|
public Class toClass() throws com.fr.third.javassist.CannotCompileException { |
|
return getClassPool().toClass(this); |
|
} |
|
|
|
/** |
|
* Converts this class to a <code>java.lang.Class</code> object. |
|
* Once this method is called, further modifications are not allowed |
|
* any more. |
|
* |
|
* <p>The class file represented by this <code>CtClass</code> is |
|
* loaded by the given class loader to construct a |
|
* <code>java.lang.Class</code> object. Since a private method |
|
* on the class loader is invoked through the reflection API, |
|
* the caller must have permissions to do that. |
|
* |
|
* <p>An easy way to obtain <code>ProtectionDomain</code> object is |
|
* to call <code>getProtectionDomain()</code> |
|
* in <code>java.lang.Class</code>. It returns the domain that |
|
* the class belongs to. |
|
* |
|
* <p>This method is provided for convenience. If you need more |
|
* complex functionality, you should write your own class loader. |
|
* |
|
* <p>Note: this method calls <code>toClass()</code> |
|
* in <code>ClassPool</code>. |
|
* |
|
* @param loader the class loader used to load this class. |
|
* If it is null, the class loader returned by |
|
* {@link com.fr.third.javassist.ClassPool#getClassLoader()} is used. |
|
* @param domain the protection domain that the class belongs to. |
|
* If it is null, the default domain created |
|
* by <code>java.lang.ClassLoader</code> is used. |
|
* @see com.fr.third.javassist.ClassPool#toClass(CtClass,java.lang.ClassLoader) |
|
* @since 3.3 |
|
*/ |
|
public Class toClass(ClassLoader loader, ProtectionDomain domain) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
com.fr.third.javassist.ClassPool cp = getClassPool(); |
|
if (loader == null) |
|
loader = cp.getClassLoader(); |
|
|
|
return cp.toClass(this, loader, domain); |
|
} |
|
|
|
/** |
|
* Converts this class to a <code>java.lang.Class</code> object. |
|
* |
|
* <p><b>Warining:</b> A Class object returned by this method may not |
|
* work with a security manager or a signed jar file because a |
|
* protection domain is not specified. |
|
* |
|
* @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)} |
|
*/ |
|
public final Class toClass(ClassLoader loader) |
|
throws com.fr.third.javassist.CannotCompileException |
|
{ |
|
return getClassPool().toClass(this, loader); |
|
} |
|
|
|
/** |
|
* Removes this <code>CtClass</code> object from the |
|
* <code>ClassPool</code>. |
|
* After this method is called, any method cannot be called on the |
|
* removed <code>CtClass</code> object. |
|
* |
|
* <p>If <code>get()</code> in <code>ClassPool</code> is called |
|
* with the name of the removed method, |
|
* the <code>ClassPool</code> will read the class file again |
|
* and constructs another <code>CtClass</code> object representing |
|
* the same class. |
|
*/ |
|
public void detach() { |
|
com.fr.third.javassist.ClassPool cp = getClassPool(); |
|
CtClass obj = cp.removeCached(getName()); |
|
if (obj != this) |
|
cp.cacheCtClass(getName(), obj, false); |
|
} |
|
|
|
/** |
|
* Disallows (or allows) automatically pruning this <code>CtClass</code> |
|
* object. |
|
* |
|
* <p> |
|
* Javassist can automatically prune a <code>CtClass</code> object |
|
* when <code>toBytecode()</code> (or <code>toClass()</code>, |
|
* <code>writeFile()</code>) is called. |
|
* Since a <code>ClassPool</code> holds all instances of <code>CtClass</code> |
|
* even after <code>toBytecode()</code> (or <code>toClass()</code>, |
|
* <code>writeFile()</code>) is called, pruning may significantly |
|
* save memory consumption. |
|
* |
|
* <p>If <code>ClassPool.doPruning</code> is true, the automatic pruning |
|
* is on by default. Otherwise, it is off. The default value of |
|
* <code>ClassPool.doPruning</code> is false. |
|
* |
|
* @param stop disallow pruning if true. Otherwise, allow. |
|
* @return the previous status of pruning. true if pruning is already stopped. |
|
* |
|
* @see #detach() |
|
* @see #prune() |
|
* @see com.fr.third.javassist.ClassPool#doPruning |
|
*/ |
|
public boolean stopPruning(boolean stop) { return true; } |
|
|
|
/** |
|
* Discards unnecessary attributes, in particular, |
|
* <code>CodeAttribute</code>s (method bodies) of the class, |
|
* to minimize the memory footprint. |
|
* After calling this method, the class is read only. |
|
* It cannot be modified any more. |
|
* Furthermore, <code>toBytecode()</code>, |
|
* <code>writeFile()</code>, <code>toClass()</code>, |
|
* or <code>instrument()</code> cannot be called. |
|
* However, the method names and signatures in the class etc. |
|
* are still accessible. |
|
* |
|
* <p><code>toBytecode()</code>, <code>writeFile()</code>, and |
|
* <code>toClass()</code> internally call this method if |
|
* automatic pruning is on. |
|
* |
|
* <p>According to some experiments, pruning does not really reduce |
|
* memory consumption. Only about 20%. Since pruning takes time, |
|
* it might not pay off. So the automatic pruning is off by default. |
|
* |
|
* @see #stopPruning(boolean) |
|
* @see #detach() |
|
* @see ClassPool#doPruning |
|
* |
|
* @see #toBytecode() |
|
* @see #toClass() |
|
* @see #writeFile() |
|
* @see #instrument(CodeConverter) |
|
* @see #instrument(ExprEditor) |
|
*/ |
|
public void prune() {} |
|
|
|
/* Called by get() in ClassPool. |
|
* CtClassType overrides this method. |
|
*/ |
|
void incGetCounter() {} |
|
|
|
/** |
|
* If this method is called, the class file will be |
|
* rebuilt when it is finally generated by |
|
* <code>toBytecode()</code> and <code>writeFile()</code>. |
|
* For a performance reason, the symbol table of the |
|
* class file may contain unused entries, for example, |
|
* after a method or a filed is deleted. |
|
* This method |
|
* removes those unused entries. This removal will |
|
* minimize the size of the class file. |
|
* |
|
* @since 3.8.1 |
|
*/ |
|
public void rebuildClassFile() {} |
|
|
|
/** |
|
* Converts this class to a class file. |
|
* Once this method is called, further modifications are not |
|
* possible any more. |
|
* |
|
* @return the contents of the class file. |
|
*/ |
|
public byte[] toBytecode() throws IOException, com.fr.third.javassist.CannotCompileException { |
|
ByteArrayOutputStream barray = new ByteArrayOutputStream(); |
|
DataOutputStream out = new DataOutputStream(barray); |
|
try { |
|
toBytecode(out); |
|
} |
|
finally { |
|
out.close(); |
|
} |
|
|
|
return barray.toByteArray(); |
|
} |
|
|
|
/** |
|
* Writes a class file represented by this <code>CtClass</code> |
|
* object in the current directory. |
|
* Once this method is called, further modifications are not |
|
* possible any more. |
|
* |
|
* @see #debugWriteFile() |
|
*/ |
|
public void writeFile() |
|
throws NotFoundException, IOException, com.fr.third.javassist.CannotCompileException |
|
{ |
|
writeFile("."); |
|
} |
|
|
|
/** |
|
* Writes a class file represented by this <code>CtClass</code> |
|
* object on a local disk. |
|
* Once this method is called, further modifications are not |
|
* possible any more. |
|
* |
|
* @param directoryName it must end without a directory separator. |
|
* @see #debugWriteFile(String) |
|
*/ |
|
public void writeFile(String directoryName) |
|
throws com.fr.third.javassist.CannotCompileException, IOException |
|
{ |
|
DataOutputStream out = makeFileOutput(directoryName); |
|
try { |
|
toBytecode(out); |
|
} |
|
finally { |
|
out.close(); |
|
} |
|
} |
|
|
|
protected DataOutputStream makeFileOutput(String directoryName) { |
|
String classname = getName(); |
|
String filename = directoryName + File.separatorChar |
|
+ classname.replace('.', File.separatorChar) + ".class"; |
|
int pos = filename.lastIndexOf(File.separatorChar); |
|
if (pos > 0) { |
|
String dir = filename.substring(0, pos); |
|
if (!dir.equals(".")) |
|
new File(dir).mkdirs(); |
|
} |
|
|
|
return new DataOutputStream(new BufferedOutputStream( |
|
new DelayedFileOutputStream(filename))); |
|
} |
|
|
|
/** |
|
* Writes a class file as <code>writeFile()</code> does although this |
|
* method does not prune or freeze the class after writing the class |
|
* file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> |
|
* is called, it cannot be called again since the class is pruned and frozen. |
|
* This method would be useful for debugging. |
|
*/ |
|
public void debugWriteFile() { |
|
debugWriteFile("."); |
|
} |
|
|
|
/** |
|
* Writes a class file as <code>writeFile()</code> does although this |
|
* method does not prune or freeze the class after writing the class |
|
* file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code> |
|
* is called, it cannot be called again since the class is pruned and frozen. |
|
* This method would be useful for debugging. |
|
* |
|
* @param directoryName it must end without a directory separator. |
|
*/ |
|
public void debugWriteFile(String directoryName) { |
|
try { |
|
boolean p = stopPruning(true); |
|
writeFile(directoryName); |
|
defrost(); |
|
stopPruning(p); |
|
} |
|
catch (Exception e) { |
|
throw new RuntimeException(e); |
|
} |
|
} |
|
|
|
static class DelayedFileOutputStream extends OutputStream { |
|
private FileOutputStream file; |
|
private String filename; |
|
|
|
DelayedFileOutputStream(String name) { |
|
file = null; |
|
filename = name; |
|
} |
|
|
|
private void init() throws IOException { |
|
if (file == null) |
|
file = new FileOutputStream(filename); |
|
} |
|
|
|
public void write(int b) throws IOException { |
|
init(); |
|
file.write(b); |
|
} |
|
|
|
public void write(byte[] b) throws IOException { |
|
init(); |
|
file.write(b); |
|
} |
|
|
|
public void write(byte[] b, int off, int len) throws IOException { |
|
init(); |
|
file.write(b, off, len); |
|
|
|
} |
|
|
|
public void flush() throws IOException { |
|
init(); |
|
file.flush(); |
|
} |
|
|
|
public void close() throws IOException { |
|
init(); |
|
file.close(); |
|
} |
|
} |
|
|
|
/** |
|
* Converts this class to a class file. |
|
* Once this method is called, further modifications are not |
|
* possible any more. |
|
* |
|
* <p>This method dose not close the output stream in the end. |
|
* |
|
* @param out the output stream that a class file is written to. |
|
*/ |
|
public void toBytecode(DataOutputStream out) |
|
throws com.fr.third.javassist.CannotCompileException, IOException |
|
{ |
|
throw new CannotCompileException("not a class"); |
|
} |
|
|
|
/** |
|
* Makes a unique member name. This method guarantees that |
|
* the returned name is not used as a prefix of any methods |
|
* or fields visible in this class. |
|
* If the returned name is XYZ, then any method or field names |
|
* in this class do not start with XYZ. |
|
* |
|
* @param prefix the prefix of the member name. |
|
*/ |
|
public String makeUniqueName(String prefix) { |
|
throw new RuntimeException("not available in " + getName()); |
|
} |
|
|
|
/* Invoked from ClassPool#compress(). |
|
* This method is overridden by CtClassType. |
|
*/ |
|
void compress() {} |
|
}
|
|
|