0001: /*
0002: * Javassist, a Java-bytecode translator toolkit.
0003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
0004: *
0005: * The contents of this file are subject to the Mozilla Public License Version
0006: * 1.1 (the "License"); you may not use this file except in compliance with
0007: * the License. Alternatively, the contents of this file may be used under
0008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
0009: *
0010: * Software distributed under the License is distributed on an "AS IS" basis,
0011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0012: * for the specific language governing rights and limitations under the
0013: * License.
0014: */
0015:
0016: package javassist;
0017:
0018: import java.io.BufferedOutputStream;
0019: import java.io.ByteArrayOutputStream;
0020: import java.io.DataOutputStream;
0021: import java.io.File;
0022: import java.io.FileOutputStream;
0023: import java.io.IOException;
0024: import java.io.OutputStream;
0025: import java.net.URL;
0026: import java.security.ProtectionDomain;
0027: import java.util.Collection;
0028: import javassist.bytecode.ClassFile;
0029: import javassist.bytecode.Descriptor;
0030: import javassist.bytecode.Opcode;
0031: import javassist.expr.ExprEditor;
0032:
0033: /* Note:
0034: *
0035: * This class is an abstract class and several methods just return null
0036: * or throw an exception. Those methods are overridden in subclasses
0037: * of this class. Read the source code of CtClassType if you are
0038: * interested in the implementation of Javassist.
0039: *
0040: * Subclasses of CtClass are CtClassType, CtPrimitiveType, and CtArray.
0041: */
0042:
0043: /**
0044: * An instance of <code>CtClass</code> represents a class.
0045: * It is obtained from <code>ClassPool</code>.
0046: *
0047: * @see ClassPool#get(String)
0048: */
0049: public abstract class CtClass {
0050: protected String qualifiedName;
0051:
0052: /**
0053: * The version number of this release.
0054: */
0055: public static final String version = "3.4";
0056:
0057: /**
0058: * Prints the version number and the copyright notice.
0059: *
0060: * <p>The following command invokes this method:
0061: *
0062: * <ul><pre>java -jar javassist.jar</pre></ul>
0063: */
0064: public static void main(String[] args) {
0065: System.out.println("Javassist version " + CtClass.version);
0066: System.out.println("Copyright (C) 1999-2006 Shigeru Chiba."
0067: + " All Rights Reserved.");
0068: }
0069:
0070: static final String javaLangObject = "java.lang.Object";
0071:
0072: /**
0073: * The <code>CtClass</code> object representing
0074: * the <code>boolean</code> type.
0075: */
0076: public static CtClass booleanType;
0077:
0078: /**
0079: * The <code>CtClass</code> object representing
0080: * the <code>char</code> type.
0081: */
0082: public static CtClass charType;
0083:
0084: /**
0085: * The <code>CtClass</code> object representing
0086: * the <code>byte</code> type.
0087: */
0088: public static CtClass byteType;
0089:
0090: /**
0091: * The <code>CtClass</code> object representing
0092: * the <code>short</code> type.
0093: */
0094: public static CtClass shortType;
0095:
0096: /**
0097: * The <code>CtClass</code> object representing
0098: * the <code>int</code> type.
0099: */
0100: public static CtClass intType;
0101:
0102: /**
0103: * The <code>CtClass</code> object representing
0104: * the <code>long</code> type.
0105: */
0106: public static CtClass longType;
0107:
0108: /**
0109: * The <code>CtClass</code> object representing
0110: * the <code>float</code> type.
0111: */
0112: public static CtClass floatType;
0113:
0114: /**
0115: * The <code>CtClass</code> object representing
0116: * the <code>double</code> type.
0117: */
0118: public static CtClass doubleType;
0119:
0120: /**
0121: * The <code>CtClass</code> object representing
0122: * the <code>void</code> type.
0123: */
0124: public static CtClass voidType;
0125:
0126: static CtClass[] primitiveTypes;
0127:
0128: static {
0129: primitiveTypes = new CtClass[9];
0130:
0131: booleanType = new CtPrimitiveType("boolean", 'Z',
0132: "java.lang.Boolean", "booleanValue", "()Z",
0133: Opcode.IRETURN, Opcode.T_BOOLEAN, 1);
0134: primitiveTypes[0] = booleanType;
0135:
0136: charType = new CtPrimitiveType("char", 'C',
0137: "java.lang.Character", "charValue", "()C",
0138: Opcode.IRETURN, Opcode.T_CHAR, 1);
0139: primitiveTypes[1] = charType;
0140:
0141: byteType = new CtPrimitiveType("byte", 'B', "java.lang.Byte",
0142: "byteValue", "()B", Opcode.IRETURN, Opcode.T_BYTE, 1);
0143: primitiveTypes[2] = byteType;
0144:
0145: shortType = new CtPrimitiveType("short", 'S',
0146: "java.lang.Short", "shortValue", "()S", Opcode.IRETURN,
0147: Opcode.T_SHORT, 1);
0148: primitiveTypes[3] = shortType;
0149:
0150: intType = new CtPrimitiveType("int", 'I', "java.lang.Integer",
0151: "intValue", "()I", Opcode.IRETURN, Opcode.T_INT, 1);
0152: primitiveTypes[4] = intType;
0153:
0154: longType = new CtPrimitiveType("long", 'J', "java.lang.Long",
0155: "longValue", "()J", Opcode.LRETURN, Opcode.T_LONG, 2);
0156: primitiveTypes[5] = longType;
0157:
0158: floatType = new CtPrimitiveType("float", 'F',
0159: "java.lang.Float", "floatValue", "()F", Opcode.FRETURN,
0160: Opcode.T_FLOAT, 1);
0161: primitiveTypes[6] = floatType;
0162:
0163: doubleType = new CtPrimitiveType("double", 'D',
0164: "java.lang.Double", "doubleValue", "()D",
0165: Opcode.DRETURN, Opcode.T_DOUBLE, 2);
0166: primitiveTypes[7] = doubleType;
0167:
0168: voidType = new CtPrimitiveType("void", 'V', "java.lang.Void",
0169: null, null, Opcode.RETURN, 0, 0);
0170: primitiveTypes[8] = voidType;
0171: }
0172:
0173: protected CtClass(String name) {
0174: qualifiedName = name;
0175: }
0176:
0177: /**
0178: * Converts the object to a string.
0179: */
0180: public String toString() {
0181: StringBuffer buf = new StringBuffer(getClass().getName());
0182: buf.append("@");
0183: buf.append(Integer.toHexString(hashCode()));
0184: buf.append("[");
0185: extendToString(buf);
0186: buf.append("]");
0187: return buf.toString();
0188: }
0189:
0190: /**
0191: * Implemented in subclasses to add to the {@link #toString()} result.
0192: * Subclasses should put a space before each token added to the buffer.
0193: */
0194: protected void extendToString(StringBuffer buffer) {
0195: buffer.append(getName());
0196: }
0197:
0198: /**
0199: * Returns a <code>ClassPool</code> for this class.
0200: */
0201: public ClassPool getClassPool() {
0202: return null;
0203: }
0204:
0205: /**
0206: * Returns a class file for this class.
0207: *
0208: * <p>This method is not available if <code>isFrozen()</code>
0209: * is true.
0210: */
0211: public ClassFile getClassFile() {
0212: checkModify();
0213: return getClassFile2();
0214: }
0215:
0216: /**
0217: * Returns a class file for this class (read only).
0218: * Normal applications do not need calling this method. Use
0219: * <code>getClassFile()</code>.
0220: *
0221: * <p>The <code>ClassFile</code> object obtained by this method
0222: * is read only. Changes to this object might not be reflected
0223: * on a class file generated by <code>toBytecode()</code>,
0224: * <code>toClass()</code>, etc.
0225: *
0226: * <p>This method is available even if <code>isFrozen()</code>
0227: * is true. However, if the class is frozen, it might be also
0228: * pruned.
0229: *
0230: * @see CtClass#getClassFile()
0231: * @see CtClass#isFrozen()
0232: * @see CtClass#prune()
0233: */
0234: public ClassFile getClassFile2() {
0235: return null;
0236: }
0237:
0238: /**
0239: * Undocumented method. Do not use; internal-use only.
0240: */
0241: public javassist.compiler.AccessorMaker getAccessorMaker() {
0242: return null;
0243: }
0244:
0245: /**
0246: * Returns the uniform resource locator (URL) of the class file.
0247: */
0248: public URL getURL() throws NotFoundException {
0249: throw new NotFoundException(getName());
0250: }
0251:
0252: /**
0253: * Returns true if the definition of the class has been modified.
0254: */
0255: public boolean isModified() {
0256: return false;
0257: }
0258:
0259: /**
0260: * Returns true if the class has been loaded or written out
0261: * and thus it cannot be modified any more.
0262: *
0263: * @see #defrost()
0264: * @see #detach()
0265: */
0266: public boolean isFrozen() {
0267: return true;
0268: }
0269:
0270: void freeze() {
0271: }
0272:
0273: /* Note: this method is overridden by CtClassType
0274: */
0275: void checkModify() throws RuntimeException {
0276: if (isFrozen())
0277: throw new RuntimeException(getName() + " class is frozen");
0278:
0279: // isModified() must return true after this method is invoked.
0280: }
0281:
0282: /**
0283: * Defrosts the class so that the class can be modified again.
0284: *
0285: * <p>To avoid changes that will be never reflected,
0286: * the class is frozen to be unmodifiable if it is loaded or
0287: * written out. This method should be called only in a case
0288: * that the class will be reloaded or written out later again.
0289: *
0290: * <p>If <code>defrost()</code> will be called later, pruning
0291: * must be disallowed in advance.
0292: *
0293: * @see #isFrozen()
0294: * @see #stopPruning(boolean)
0295: * @see #detach()
0296: */
0297: public void defrost() {
0298: throw new RuntimeException("cannot defrost " + getName());
0299: }
0300:
0301: /**
0302: * Returns <code>true</code> if this object represents a primitive
0303: * Java type: boolean, byte, char, short, int, long, float, double,
0304: * or void.
0305: */
0306: public boolean isPrimitive() {
0307: return false;
0308: }
0309:
0310: /**
0311: * Returns <code>true</code> if this object represents an array type.
0312: */
0313: public boolean isArray() {
0314: return false;
0315: }
0316:
0317: /**
0318: * If this object represents an array, this method returns the component
0319: * type of the array. Otherwise, it returns <code>null</code>.
0320: */
0321: public CtClass getComponentType() throws NotFoundException {
0322: return null;
0323: }
0324:
0325: /**
0326: * Returns <code>true</code> if this class extends or implements
0327: * <code>clazz</code>. It also returns <code>true</code> if
0328: * this class is the same as <code>clazz</code>.
0329: */
0330: public boolean subtypeOf(CtClass clazz) throws NotFoundException {
0331: return this == clazz || getName().equals(clazz.getName());
0332: }
0333:
0334: /**
0335: * Obtains the fully-qualified name of the class.
0336: */
0337: public String getName() {
0338: return qualifiedName;
0339: }
0340:
0341: /**
0342: * Obtains the not-qualified class name.
0343: */
0344: public final String getSimpleName() {
0345: String qname = qualifiedName;
0346: int index = qname.lastIndexOf('.');
0347: if (index < 0)
0348: return qname;
0349: else
0350: return qname.substring(index + 1);
0351: }
0352:
0353: /**
0354: * Obtains the package name. It may be <code>null</code>.
0355: */
0356: public final String getPackageName() {
0357: String qname = qualifiedName;
0358: int index = qname.lastIndexOf('.');
0359: if (index < 0)
0360: return null;
0361: else
0362: return qname.substring(0, index);
0363: }
0364:
0365: /**
0366: * Sets the class name
0367: *
0368: * @param name fully-qualified name
0369: */
0370: public void setName(String name) {
0371: checkModify();
0372: if (name != null)
0373: qualifiedName = name;
0374: }
0375:
0376: /**
0377: * Substitutes <code>newName</code> for all occurrences of a class
0378: * name <code>oldName</code> in the class file.
0379: *
0380: * @param oldName replaced class name
0381: * @param newName substituted class name
0382: */
0383: public void replaceClassName(String oldName, String newName) {
0384: checkModify();
0385: }
0386:
0387: /**
0388: * Changes class names appearing in the class file according to the
0389: * given <code>map</code>.
0390: *
0391: * <p>All the class names appearing in the class file are tested
0392: * with <code>map</code> to determine whether each class name is
0393: * replaced or not. Thus this method can be used for collecting
0394: * all the class names in the class file. To do that, first define
0395: * a subclass of <code>ClassMap</code> so that <code>get()</code>
0396: * records all the given parameters. Then, make an instance of
0397: * that subclass as an empty hash-table. Finally, pass that instance
0398: * to this method. After this method finishes, that instance would
0399: * contain all the class names appearing in the class file.
0400: *
0401: * @param map the hashtable associating replaced class names
0402: * with substituted names.
0403: */
0404: public void replaceClassName(ClassMap map) {
0405: checkModify();
0406: }
0407:
0408: /**
0409: * Returns a collection of the names of all the classes
0410: * referenced in this class.
0411: * That collection includes the name of this class.
0412: *
0413: * <p>This method may return <code>null</code>.
0414: */
0415: public Collection getRefClasses() {
0416: ClassFile cf = getClassFile2();
0417: if (cf != null) {
0418: ClassMap cm = new ClassMap() {
0419: public void put(String oldname, String newname) {
0420: put0(oldname, newname);
0421: }
0422:
0423: public Object get(Object jvmClassName) {
0424: String n = toJavaName((String) jvmClassName);
0425: put0(n, n);
0426: return null;
0427: }
0428:
0429: public void fix(String name) {
0430: }
0431: };
0432: cf.renameClass(cm);
0433: return cm.values();
0434: } else
0435: return null;
0436: }
0437:
0438: /**
0439: * Determines whether this object represents a class or an interface.
0440: * It returns <code>true</code> if this object represents an interface.
0441: */
0442: public boolean isInterface() {
0443: return false;
0444: }
0445:
0446: /**
0447: * Determines whether this object represents an annotation type.
0448: * It returns <code>true</code> if this object represents an annotation type.
0449: *
0450: * @since 3.2
0451: */
0452: public boolean isAnnotation() {
0453: return false;
0454: }
0455:
0456: /**
0457: * Determines whether this object represents an enum.
0458: * It returns <code>true</code> if this object represents an enum.
0459: *
0460: * @since 3.2
0461: */
0462: public boolean isEnum() {
0463: return false;
0464: }
0465:
0466: /**
0467: * Returns the modifiers for this class, encoded in an integer.
0468: * For decoding, use <code>javassist.Modifier</code>.
0469: *
0470: * <p>If the class is a static nested class (a.k.a. static inner class),
0471: * the returned modifiers include <code>Modifier.STATIC</code>.
0472: *
0473: * @see Modifier
0474: */
0475: public int getModifiers() {
0476: return 0;
0477: }
0478:
0479: /**
0480: * Returns the annotations associated with this class.
0481: * For example, if an annotation <code>@Author</code> is associated
0482: * with this class, the returned array contains an <code>Author</code>
0483: * object. The member values can be obtained by calling methods on
0484: * the <code>Author</code> object.
0485: *
0486: * @return an array of annotation-type objects.
0487: * @see CtMember#getAnnotations()
0488: * @since 3.1
0489: */
0490: public Object[] getAnnotations() throws ClassNotFoundException {
0491: return new Object[0];
0492: }
0493:
0494: /**
0495: * Returns the annotations associated with this class.
0496: * This method is equivalent to <code>getAnnotations()</code>
0497: * except that, if any annotations are not on the classpath,
0498: * they are not included in the returned array.
0499: *
0500: * @return an array of annotation-type objects.
0501: * @see #getAnnotations()
0502: * @see CtMember#getAvailableAnnotations()
0503: * @since 3.3
0504: */
0505: public Object[] getAvailableAnnotations() {
0506: return new Object[0];
0507: }
0508:
0509: /**
0510: * Returns an array of nested classes declared in the class.
0511: * Nested classes are inner classes, anonymous classes, local classes,
0512: * and static nested classes.
0513: *
0514: * @since 3.2
0515: */
0516: public CtClass[] getNestedClasses() throws NotFoundException {
0517: return new CtClass[0];
0518: }
0519:
0520: /**
0521: * Sets the modifiers.
0522: *
0523: * <p>If the class is a nested class, this method also modifies
0524: * the class declaring that nested class (i.e. the enclosing
0525: * class is modified).
0526: *
0527: * @param mod modifiers encoded by
0528: * <code>javassist.Modifier</code>
0529: * @see Modifier
0530: */
0531: public void setModifiers(int mod) {
0532: checkModify();
0533: }
0534:
0535: /**
0536: * Determines whether the class directly or indirectly extends
0537: * the given class. If this class extends a class A and
0538: * the class A extends a class B, then subclassof(B) returns true.
0539: *
0540: * <p>This method returns true if the given class is identical to
0541: * the class represented by this object.
0542: */
0543: public boolean subclassOf(CtClass super class) {
0544: return false;
0545: }
0546:
0547: /**
0548: * Obtains the class object representing the superclass of the
0549: * class.
0550: * It returns null if this object represents the
0551: * <code>java.lang.Object</code> class and thus it does not have
0552: * the super class.
0553: *
0554: * <p>If this object represents an interface, this method
0555: * always returns the <code>java.lang.Object</code> class.
0556: * To obtain the super interfaces
0557: * extended by that interface, call <code>getInterfaces()</code>.
0558: */
0559: public CtClass getSuperclass() throws NotFoundException {
0560: return null;
0561: }
0562:
0563: /**
0564: * Changes a super class unless this object represents an interface.
0565: * The new super class must be compatible with the old one.
0566: *
0567: * <p>If this object represents an interface, this method is equivalent
0568: * to <code>addInterface()</code>; it appends <code>clazz</code> to
0569: * the list of the super interfaces extended by that interface.
0570: * Note that an interface can extend multiple super interfaces.
0571: */
0572: public void setSuperclass(CtClass clazz)
0573: throws CannotCompileException {
0574: checkModify();
0575: }
0576:
0577: /**
0578: * Obtains the class objects representing the interfaces implemented
0579: * by the class or, if this object represents an interface, the interfaces
0580: * extended by that interface.
0581: */
0582: public CtClass[] getInterfaces() throws NotFoundException {
0583: return new CtClass[0];
0584: }
0585:
0586: /**
0587: * Sets implemented interfaces. If this object represents an interface,
0588: * this method sets the interfaces extended by that interface.
0589: *
0590: * @param list a list of the <code>CtClass</code> objects
0591: * representing interfaces, or
0592: * <code>null</code> if the class implements
0593: * no interfaces.
0594: */
0595: public void setInterfaces(CtClass[] list) {
0596: checkModify();
0597: }
0598:
0599: /**
0600: * Adds an interface.
0601: *
0602: * @param anInterface the added interface.
0603: */
0604: public void addInterface(CtClass anInterface) {
0605: checkModify();
0606: }
0607:
0608: /**
0609: * If this class is a member class or interface of another class,
0610: * then the class enclosing this class is returned.
0611: *
0612: * @return null if this class is a top-level class or an anonymous class.
0613: */
0614: public CtClass getDeclaringClass() throws NotFoundException {
0615: return null;
0616: }
0617:
0618: /**
0619: * Returns the immediately enclosing method of this class.
0620: * This method works only with JDK 1.5 or later.
0621: *
0622: * @return null if this class is not a local class or an anonymous
0623: * class.
0624: */
0625: public CtMethod getEnclosingMethod() throws NotFoundException {
0626: return null;
0627: }
0628:
0629: /**
0630: * Makes a new public nested class. If this method is called,
0631: * the <code>CtClass</code>, which encloses the nested class, is modified
0632: * since a class file includes a list of nested classes.
0633: *
0634: * <p>The current implementation only supports a static nested class.
0635: * <code>isStatic</code> must be true.
0636: *
0637: * @param name the simple name of the nested class.
0638: * @param isStatic true if the nested class is static.
0639: */
0640: public CtClass makeNestedClass(String name, boolean isStatic) {
0641: throw new RuntimeException(getName() + " is not a class");
0642: }
0643:
0644: /**
0645: * Returns an array containing <code>CtField</code> objects
0646: * representing all the non-private fields of the class.
0647: * That array includes non-private fields inherited from the
0648: * superclasses.
0649: */
0650: public CtField[] getFields() {
0651: return new CtField[0];
0652: }
0653:
0654: /**
0655: * Returns the field with the specified name. The returned field
0656: * may be a private field declared in a super class or interface.
0657: */
0658: public CtField getField(String name) throws NotFoundException {
0659: throw new NotFoundException(name);
0660: }
0661:
0662: /**
0663: * @return null if the specified field is not found.
0664: */
0665: CtField getField2(String name) {
0666: return null;
0667: }
0668:
0669: /**
0670: * Gets all the fields declared in the class. The inherited fields
0671: * are not included.
0672: *
0673: * <p>Note: the result does not include inherited fields.
0674: */
0675: public CtField[] getDeclaredFields() {
0676: return new CtField[0];
0677: }
0678:
0679: /**
0680: * Retrieves the field with the specified name among the fields
0681: * declared in the class.
0682: *
0683: * <p>Note: this method does not search the superclasses.
0684: */
0685: public CtField getDeclaredField(String name)
0686: throws NotFoundException {
0687: throw new NotFoundException(name);
0688: }
0689:
0690: /**
0691: * Gets all the constructors and methods declared in the class.
0692: */
0693: public CtBehavior[] getDeclaredBehaviors() {
0694: return new CtBehavior[0];
0695: }
0696:
0697: /**
0698: * Returns an array containing <code>CtConstructor</code> objects
0699: * representing all the non-private constructors of the class.
0700: */
0701: public CtConstructor[] getConstructors() {
0702: return new CtConstructor[0];
0703: }
0704:
0705: /**
0706: * Returns the constructor with the given signature,
0707: * which is represented by a character string
0708: * called method descriptor.
0709: * For details of the method descriptor, see the JVM specification
0710: * or <code>javassist.bytecode.Descriptor</code>.
0711: *
0712: * @param desc method descriptor
0713: * @see javassist.bytecode.Descriptor
0714: */
0715: public CtConstructor getConstructor(String desc)
0716: throws NotFoundException {
0717: throw new NotFoundException("no such a constructor");
0718: }
0719:
0720: /**
0721: * Gets all the constructors declared in the class.
0722: *
0723: * @see javassist.CtConstructor
0724: */
0725: public CtConstructor[] getDeclaredConstructors() {
0726: return new CtConstructor[0];
0727: }
0728:
0729: /**
0730: * Returns a constructor receiving the specified parameters.
0731: *
0732: * @param params parameter types.
0733: */
0734: public CtConstructor getDeclaredConstructor(CtClass[] params)
0735: throws NotFoundException {
0736: String desc = Descriptor.ofConstructor(params);
0737: return getConstructor(desc);
0738: }
0739:
0740: /**
0741: * Gets the class initializer (static constructor)
0742: * declared in the class.
0743: * This method returns <code>null</code> if
0744: * no class initializer is not declared.
0745: *
0746: * @see #makeClassInitializer()
0747: * @see javassist.CtConstructor
0748: */
0749: public CtConstructor getClassInitializer() {
0750: return null;
0751: }
0752:
0753: /**
0754: * Returns an array containing <code>CtMethod</code> objects
0755: * representing all the non-private methods of the class.
0756: * That array includes pon-private methods inherited from the
0757: * superclasses.
0758: */
0759: public CtMethod[] getMethods() {
0760: return new CtMethod[0];
0761: }
0762:
0763: /**
0764: * Returns the method with the given name and signature.
0765: * The returned method may be declared in a super class.
0766: * The method signature is represented by a character string
0767: * called method descriptor,
0768: * which is defined in the JVM specification.
0769: *
0770: * @param name method name
0771: * @param desc method descriptor
0772: * @see CtBehavior#getSignature()
0773: * @see javassist.bytecode.Descriptor
0774: */
0775: public CtMethod getMethod(String name, String desc)
0776: throws NotFoundException {
0777: throw new NotFoundException(name);
0778: }
0779:
0780: /**
0781: * Gets all methods declared in the class. The inherited methods
0782: * are not included.
0783: *
0784: * @see javassist.CtMethod
0785: */
0786: public CtMethod[] getDeclaredMethods() {
0787: return new CtMethod[0];
0788: }
0789:
0790: /**
0791: * Retrieves the method with the specified name and parameter types
0792: * among the methods declared in the class.
0793: *
0794: * <p>Note: this method does not search the superclasses.
0795: *
0796: * @param name method name
0797: * @param params parameter types
0798: * @see javassist.CtMethod
0799: */
0800: public CtMethod getDeclaredMethod(String name, CtClass[] params)
0801: throws NotFoundException {
0802: throw new NotFoundException(name);
0803: }
0804:
0805: /**
0806: * Retrieves the method with the specified name among the methods
0807: * declared in the class. If there are multiple methods with
0808: * the specified name, then this method returns one of them.
0809: *
0810: * <p>Note: this method does not search the superclasses.
0811: *
0812: * @see javassist.CtMethod
0813: */
0814: public CtMethod getDeclaredMethod(String name)
0815: throws NotFoundException {
0816: throw new NotFoundException(name);
0817: }
0818:
0819: /**
0820: * Makes an empty class initializer (static constructor).
0821: * If the class already includes a class initializer,
0822: * this method returns it.
0823: *
0824: * @see #getClassInitializer()
0825: */
0826: public CtConstructor makeClassInitializer()
0827: throws CannotCompileException {
0828: throw new CannotCompileException("not a class");
0829: }
0830:
0831: /**
0832: * Adds a constructor. To add a class initializer (static constructor),
0833: * call <code>makeClassInitializer()</code>.
0834: *
0835: * @see #makeClassInitializer()
0836: */
0837: public void addConstructor(CtConstructor c)
0838: throws CannotCompileException {
0839: checkModify();
0840: }
0841:
0842: /**
0843: * Removes a constructor declared in this class.
0844: *
0845: * @param c removed constructor.
0846: * @throws NotFoundException if the constructor is not found.
0847: */
0848: public void removeConstructor(CtConstructor c)
0849: throws NotFoundException {
0850: checkModify();
0851: }
0852:
0853: /**
0854: * Adds a method.
0855: */
0856: public void addMethod(CtMethod m) throws CannotCompileException {
0857: checkModify();
0858: }
0859:
0860: /**
0861: * Removes a method declared in this class.
0862: *
0863: * @param m removed method.
0864: * @throws NotFoundException if the method is not found.
0865: */
0866: public void removeMethod(CtMethod m) throws NotFoundException {
0867: checkModify();
0868: }
0869:
0870: /**
0871: * Adds a field.
0872: *
0873: * <p>The <code>CtField</code> belonging to another
0874: * <code>CtClass</code> cannot be directly added to this class.
0875: * Only a field created for this class can be added.
0876: *
0877: * @see javassist.CtField#CtField(CtField,CtClass)
0878: */
0879: public void addField(CtField f) throws CannotCompileException {
0880: addField(f, (CtField.Initializer) null);
0881: }
0882:
0883: /**
0884: * Adds a field with an initial value.
0885: *
0886: * <p>The <code>CtField</code> belonging to another
0887: * <code>CtClass</code> cannot be directly added to this class.
0888: * Only a field created for this class can be added.
0889: *
0890: * <p>The initial value is given as an expression written in Java.
0891: * Any regular Java expression can be used for specifying the initial
0892: * value. The followings are examples.
0893: *
0894: * <ul><pre>
0895: * cc.addField(f, "0") // the initial value is 0.
0896: * cc.addField(f, "i + 1") // i + 1.
0897: * cc.addField(f, "new Point()"); // a Point object.
0898: * </pre></ul>
0899: *
0900: * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>.
0901: * The type of <code>f</code> is <code>CtField</code>.
0902: *
0903: * @param init an expression for the initial value.
0904: *
0905: * @see javassist.CtField.Initializer#byExpr(String)
0906: * @see javassist.CtField#CtField(CtField,CtClass)
0907: */
0908: public void addField(CtField f, String init)
0909: throws CannotCompileException {
0910: checkModify();
0911: }
0912:
0913: /**
0914: * Adds a field with an initial value.
0915: *
0916: * <p>The <code>CtField</code> belonging to another
0917: * <code>CtClass</code> cannot be directly added to this class.
0918: * Only a field created for this class can be added.
0919: *
0920: * <p>For example,
0921: *
0922: * <ul><pre>
0923: * CtClass cc = ...;
0924: * addField(new CtField(CtClass.intType, "i", cc),
0925: * CtField.Initializer.constant(1));
0926: * </pre></ul>
0927: *
0928: * <p>This code adds an <code>int</code> field named "i". The
0929: * initial value of this field is 1.
0930: *
0931: * @param init specifies the initial value of the field.
0932: *
0933: * @see javassist.CtField#CtField(CtField,CtClass)
0934: */
0935: public void addField(CtField f, CtField.Initializer init)
0936: throws CannotCompileException {
0937: checkModify();
0938: }
0939:
0940: /**
0941: * Removes a field declared in this class.
0942: *
0943: * @param f removed field.
0944: * @throws NotFoundException if the field is not found.
0945: */
0946: public void removeField(CtField f) throws NotFoundException {
0947: checkModify();
0948: }
0949:
0950: /**
0951: * Obtains an attribute with the given name.
0952: * If that attribute is not found in the class file, this
0953: * method returns null.
0954: *
0955: * <p>This is a convenient method mainly for obtaining
0956: * a user-defined attribute. For dealing with attributes, see the
0957: * <code>javassist.bytecode</code> package. For example, the following
0958: * expression returns all the attributes of a class file.
0959: *
0960: * <ul><pre>
0961: * getClassFile().getAttributes()
0962: * </pre></ul>
0963: *
0964: * @param name attribute name
0965: * @see javassist.bytecode.AttributeInfo
0966: */
0967: public byte[] getAttribute(String name) {
0968: return null;
0969: }
0970:
0971: /**
0972: * Adds a named attribute.
0973: * An arbitrary data (smaller than 64Kb) can be saved in the class
0974: * file. Some attribute name are reserved by the JVM.
0975: * The attributes with the non-reserved names are ignored when a
0976: * class file is loaded into the JVM.
0977: * If there is already an attribute with
0978: * the same name, this method substitutes the new one for it.
0979: *
0980: * <p>This is a convenient method mainly for adding
0981: * a user-defined attribute. For dealing with attributes, see the
0982: * <code>javassist.bytecode</code> package. For example, the following
0983: * expression adds an attribute <code>info</code> to a class file.
0984: *
0985: * <ul><pre>
0986: * getClassFile().addAttribute(info)
0987: * </pre></ul>
0988: *
0989: * @param name attribute name
0990: * @param data attribute value
0991: * @see javassist.bytecode.AttributeInfo
0992: */
0993: public void setAttribute(String name, byte[] data) {
0994: checkModify();
0995: }
0996:
0997: /**
0998: * Applies the given converter to all methods and constructors
0999: * declared in the class. This method calls <code>instrument()</code>
1000: * on every <code>CtMethod</code> and <code>CtConstructor</code> object
1001: * in the class.
1002: *
1003: * @param converter specifies how to modify.
1004: */
1005: public void instrument(CodeConverter converter)
1006: throws CannotCompileException {
1007: checkModify();
1008: }
1009:
1010: /**
1011: * Modifies the bodies of all methods and constructors
1012: * declared in the class. This method calls <code>instrument()</code>
1013: * on every <code>CtMethod</code> and <code>CtConstructor</code> object
1014: * in the class.
1015: *
1016: * @param editor specifies how to modify.
1017: */
1018: public void instrument(ExprEditor editor)
1019: throws CannotCompileException {
1020: checkModify();
1021: }
1022:
1023: /**
1024: * Converts this class to a <code>java.lang.Class</code> object.
1025: * Once this method is called, further modifications are not
1026: * allowed any more.
1027: * To load the class, this method uses the context class loader
1028: * of the current thread. If the program is running on some application
1029: * server, the context class loader might be inappropriate to load the
1030: * class.
1031: *
1032: * <p>This method is provided for convenience. If you need more
1033: * complex functionality, you should write your own class loader.
1034: *
1035: * <p>Note: this method calls <code>toClass()</code>
1036: * in <code>ClassPool</code>.
1037: *
1038: * <p><b>Warining:</b> A Class object returned by this method may not
1039: * work with a security manager or a signed jar file because a
1040: * protection domain is not specified.
1041: *
1042: * @see #toClass(java.lang.ClassLoader,ProtectionDomain)
1043: * @see ClassPool#toClass(CtClass)
1044: */
1045: public Class toClass() throws CannotCompileException {
1046: return getClassPool().toClass(this );
1047: }
1048:
1049: /**
1050: * Converts this class to a <code>java.lang.Class</code> object.
1051: * Once this method is called, further modifications are not allowed
1052: * any more.
1053: *
1054: * <p>The class file represented by this <code>CtClass</code> is
1055: * loaded by the given class loader to construct a
1056: * <code>java.lang.Class</code> object. Since a private method
1057: * on the class loader is invoked through the reflection API,
1058: * the caller must have permissions to do that.
1059: *
1060: * <p>An easy way to obtain <code>ProtectionDomain</code> object is
1061: * to call <code>getProtectionDomain()</code>
1062: * in <code>java.lang.Class</code>. It returns the domain that
1063: * the class belongs to.
1064: *
1065: * <p>This method is provided for convenience. If you need more
1066: * complex functionality, you should write your own class loader.
1067: *
1068: * <p>Note: this method calls <code>toClass()</code>
1069: * in <code>ClassPool</code>.
1070: *
1071: * @param loader the class loader used to load this class.
1072: * If it is null, the class loader returned by
1073: * {@link ClassPool#getClassLoader()} is used.
1074: * @param domain the protection domain that the class belongs to.
1075: * If it is null, the default domain created
1076: * by <code>java.lang.ClassLoader</code> is used.
1077: * @see ClassPool#toClass(CtClass,java.lang.ClassLoader)
1078: * @since 3.3
1079: */
1080: public Class toClass(ClassLoader loader, ProtectionDomain domain)
1081: throws CannotCompileException {
1082: ClassPool cp = getClassPool();
1083: if (loader == null)
1084: loader = cp.getClassLoader();
1085:
1086: return cp.toClass(this , loader, domain);
1087: }
1088:
1089: /**
1090: * Converts this class to a <code>java.lang.Class</code> object.
1091: *
1092: * <p><b>Warining:</b> A Class object returned by this method may not
1093: * work with a security manager or a signed jar file because a
1094: * protection domain is not specified.
1095: *
1096: * @deprecated Replaced by {@link #toClass(ClassLoader,ProtectionDomain)}
1097: */
1098: public final Class toClass(ClassLoader loader)
1099: throws CannotCompileException {
1100: return getClassPool().toClass(this , loader);
1101: }
1102:
1103: /**
1104: * Removes this <code>CtClass</code> object from the
1105: * <code>ClassPool</code>.
1106: * After this method is called, any method cannot be called on the
1107: * removed <code>CtClass</code> object.
1108: *
1109: * <p>If <code>get()</code> in <code>ClassPool</code> is called
1110: * with the name of the removed method,
1111: * the <code>ClassPool</code> will read the class file again
1112: * and constructs another <code>CtClass</code> object representing
1113: * the same class.
1114: */
1115: public void detach() {
1116: ClassPool cp = getClassPool();
1117: CtClass obj = cp.removeCached(getName());
1118: if (obj != this )
1119: cp.cacheCtClass(getName(), obj, false);
1120: }
1121:
1122: /**
1123: * Disallows (or allows) automatically pruning this <code>CtClass</code>
1124: * object.
1125: *
1126: * <p>
1127: * Javassist can automatically prune a <code>CtClass</code> object
1128: * when <code>toBytecode()</code> (or <code>toClass()</code>,
1129: * <code>writeFile()</code>) is called.
1130: * Since a <code>ClassPool</code> holds all instances of <code>CtClass</code>
1131: * even after <code>toBytecode()</code> (or <code>toClass()</code>,
1132: * <code>writeFile()</code>) is called, pruning may significantly
1133: * save memory consumption.
1134: *
1135: * <p>If <code>ClassPool.doPruning</code> is true, the automatic pruning
1136: * is on by default. Otherwise, it is off.
1137: *
1138: * @param stop disallow pruning if true. Otherwise, allow.
1139: * @return the previous status of pruning. true if pruning is already stopped.
1140: *
1141: * @see #detach()
1142: * @see #prune()
1143: * @see ClassPool#doPruning
1144: */
1145: public boolean stopPruning(boolean stop) {
1146: return true;
1147: }
1148:
1149: /**
1150: * Discards unnecessary attributes, in particuar,
1151: * <code>CodeAttribute</code>s (method bodies) of the class,
1152: * to minimize the memory footprint.
1153: * After calling this method, the class is read only.
1154: * It cannot be modified any more.
1155: * Furthermore, <code>toBytecode()</code>,
1156: * <code>writeFile()</code>, <code>toClass()</code>,
1157: * or <code>instrument()</code> cannot be called.
1158: * However, the method names and signatures in the class etc.
1159: * are still accessible.
1160: *
1161: * <p><code>toBytecode()</code>, <code>writeFile()</code>, and
1162: * <code>toClass()</code> internally call this method.
1163: *
1164: * @see #toBytecode()
1165: * @see #toClass()
1166: * @see #writeFile()
1167: * @see #instrument(CodeConverter)
1168: * @see #instrument(ExprEditor)
1169: *
1170: * @see #stopPruning(boolean)
1171: */
1172: public void prune() {
1173: }
1174:
1175: /* Called by get() in ClassPool.
1176: * CtClassType overrides this method.
1177: */
1178: void incGetCounter() {
1179: }
1180:
1181: /**
1182: * Converts this class to a class file.
1183: * Once this method is called, further modifications are not
1184: * possible any more.
1185: *
1186: * @return the contents of the class file.
1187: */
1188: public byte[] toBytecode() throws IOException,
1189: CannotCompileException {
1190: ByteArrayOutputStream barray = new ByteArrayOutputStream();
1191: DataOutputStream out = new DataOutputStream(barray);
1192: try {
1193: toBytecode(out);
1194: } finally {
1195: out.close();
1196: }
1197:
1198: return barray.toByteArray();
1199: }
1200:
1201: /**
1202: * Writes a class file represented by this <code>CtClass</code>
1203: * object in the current directory.
1204: * Once this method is called, further modifications are not
1205: * possible any more.
1206: */
1207: public void writeFile() throws NotFoundException, IOException,
1208: CannotCompileException {
1209: writeFile(".");
1210: }
1211:
1212: /**
1213: * Writes a class file represented by this <code>CtClass</code>
1214: * object on a local disk.
1215: * Once this method is called, further modifications are not
1216: * possible any more.
1217: *
1218: * @param directoryName it must end without a directory separator.
1219: */
1220: public void writeFile(String directoryName)
1221: throws CannotCompileException, IOException {
1222: String classname = getName();
1223: String filename = directoryName + File.separatorChar
1224: + classname.replace('.', File.separatorChar) + ".class";
1225: int pos = filename.lastIndexOf(File.separatorChar);
1226: if (pos > 0) {
1227: String dir = filename.substring(0, pos);
1228: if (!dir.equals("."))
1229: new File(dir).mkdirs();
1230: }
1231:
1232: DataOutputStream out = new DataOutputStream(
1233: new BufferedOutputStream(new DelayedFileOutputStream(
1234: filename)));
1235: try {
1236: toBytecode(out);
1237: } finally {
1238: out.close();
1239: }
1240: }
1241:
1242: /**
1243: * Writes a class file as <code>writeFile()</code> does although this
1244: * method does not prune or freeze the class after writing the class
1245: * file. Note that, once <code>writeFile()</code> or <code>toBytecode()</code>
1246: * is called, it cannot be called again since the class is pruned and frozen.
1247: * This method would be useful for debugging.
1248: */
1249: public void debugWriteFile() {
1250: try {
1251: boolean p = stopPruning(true);
1252: writeFile();
1253: defrost();
1254: stopPruning(p);
1255: } catch (Exception e) {
1256: throw new RuntimeException(e);
1257: }
1258: }
1259:
1260: static class DelayedFileOutputStream extends OutputStream {
1261: private FileOutputStream file;
1262: private String filename;
1263:
1264: DelayedFileOutputStream(String name) {
1265: file = null;
1266: filename = name;
1267: }
1268:
1269: private void init() throws IOException {
1270: if (file == null)
1271: file = new FileOutputStream(filename);
1272: }
1273:
1274: public void write(int b) throws IOException {
1275: init();
1276: file.write(b);
1277: }
1278:
1279: public void write(byte[] b) throws IOException {
1280: init();
1281: file.write(b);
1282: }
1283:
1284: public void write(byte[] b, int off, int len)
1285: throws IOException {
1286: init();
1287: file.write(b, off, len);
1288:
1289: }
1290:
1291: public void flush() throws IOException {
1292: init();
1293: file.flush();
1294: }
1295:
1296: public void close() throws IOException {
1297: init();
1298: file.close();
1299: }
1300: }
1301:
1302: /**
1303: * Converts this class to a class file.
1304: * Once this method is called, further modifications are not
1305: * possible any more.
1306: *
1307: * <p>This method dose not close the output stream in the end.
1308: *
1309: * @param out the output stream that a class file is written to.
1310: */
1311: public void toBytecode(DataOutputStream out)
1312: throws CannotCompileException, IOException {
1313: throw new CannotCompileException("not a class");
1314: }
1315:
1316: /**
1317: * Makes a unique member name. This method guarantees that
1318: * the returned name is not used as a prefix of any methods
1319: * or fields visible in this class.
1320: * If the returned name is XYZ, then any method or field names
1321: * in this class do not start with XYZ.
1322: *
1323: * @param prefix the prefix of the member name.
1324: */
1325: public String makeUniqueName(String prefix) {
1326: throw new RuntimeException("not available in " + getName());
1327: }
1328: }
|