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.bytecode;
0017:
0018: import java.io.DataInputStream;
0019: import java.io.DataOutputStream;
0020: import java.io.ByteArrayOutputStream;
0021: import java.io.PrintWriter;
0022: import java.io.IOException;
0023: import java.util.HashMap;
0024: import java.util.HashSet;
0025: import java.util.Map;
0026: import java.util.Set;
0027:
0028: import javassist.CtClass;
0029:
0030: /**
0031: * Constant pool table.
0032: */
0033: public final class ConstPool {
0034: LongVector items;
0035: int numOfItems;
0036: HashMap classes;
0037: HashMap strings;
0038: int this ClassInfo;
0039:
0040: /**
0041: * <code>CONSTANT_Class</code>
0042: */
0043: public static final int CONST_Class = ClassInfo.tag;
0044:
0045: /**
0046: * <code>CONSTANT_Fieldref</code>
0047: */
0048: public static final int CONST_Fieldref = FieldrefInfo.tag;
0049:
0050: /**
0051: * <code>CONSTANT_Methodref</code>
0052: */
0053: public static final int CONST_Methodref = MethodrefInfo.tag;
0054:
0055: /**
0056: * <code>CONSTANT_InterfaceMethodref</code>
0057: */
0058: public static final int CONST_InterfaceMethodref = InterfaceMethodrefInfo.tag;
0059:
0060: /**
0061: * <code>CONSTANT_String</code>
0062: */
0063: public static final int CONST_String = StringInfo.tag;
0064:
0065: /**
0066: * <code>CONSTANT_Integer</code>
0067: */
0068: public static final int CONST_Integer = IntegerInfo.tag;
0069:
0070: /**
0071: * <code>CONSTANT_Float</code>
0072: */
0073: public static final int CONST_Float = FloatInfo.tag;
0074:
0075: /**
0076: * <code>CONSTANT_Long</code>
0077: */
0078: public static final int CONST_Long = LongInfo.tag;
0079:
0080: /**
0081: * <code>CONSTANT_Double</code>
0082: */
0083: public static final int CONST_Double = DoubleInfo.tag;
0084:
0085: /**
0086: * <code>CONSTANT_NameAndType</code>
0087: */
0088: public static final int CONST_NameAndType = NameAndTypeInfo.tag;
0089:
0090: /**
0091: * <code>CONSTANT_Utf8</code>
0092: */
0093: public static final int CONST_Utf8 = Utf8Info.tag;
0094:
0095: /**
0096: * Represents the class using this constant pool table.
0097: */
0098: public static final CtClass THIS = null;
0099:
0100: /**
0101: * Constructs a constant pool table.
0102: *
0103: * @param thisclass the name of the class using this constant
0104: * pool table
0105: */
0106: public ConstPool(String this class) {
0107: items = new LongVector();
0108: numOfItems = 0;
0109: addItem(null); // index 0 is reserved by the JVM.
0110: classes = new HashMap();
0111: strings = new HashMap();
0112: this ClassInfo = addClassInfo(this class);
0113: }
0114:
0115: /**
0116: * Constructs a constant pool table from the given byte stream.
0117: *
0118: * @param in byte stream.
0119: */
0120: public ConstPool(DataInputStream in) throws IOException {
0121: classes = new HashMap();
0122: strings = new HashMap();
0123: this ClassInfo = 0;
0124: /* read() initializes items and numOfItems, and do addItem(null).
0125: */
0126: read(in);
0127: }
0128:
0129: void prune() {
0130: classes = new HashMap();
0131: strings = new HashMap();
0132: }
0133:
0134: /**
0135: * Returns the number of entries in this table.
0136: */
0137: public int getSize() {
0138: return numOfItems;
0139: }
0140:
0141: /**
0142: * Returns the name of the class using this constant pool table.
0143: */
0144: public String getClassName() {
0145: return getClassInfo(this ClassInfo);
0146: }
0147:
0148: /**
0149: * Returns the index of <code>CONSTANT_Class_info</code> structure
0150: * specifying the class using this constant pool table.
0151: */
0152: public int getThisClassInfo() {
0153: return this ClassInfo;
0154: }
0155:
0156: void setThisClassInfo(int i) {
0157: this ClassInfo = i;
0158: }
0159:
0160: ConstInfo getItem(int n) {
0161: return (ConstInfo) items.elementAt(n);
0162: }
0163:
0164: /**
0165: * Returns the <code>tag</code> field of the constant pool table
0166: * entry at the given index.
0167: */
0168: public int getTag(int index) {
0169: return getItem(index).getTag();
0170: }
0171:
0172: /**
0173: * Reads <code>CONSTANT_Class_info</code> structure
0174: * at the given index.
0175: *
0176: * @return a fully-qualified class or interface name specified
0177: * by <code>name_index</code>.
0178: */
0179: public String getClassInfo(int index) {
0180: ClassInfo c = (ClassInfo) getItem(index);
0181: if (c == null)
0182: return null;
0183: else
0184: return Descriptor.toJavaName(getUtf8Info(c.name));
0185: }
0186:
0187: /**
0188: * Reads the <code>name_index</code> field of the
0189: * <code>CONSTANT_NameAndType_info</code> structure
0190: * at the given index.
0191: */
0192: public int getNameAndTypeName(int index) {
0193: NameAndTypeInfo ntinfo = (NameAndTypeInfo) getItem(index);
0194: return ntinfo.memberName;
0195: }
0196:
0197: /**
0198: * Reads the <code>descriptor_index</code> field of the
0199: * <code>CONSTANT_NameAndType_info</code> structure
0200: * at the given index.
0201: */
0202: public int getNameAndTypeDescriptor(int index) {
0203: NameAndTypeInfo ntinfo = (NameAndTypeInfo) getItem(index);
0204: return ntinfo.typeDescriptor;
0205: }
0206:
0207: /**
0208: * Reads the <code>class_index</code> field of the
0209: * <code>CONSTANT_Fieldref_info</code> structure
0210: * at the given index.
0211: */
0212: public int getFieldrefClass(int index) {
0213: FieldrefInfo finfo = (FieldrefInfo) getItem(index);
0214: return finfo.classIndex;
0215: }
0216:
0217: /**
0218: * Reads the <code>class_index</code> field of the
0219: * <code>CONSTANT_Fieldref_info</code> structure
0220: * at the given index.
0221: *
0222: * @return the name of the class at that <code>class_index</code>.
0223: */
0224: public String getFieldrefClassName(int index) {
0225: FieldrefInfo f = (FieldrefInfo) getItem(index);
0226: if (f == null)
0227: return null;
0228: else
0229: return getClassInfo(f.classIndex);
0230: }
0231:
0232: /**
0233: * Reads the <code>name_and_type_index</code> field of the
0234: * <code>CONSTANT_Fieldref_info</code> structure
0235: * at the given index.
0236: */
0237: public int getFieldrefNameAndType(int index) {
0238: FieldrefInfo finfo = (FieldrefInfo) getItem(index);
0239: return finfo.nameAndTypeIndex;
0240: }
0241:
0242: /**
0243: * Reads the <code>name_index</code> field of the
0244: * <code>CONSTANT_NameAndType_info</code> structure
0245: * indirectly specified by the given index.
0246: *
0247: * @param index an index to a <code>CONSTANT_Fieldref_info</code>.
0248: * @return the name of the field.
0249: */
0250: public String getFieldrefName(int index) {
0251: FieldrefInfo f = (FieldrefInfo) getItem(index);
0252: if (f == null)
0253: return null;
0254: else {
0255: NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex);
0256: if (n == null)
0257: return null;
0258: else
0259: return getUtf8Info(n.memberName);
0260: }
0261: }
0262:
0263: /**
0264: * Reads the <code>descriptor_index</code> field of the
0265: * <code>CONSTANT_NameAndType_info</code> structure
0266: * indirectly specified by the given index.
0267: *
0268: * @param index an index to a <code>CONSTANT_Fieldref_info</code>.
0269: * @return the type descriptor of the field.
0270: */
0271: public String getFieldrefType(int index) {
0272: FieldrefInfo f = (FieldrefInfo) getItem(index);
0273: if (f == null)
0274: return null;
0275: else {
0276: NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex);
0277: if (n == null)
0278: return null;
0279: else
0280: return getUtf8Info(n.typeDescriptor);
0281: }
0282: }
0283:
0284: /**
0285: * Reads the <code>class_index</code> field of the
0286: * <code>CONSTANT_Methodref_info</code> structure
0287: * at the given index.
0288: */
0289: public int getMethodrefClass(int index) {
0290: MethodrefInfo minfo = (MethodrefInfo) getItem(index);
0291: return minfo.classIndex;
0292: }
0293:
0294: /**
0295: * Reads the <code>class_index</code> field of the
0296: * <code>CONSTANT_Methodref_info</code> structure
0297: * at the given index.
0298: *
0299: * @return the name of the class at that <code>class_index</code>.
0300: */
0301: public String getMethodrefClassName(int index) {
0302: MethodrefInfo minfo = (MethodrefInfo) getItem(index);
0303: if (minfo == null)
0304: return null;
0305: else
0306: return getClassInfo(minfo.classIndex);
0307: }
0308:
0309: /**
0310: * Reads the <code>name_and_type_index</code> field of the
0311: * <code>CONSTANT_Methodref_info</code> structure
0312: * at the given index.
0313: */
0314: public int getMethodrefNameAndType(int index) {
0315: MethodrefInfo minfo = (MethodrefInfo) getItem(index);
0316: return minfo.nameAndTypeIndex;
0317: }
0318:
0319: /**
0320: * Reads the <code>name_index</code> field of the
0321: * <code>CONSTANT_NameAndType_info</code> structure
0322: * indirectly specified by the given index.
0323: *
0324: * @param index an index to a <code>CONSTANT_Methodref_info</code>.
0325: * @return the name of the method.
0326: */
0327: public String getMethodrefName(int index) {
0328: MethodrefInfo minfo = (MethodrefInfo) getItem(index);
0329: if (minfo == null)
0330: return null;
0331: else {
0332: NameAndTypeInfo n = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
0333: if (n == null)
0334: return null;
0335: else
0336: return getUtf8Info(n.memberName);
0337: }
0338: }
0339:
0340: /**
0341: * Reads the <code>descriptor_index</code> field of the
0342: * <code>CONSTANT_NameAndType_info</code> structure
0343: * indirectly specified by the given index.
0344: *
0345: * @param index an index to a <code>CONSTANT_Methodref_info</code>.
0346: * @return the descriptor of the method.
0347: */
0348: public String getMethodrefType(int index) {
0349: MethodrefInfo minfo = (MethodrefInfo) getItem(index);
0350: if (minfo == null)
0351: return null;
0352: else {
0353: NameAndTypeInfo n = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
0354: if (n == null)
0355: return null;
0356: else
0357: return getUtf8Info(n.typeDescriptor);
0358: }
0359: }
0360:
0361: /**
0362: * Reads the <code>class_index</code> field of the
0363: * <code>CONSTANT_InterfaceMethodref_info</code> structure
0364: * at the given index.
0365: */
0366: public int getInterfaceMethodrefClass(int index) {
0367: InterfaceMethodrefInfo minfo = (InterfaceMethodrefInfo) getItem(index);
0368: return minfo.classIndex;
0369: }
0370:
0371: /**
0372: * Reads the <code>class_index</code> field of the
0373: * <code>CONSTANT_InterfaceMethodref_info</code> structure
0374: * at the given index.
0375: *
0376: * @return the name of the class at that <code>class_index</code>.
0377: */
0378: public String getInterfaceMethodrefClassName(int index) {
0379: InterfaceMethodrefInfo minfo = (InterfaceMethodrefInfo) getItem(index);
0380: return getClassInfo(minfo.classIndex);
0381: }
0382:
0383: /**
0384: * Reads the <code>name_and_type_index</code> field of the
0385: * <code>CONSTANT_InterfaceMethodref_info</code> structure
0386: * at the given index.
0387: */
0388: public int getInterfaceMethodrefNameAndType(int index) {
0389: InterfaceMethodrefInfo minfo = (InterfaceMethodrefInfo) getItem(index);
0390: return minfo.nameAndTypeIndex;
0391: }
0392:
0393: /**
0394: * Reads the <code>name_index</code> field of the
0395: * <code>CONSTANT_NameAndType_info</code> structure
0396: * indirectly specified by the given index.
0397: *
0398: * @param index an index to
0399: * a <code>CONSTANT_InterfaceMethodref_info</code>.
0400: * @return the name of the method.
0401: */
0402: public String getInterfaceMethodrefName(int index) {
0403: InterfaceMethodrefInfo minfo = (InterfaceMethodrefInfo) getItem(index);
0404: if (minfo == null)
0405: return null;
0406: else {
0407: NameAndTypeInfo n = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
0408: if (n == null)
0409: return null;
0410: else
0411: return getUtf8Info(n.memberName);
0412: }
0413: }
0414:
0415: /**
0416: * Reads the <code>descriptor_index</code> field of the
0417: * <code>CONSTANT_NameAndType_info</code> structure
0418: * indirectly specified by the given index.
0419: *
0420: * @param index an index to
0421: * a <code>CONSTANT_InterfaceMethodref_info</code>.
0422: * @return the descriptor of the method.
0423: */
0424: public String getInterfaceMethodrefType(int index) {
0425: InterfaceMethodrefInfo minfo = (InterfaceMethodrefInfo) getItem(index);
0426: if (minfo == null)
0427: return null;
0428: else {
0429: NameAndTypeInfo n = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
0430: if (n == null)
0431: return null;
0432: else
0433: return getUtf8Info(n.typeDescriptor);
0434: }
0435: }
0436:
0437: /**
0438: * Reads <code>CONSTANT_Integer_info</code>, <code>_Float_info</code>,
0439: * <code>_Long_info</code>, <code>_Double_info</code>, or
0440: * <code>_String_info</code> structure.
0441: * These are used with the LDC instruction.
0442: *
0443: * @return a <code>String</code> value or a wrapped primitive-type
0444: * value.
0445: */
0446: public Object getLdcValue(int index) {
0447: ConstInfo constInfo = this .getItem(index);
0448: Object value = null;
0449: if (constInfo instanceof StringInfo)
0450: value = this .getStringInfo(index);
0451: else if (constInfo instanceof FloatInfo)
0452: value = new Float(getFloatInfo(index));
0453: else if (constInfo instanceof IntegerInfo)
0454: value = new Integer(getIntegerInfo(index));
0455: else if (constInfo instanceof LongInfo)
0456: value = new Long(getLongInfo(index));
0457: else if (constInfo instanceof DoubleInfo)
0458: value = new Double(getDoubleInfo(index));
0459: else
0460: value = null;
0461:
0462: return value;
0463: }
0464:
0465: /**
0466: * Reads <code>CONSTANT_Integer_info</code> structure
0467: * at the given index.
0468: *
0469: * @return the value specified by this entry.
0470: */
0471: public int getIntegerInfo(int index) {
0472: IntegerInfo i = (IntegerInfo) getItem(index);
0473: return i.value;
0474: }
0475:
0476: /**
0477: * Reads <code>CONSTANT_Float_info</code> structure
0478: * at the given index.
0479: *
0480: * @return the value specified by this entry.
0481: */
0482: public float getFloatInfo(int index) {
0483: FloatInfo i = (FloatInfo) getItem(index);
0484: return i.value;
0485: }
0486:
0487: /**
0488: * Reads <code>CONSTANT_Long_info</code> structure
0489: * at the given index.
0490: *
0491: * @return the value specified by this entry.
0492: */
0493: public long getLongInfo(int index) {
0494: LongInfo i = (LongInfo) getItem(index);
0495: return i.value;
0496: }
0497:
0498: /**
0499: * Reads <code>CONSTANT_Double_info</code> structure
0500: * at the given index.
0501: *
0502: * @return the value specified by this entry.
0503: */
0504: public double getDoubleInfo(int index) {
0505: DoubleInfo i = (DoubleInfo) getItem(index);
0506: return i.value;
0507: }
0508:
0509: /**
0510: * Reads <code>CONSTANT_String_info</code> structure
0511: * at the given index.
0512: *
0513: * @return the string specified by <code>string_index</code>.
0514: */
0515: public String getStringInfo(int index) {
0516: StringInfo si = (StringInfo) getItem(index);
0517: return getUtf8Info(si.string);
0518: }
0519:
0520: /**
0521: * Reads <code>CONSTANT_utf8_info</code> structure
0522: * at the given index.
0523: *
0524: * @return the string specified by this entry.
0525: */
0526: public String getUtf8Info(int index) {
0527: Utf8Info utf = (Utf8Info) getItem(index);
0528: return utf.string;
0529: }
0530:
0531: /**
0532: * Determines whether <code>CONSTANT_Methodref_info</code>
0533: * structure at the given index represents the constructor
0534: * of the given class.
0535: *
0536: * @return the <code>descriptor_index</code> specifying
0537: * the type descriptor of the that constructor.
0538: * If it is not that constructor,
0539: * <code>isConstructor()</code> returns 0.
0540: */
0541: public int isConstructor(String classname, int index) {
0542: return isMember(classname, MethodInfo.nameInit, index);
0543: }
0544:
0545: /**
0546: * Determines whether <code>CONSTANT_Methodref_info</code>,
0547: * <code>CONSTANT_Fieldref_info</code>, or
0548: * <code>CONSTANT_InterfaceMethodref_info</code> structure
0549: * at the given index represents the member with the specified
0550: * name and declaring class.
0551: *
0552: * @param classname the class declaring the member
0553: * @param membername the member name
0554: * @param index the index into the constant pool table
0555: *
0556: * @return the <code>descriptor_index</code> specifying
0557: * the type descriptor of that member.
0558: * If it is not that member,
0559: * <code>isMember()</code> returns 0.
0560: */
0561: public int isMember(String classname, String membername, int index) {
0562: MemberrefInfo minfo = (MemberrefInfo) getItem(index);
0563: if (getClassInfo(minfo.classIndex).equals(classname)) {
0564: NameAndTypeInfo ntinfo = (NameAndTypeInfo) getItem(minfo.nameAndTypeIndex);
0565: if (getUtf8Info(ntinfo.memberName).equals(membername))
0566: return ntinfo.typeDescriptor;
0567: }
0568:
0569: return 0; // false
0570: }
0571:
0572: private int addItem(ConstInfo info) {
0573: items.addElement(info);
0574: return numOfItems++;
0575: }
0576:
0577: /**
0578: * Copies the n-th item in this ConstPool object into the destination
0579: * ConstPool object.
0580: * The class names that the item refers to are renamed according
0581: * to the given map.
0582: *
0583: * @param n the <i>n</i>-th item
0584: * @param dest destination constant pool table
0585: * @param classnames the map or null.
0586: * @return the index of the copied item into the destination ClassPool.
0587: */
0588: public int copy(int n, ConstPool dest, Map classnames) {
0589: if (n == 0)
0590: return 0;
0591:
0592: ConstInfo info = getItem(n);
0593: return info.copy(this , dest, classnames);
0594: }
0595:
0596: int addConstInfoPadding() {
0597: return addItem(new ConstInfoPadding());
0598: }
0599:
0600: /**
0601: * Adds a new <code>CONSTANT_Class_info</code> structure.
0602: *
0603: * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
0604: * for storing the class name.
0605: *
0606: * @return the index of the added entry.
0607: */
0608: public int addClassInfo(CtClass c) {
0609: if (c == THIS)
0610: return this ClassInfo;
0611: else if (!c.isArray())
0612: return addClassInfo(c.getName());
0613: else {
0614: // an array type is recorded in the hashtable with
0615: // the key "[L<classname>;" instead of "<classname>".
0616: //
0617: // note: toJvmName(toJvmName(c)) is equal to toJvmName(c).
0618:
0619: return addClassInfo(Descriptor.toJvmName(c));
0620: }
0621: }
0622:
0623: /**
0624: * Adds a new <code>CONSTANT_Class_info</code> structure.
0625: *
0626: * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
0627: * for storing the class name.
0628: *
0629: * @param qname a fully-qualified class name
0630: * (or the JVM-internal representation of that name).
0631: * @return the index of the added entry.
0632: */
0633: public int addClassInfo(String qname) {
0634: ClassInfo info = (ClassInfo) classes.get(qname);
0635: if (info != null)
0636: return info.index;
0637: else {
0638: int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
0639: info = new ClassInfo(utf8, numOfItems);
0640: classes.put(qname, info);
0641: return addItem(info);
0642: }
0643: }
0644:
0645: /**
0646: * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
0647: *
0648: * <p>This also adds <code>CONSTANT_Utf8_info</code> structures.
0649: *
0650: * @param name <code>name_index</code>
0651: * @param type <code>descriptor_index</code>
0652: * @return the index of the added entry.
0653: */
0654: public int addNameAndTypeInfo(String name, String type) {
0655: return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
0656: }
0657:
0658: /**
0659: * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
0660: *
0661: * @param name <code>name_index</code>
0662: * @param type <code>descriptor_index</code>
0663: * @return the index of the added entry.
0664: */
0665: public int addNameAndTypeInfo(int name, int type) {
0666: return addItem(new NameAndTypeInfo(name, type));
0667: }
0668:
0669: /**
0670: * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
0671: *
0672: * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
0673: * structure.
0674: *
0675: * @param classInfo <code>class_index</code>
0676: * @param name <code>name_index</code>
0677: * of <code>CONSTANT_NameAndType_info</code>.
0678: * @param type <code>descriptor_index</code>
0679: * of <code>CONSTANT_NameAndType_info</code>.
0680: * @return the index of the added entry.
0681: */
0682: public int addFieldrefInfo(int classInfo, String name, String type) {
0683: int nt = addNameAndTypeInfo(name, type);
0684: return addFieldrefInfo(classInfo, nt);
0685: }
0686:
0687: /**
0688: * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
0689: *
0690: * @param classInfo <code>class_index</code>
0691: * @param nameAndTypeInfo <code>name_and_type_index</code>.
0692: * @return the index of the added entry.
0693: */
0694: public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
0695: return addItem(new FieldrefInfo(classInfo, nameAndTypeInfo));
0696: }
0697:
0698: /**
0699: * Adds a new <code>CONSTANT_Methodref_info</code> structure.
0700: *
0701: * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
0702: * structure.
0703: *
0704: * @param classInfo <code>class_index</code>
0705: * @param name <code>name_index</code>
0706: * of <code>CONSTANT_NameAndType_info</code>.
0707: * @param type <code>descriptor_index</code>
0708: * of <code>CONSTANT_NameAndType_info</code>.
0709: * @return the index of the added entry.
0710: */
0711: public int addMethodrefInfo(int classInfo, String name, String type) {
0712: int nt = addNameAndTypeInfo(name, type);
0713: return addMethodrefInfo(classInfo, nt);
0714: }
0715:
0716: /**
0717: * Adds a new <code>CONSTANT_Methodref_info</code> structure.
0718: *
0719: * @param classInfo <code>class_index</code>
0720: * @param nameAndTypeInfo <code>name_and_type_index</code>.
0721: * @return the index of the added entry.
0722: */
0723: public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
0724: return addItem(new MethodrefInfo(classInfo, nameAndTypeInfo));
0725: }
0726:
0727: /**
0728: * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
0729: * structure.
0730: *
0731: * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
0732: * structure.
0733: *
0734: * @param classInfo <code>class_index</code>
0735: * @param name <code>name_index</code>
0736: * of <code>CONSTANT_NameAndType_info</code>.
0737: * @param type <code>descriptor_index</code>
0738: * of <code>CONSTANT_NameAndType_info</code>.
0739: * @return the index of the added entry.
0740: */
0741: public int addInterfaceMethodrefInfo(int classInfo, String name,
0742: String type) {
0743: int nt = addNameAndTypeInfo(name, type);
0744: return addInterfaceMethodrefInfo(classInfo, nt);
0745: }
0746:
0747: /**
0748: * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
0749: * structure.
0750: *
0751: * @param classInfo <code>class_index</code>
0752: * @param nameAndTypeInfo <code>name_and_type_index</code>.
0753: * @return the index of the added entry.
0754: */
0755: public int addInterfaceMethodrefInfo(int classInfo,
0756: int nameAndTypeInfo) {
0757: return addItem(new InterfaceMethodrefInfo(classInfo,
0758: nameAndTypeInfo));
0759: }
0760:
0761: /**
0762: * Adds a new <code>CONSTANT_String_info</code>
0763: * structure.
0764: *
0765: * <p>This also adds a new <code>CONSTANT_Utf8_info</code>
0766: * structure.
0767: *
0768: * @return the index of the added entry.
0769: */
0770: public int addStringInfo(String str) {
0771: return addItem(new StringInfo(addUtf8Info(str)));
0772: }
0773:
0774: /**
0775: * Adds a new <code>CONSTANT_Integer_info</code>
0776: * structure.
0777: *
0778: * @return the index of the added entry.
0779: */
0780: public int addIntegerInfo(int i) {
0781: return addItem(new IntegerInfo(i));
0782: }
0783:
0784: /**
0785: * Adds a new <code>CONSTANT_Float_info</code>
0786: * structure.
0787: *
0788: * @return the index of the added entry.
0789: */
0790: public int addFloatInfo(float f) {
0791: return addItem(new FloatInfo(f));
0792: }
0793:
0794: /**
0795: * Adds a new <code>CONSTANT_Long_info</code>
0796: * structure.
0797: *
0798: * @return the index of the added entry.
0799: */
0800: public int addLongInfo(long l) {
0801: int i = addItem(new LongInfo(l));
0802: addItem(new ConstInfoPadding());
0803: return i;
0804: }
0805:
0806: /**
0807: * Adds a new <code>CONSTANT_Double_info</code>
0808: * structure.
0809: *
0810: * @return the index of the added entry.
0811: */
0812: public int addDoubleInfo(double d) {
0813: int i = addItem(new DoubleInfo(d));
0814: addItem(new ConstInfoPadding());
0815: return i;
0816: }
0817:
0818: /**
0819: * Adds a new <code>CONSTANT_Utf8_info</code>
0820: * structure.
0821: *
0822: * <p>If the given utf8 string has been already recorded in the
0823: * table, then this method does not add a new entry to avoid adding
0824: * a duplicated entry.
0825: * Instead, it returns the index of the entry already recorded.
0826: *
0827: * @return the index of the added entry.
0828: */
0829: public int addUtf8Info(String utf8) {
0830: Utf8Info info = (Utf8Info) strings.get(utf8);
0831: if (info != null)
0832: return info.index;
0833: else {
0834: info = new Utf8Info(utf8, numOfItems);
0835: strings.put(utf8, info);
0836: return addItem(info);
0837: }
0838: }
0839:
0840: /**
0841: * Get all the class names.
0842: *
0843: * @return a set of class names
0844: */
0845: public Set getClassNames() {
0846: HashSet result = new HashSet();
0847: LongVector v = items;
0848: int size = numOfItems;
0849: for (int i = 1; i < size; ++i) {
0850: String className = ((ConstInfo) v.elementAt(i))
0851: .getClassName(this );
0852: if (className != null)
0853: result.add(className);
0854: }
0855: return result;
0856: }
0857:
0858: /**
0859: * Replaces all occurrences of a class name.
0860: *
0861: * @param oldName the replaced name (JVM-internal representation).
0862: * @param newName the substituted name (JVM-internal representation).
0863: */
0864: public void renameClass(String oldName, String newName) {
0865: LongVector v = items;
0866: int size = numOfItems;
0867: classes = new HashMap(classes.size() * 2);
0868: for (int i = 1; i < size; ++i) {
0869: ConstInfo ci = (ConstInfo) v.elementAt(i);
0870: ci.renameClass(this , oldName, newName);
0871: ci.makeHashtable(this );
0872: }
0873: }
0874:
0875: /**
0876: * Replaces all occurrences of class names.
0877: *
0878: * @param classnames specifies pairs of replaced and substituted
0879: * name.
0880: */
0881: public void renameClass(Map classnames) {
0882: LongVector v = items;
0883: int size = numOfItems;
0884: classes = new HashMap(classes.size() * 2);
0885: for (int i = 1; i < size; ++i) {
0886: ConstInfo ci = (ConstInfo) v.elementAt(i);
0887: ci.renameClass(this , classnames);
0888: ci.makeHashtable(this );
0889: }
0890: }
0891:
0892: private void read(DataInputStream in) throws IOException {
0893: int n = in.readUnsignedShort();
0894:
0895: items = new LongVector(n);
0896: numOfItems = 0;
0897: addItem(null); // index 0 is reserved by the JVM.
0898:
0899: while (--n > 0) { // index 0 is reserved by JVM
0900: int tag = readOne(in);
0901: if ((tag == LongInfo.tag) || (tag == DoubleInfo.tag)) {
0902: addItem(new ConstInfoPadding());
0903: --n;
0904: }
0905: }
0906:
0907: int i = 1;
0908: while (true) {
0909: ConstInfo info = (ConstInfo) items.elementAt(i++);
0910: if (info == null)
0911: break;
0912: else
0913: info.makeHashtable(this );
0914: }
0915: }
0916:
0917: private int readOne(DataInputStream in) throws IOException {
0918: ConstInfo info;
0919: int tag = in.readUnsignedByte();
0920: switch (tag) {
0921: case Utf8Info.tag: // 1
0922: info = new Utf8Info(in, numOfItems);
0923: strings.put(((Utf8Info) info).string, info);
0924: break;
0925: case IntegerInfo.tag: // 3
0926: info = new IntegerInfo(in);
0927: break;
0928: case FloatInfo.tag: // 4
0929: info = new FloatInfo(in);
0930: break;
0931: case LongInfo.tag: // 5
0932: info = new LongInfo(in);
0933: break;
0934: case DoubleInfo.tag: // 6
0935: info = new DoubleInfo(in);
0936: break;
0937: case ClassInfo.tag: // 7
0938: info = new ClassInfo(in, numOfItems);
0939: // classes.put(<classname>, info);
0940: break;
0941: case StringInfo.tag: // 8
0942: info = new StringInfo(in);
0943: break;
0944: case FieldrefInfo.tag: // 9
0945: info = new FieldrefInfo(in);
0946: break;
0947: case MethodrefInfo.tag: // 10
0948: info = new MethodrefInfo(in);
0949: break;
0950: case InterfaceMethodrefInfo.tag: // 11
0951: info = new InterfaceMethodrefInfo(in);
0952: break;
0953: case NameAndTypeInfo.tag: // 12
0954: info = new NameAndTypeInfo(in);
0955: break;
0956: default:
0957: throw new IOException("invalid constant type: " + tag);
0958: }
0959:
0960: addItem(info);
0961: return tag;
0962: }
0963:
0964: /**
0965: * Writes the contents of the constant pool table.
0966: */
0967: public void write(DataOutputStream out) throws IOException {
0968: out.writeShort(numOfItems);
0969: LongVector v = items;
0970: int size = numOfItems;
0971: for (int i = 1; i < size; ++i)
0972: ((ConstInfo) v.elementAt(i)).write(out);
0973: }
0974:
0975: /**
0976: * Prints the contents of the constant pool table.
0977: */
0978: public void print() {
0979: print(new PrintWriter(System.out, true));
0980: }
0981:
0982: /**
0983: * Prints the contents of the constant pool table.
0984: */
0985: public void print(PrintWriter out) {
0986: int size = numOfItems;
0987: for (int i = 1; i < size; ++i) {
0988: out.print(i);
0989: out.print(" ");
0990: ((ConstInfo) items.elementAt(i)).print(out);
0991: }
0992: }
0993: }
0994:
0995: abstract class ConstInfo {
0996: public abstract int getTag();
0997:
0998: public String getClassName(ConstPool cp) {
0999: return null;
1000: }
1001:
1002: public void renameClass(ConstPool cp, String oldName, String newName) {
1003: }
1004:
1005: public void renameClass(ConstPool cp, Map classnames) {
1006: }
1007:
1008: public abstract int copy(ConstPool src, ConstPool dest,
1009: Map classnames);
1010:
1011: // ** classnames is a mapping between JVM names.
1012:
1013: public abstract void write(DataOutputStream out) throws IOException;
1014:
1015: public abstract void print(PrintWriter out);
1016:
1017: void makeHashtable(ConstPool cp) {
1018: } // called after read() finishes in ConstPool.
1019:
1020: public String toString() {
1021: ByteArrayOutputStream bout = new ByteArrayOutputStream();
1022: PrintWriter out = new PrintWriter(bout);
1023: print(out);
1024: return bout.toString();
1025: }
1026: }
1027:
1028: /* padding following DoubleInfo or LongInfo.
1029: */
1030: class ConstInfoPadding extends ConstInfo {
1031: public int getTag() {
1032: return 0;
1033: }
1034:
1035: public int copy(ConstPool src, ConstPool dest, Map map) {
1036: return dest.addConstInfoPadding();
1037: }
1038:
1039: public void write(DataOutputStream out) throws IOException {
1040: }
1041:
1042: public void print(PrintWriter out) {
1043: out.println("padding");
1044: }
1045: }
1046:
1047: class ClassInfo extends ConstInfo {
1048: static final int tag = 7;
1049: int name;
1050: int index;
1051:
1052: public ClassInfo(int className, int i) {
1053: name = className;
1054: index = i;
1055: }
1056:
1057: public ClassInfo(DataInputStream in, int i) throws IOException {
1058: name = in.readUnsignedShort();
1059: index = i;
1060: }
1061:
1062: public int getTag() {
1063: return tag;
1064: }
1065:
1066: public String getClassName(ConstPool cp) {
1067: return cp.getUtf8Info(name);
1068: };
1069:
1070: public void renameClass(ConstPool cp, String oldName, String newName) {
1071: String nameStr = cp.getUtf8Info(name);
1072: if (nameStr.equals(oldName))
1073: name = cp.addUtf8Info(newName);
1074: else if (nameStr.charAt(0) == '[') {
1075: String nameStr2 = Descriptor.rename(nameStr, oldName,
1076: newName);
1077: if (nameStr != nameStr2)
1078: name = cp.addUtf8Info(nameStr2);
1079: }
1080: }
1081:
1082: public void renameClass(ConstPool cp, Map map) {
1083: String oldName = cp.getUtf8Info(name);
1084: if (oldName.charAt(0) == '[') {
1085: String newName = Descriptor.rename(oldName, map);
1086: if (oldName != newName)
1087: name = cp.addUtf8Info(newName);
1088: } else {
1089: String newName = (String) map.get(oldName);
1090: if (newName != null && !newName.equals(oldName))
1091: name = cp.addUtf8Info(newName);
1092: }
1093: }
1094:
1095: public int copy(ConstPool src, ConstPool dest, Map map) {
1096: String classname = src.getUtf8Info(name);
1097: if (map != null) {
1098: String newname = (String) map.get(classname);
1099: if (newname != null)
1100: classname = newname;
1101: }
1102:
1103: return dest.addClassInfo(classname);
1104: }
1105:
1106: public void write(DataOutputStream out) throws IOException {
1107: out.writeByte(tag);
1108: out.writeShort(name);
1109: }
1110:
1111: public void print(PrintWriter out) {
1112: out.print("Class #");
1113: out.println(name);
1114: }
1115:
1116: void makeHashtable(ConstPool cp) {
1117: String name = Descriptor.toJavaName(getClassName(cp));
1118: cp.classes.put(name, this );
1119: }
1120: }
1121:
1122: class NameAndTypeInfo extends ConstInfo {
1123: static final int tag = 12;
1124: int memberName;
1125: int typeDescriptor;
1126:
1127: public NameAndTypeInfo(int name, int type) {
1128: memberName = name;
1129: typeDescriptor = type;
1130: }
1131:
1132: public NameAndTypeInfo(DataInputStream in) throws IOException {
1133: memberName = in.readUnsignedShort();
1134: typeDescriptor = in.readUnsignedShort();
1135: }
1136:
1137: public int getTag() {
1138: return tag;
1139: }
1140:
1141: public void renameClass(ConstPool cp, String oldName, String newName) {
1142: String type = cp.getUtf8Info(typeDescriptor);
1143: String type2 = Descriptor.rename(type, oldName, newName);
1144: if (type != type2)
1145: typeDescriptor = cp.addUtf8Info(type2);
1146: }
1147:
1148: public void renameClass(ConstPool cp, Map map) {
1149: String type = cp.getUtf8Info(typeDescriptor);
1150: String type2 = Descriptor.rename(type, map);
1151: if (type != type2)
1152: typeDescriptor = cp.addUtf8Info(type2);
1153: }
1154:
1155: public int copy(ConstPool src, ConstPool dest, Map map) {
1156: String mname = src.getUtf8Info(memberName);
1157: String tdesc = src.getUtf8Info(typeDescriptor);
1158: tdesc = Descriptor.rename(tdesc, map);
1159: return dest.addNameAndTypeInfo(dest.addUtf8Info(mname), dest
1160: .addUtf8Info(tdesc));
1161: }
1162:
1163: public void write(DataOutputStream out) throws IOException {
1164: out.writeByte(tag);
1165: out.writeShort(memberName);
1166: out.writeShort(typeDescriptor);
1167: }
1168:
1169: public void print(PrintWriter out) {
1170: out.print("NameAndType #");
1171: out.print(memberName);
1172: out.print(", type #");
1173: out.println(typeDescriptor);
1174: }
1175: }
1176:
1177: abstract class MemberrefInfo extends ConstInfo {
1178: int classIndex;
1179: int nameAndTypeIndex;
1180:
1181: public MemberrefInfo(int cindex, int ntindex) {
1182: classIndex = cindex;
1183: nameAndTypeIndex = ntindex;
1184: }
1185:
1186: public MemberrefInfo(DataInputStream in) throws IOException {
1187: classIndex = in.readUnsignedShort();
1188: nameAndTypeIndex = in.readUnsignedShort();
1189: }
1190:
1191: public int copy(ConstPool src, ConstPool dest, Map map) {
1192: int classIndex2 = src.getItem(classIndex).copy(src, dest, map);
1193: int ntIndex2 = src.getItem(nameAndTypeIndex).copy(src, dest,
1194: map);
1195: return copy2(dest, classIndex2, ntIndex2);
1196: }
1197:
1198: abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
1199:
1200: public void write(DataOutputStream out) throws IOException {
1201: out.writeByte(getTag());
1202: out.writeShort(classIndex);
1203: out.writeShort(nameAndTypeIndex);
1204: }
1205:
1206: public void print(PrintWriter out) {
1207: out.print(getTagName() + " #");
1208: out.print(classIndex);
1209: out.print(", name&type #");
1210: out.println(nameAndTypeIndex);
1211: }
1212:
1213: public abstract String getTagName();
1214: }
1215:
1216: class FieldrefInfo extends MemberrefInfo {
1217: static final int tag = 9;
1218:
1219: public FieldrefInfo(int cindex, int ntindex) {
1220: super (cindex, ntindex);
1221: }
1222:
1223: public FieldrefInfo(DataInputStream in) throws IOException {
1224: super (in);
1225: }
1226:
1227: public int getTag() {
1228: return tag;
1229: }
1230:
1231: public String getTagName() {
1232: return "Field";
1233: }
1234:
1235: protected int copy2(ConstPool dest, int cindex, int ntindex) {
1236: return dest.addFieldrefInfo(cindex, ntindex);
1237: }
1238: }
1239:
1240: class MethodrefInfo extends MemberrefInfo {
1241: static final int tag = 10;
1242:
1243: public MethodrefInfo(int cindex, int ntindex) {
1244: super (cindex, ntindex);
1245: }
1246:
1247: public MethodrefInfo(DataInputStream in) throws IOException {
1248: super (in);
1249: }
1250:
1251: public int getTag() {
1252: return tag;
1253: }
1254:
1255: public String getTagName() {
1256: return "Method";
1257: }
1258:
1259: protected int copy2(ConstPool dest, int cindex, int ntindex) {
1260: return dest.addMethodrefInfo(cindex, ntindex);
1261: }
1262: }
1263:
1264: class InterfaceMethodrefInfo extends MemberrefInfo {
1265: static final int tag = 11;
1266:
1267: public InterfaceMethodrefInfo(int cindex, int ntindex) {
1268: super (cindex, ntindex);
1269: }
1270:
1271: public InterfaceMethodrefInfo(DataInputStream in)
1272: throws IOException {
1273: super (in);
1274: }
1275:
1276: public int getTag() {
1277: return tag;
1278: }
1279:
1280: public String getTagName() {
1281: return "Interface";
1282: }
1283:
1284: protected int copy2(ConstPool dest, int cindex, int ntindex) {
1285: return dest.addInterfaceMethodrefInfo(cindex, ntindex);
1286: }
1287: }
1288:
1289: class StringInfo extends ConstInfo {
1290: static final int tag = 8;
1291: int string;
1292:
1293: public StringInfo(int str) {
1294: string = str;
1295: }
1296:
1297: public StringInfo(DataInputStream in) throws IOException {
1298: string = in.readUnsignedShort();
1299: }
1300:
1301: public int getTag() {
1302: return tag;
1303: }
1304:
1305: public int copy(ConstPool src, ConstPool dest, Map map) {
1306: return dest.addStringInfo(src.getUtf8Info(string));
1307: }
1308:
1309: public void write(DataOutputStream out) throws IOException {
1310: out.writeByte(tag);
1311: out.writeShort(string);
1312: }
1313:
1314: public void print(PrintWriter out) {
1315: out.print("String #");
1316: out.println(string);
1317: }
1318: }
1319:
1320: class IntegerInfo extends ConstInfo {
1321: static final int tag = 3;
1322: int value;
1323:
1324: public IntegerInfo(int i) {
1325: value = i;
1326: }
1327:
1328: public IntegerInfo(DataInputStream in) throws IOException {
1329: value = in.readInt();
1330: }
1331:
1332: public int getTag() {
1333: return tag;
1334: }
1335:
1336: public int copy(ConstPool src, ConstPool dest, Map map) {
1337: return dest.addIntegerInfo(value);
1338: }
1339:
1340: public void write(DataOutputStream out) throws IOException {
1341: out.writeByte(tag);
1342: out.writeInt(value);
1343: }
1344:
1345: public void print(PrintWriter out) {
1346: out.print("Integer ");
1347: out.println(value);
1348: }
1349: }
1350:
1351: class FloatInfo extends ConstInfo {
1352: static final int tag = 4;
1353: float value;
1354:
1355: public FloatInfo(float f) {
1356: value = f;
1357: }
1358:
1359: public FloatInfo(DataInputStream in) throws IOException {
1360: value = in.readFloat();
1361: }
1362:
1363: public int getTag() {
1364: return tag;
1365: }
1366:
1367: public int copy(ConstPool src, ConstPool dest, Map map) {
1368: return dest.addFloatInfo(value);
1369: }
1370:
1371: public void write(DataOutputStream out) throws IOException {
1372: out.writeByte(tag);
1373: out.writeFloat(value);
1374: }
1375:
1376: public void print(PrintWriter out) {
1377: out.print("Float ");
1378: out.println(value);
1379: }
1380: }
1381:
1382: class LongInfo extends ConstInfo {
1383: static final int tag = 5;
1384: long value;
1385:
1386: public LongInfo(long l) {
1387: value = l;
1388: }
1389:
1390: public LongInfo(DataInputStream in) throws IOException {
1391: value = in.readLong();
1392: }
1393:
1394: public int getTag() {
1395: return tag;
1396: }
1397:
1398: public int copy(ConstPool src, ConstPool dest, Map map) {
1399: return dest.addLongInfo(value);
1400: }
1401:
1402: public void write(DataOutputStream out) throws IOException {
1403: out.writeByte(tag);
1404: out.writeLong(value);
1405: }
1406:
1407: public void print(PrintWriter out) {
1408: out.print("Long ");
1409: out.println(value);
1410: }
1411: }
1412:
1413: class DoubleInfo extends ConstInfo {
1414: static final int tag = 6;
1415: double value;
1416:
1417: public DoubleInfo(double d) {
1418: value = d;
1419: }
1420:
1421: public DoubleInfo(DataInputStream in) throws IOException {
1422: value = in.readDouble();
1423: }
1424:
1425: public int getTag() {
1426: return tag;
1427: }
1428:
1429: public int copy(ConstPool src, ConstPool dest, Map map) {
1430: return dest.addDoubleInfo(value);
1431: }
1432:
1433: public void write(DataOutputStream out) throws IOException {
1434: out.writeByte(tag);
1435: out.writeDouble(value);
1436: }
1437:
1438: public void print(PrintWriter out) {
1439: out.print("Double ");
1440: out.println(value);
1441: }
1442: }
1443:
1444: class Utf8Info extends ConstInfo {
1445: static final int tag = 1;
1446: String string;
1447: int index;
1448:
1449: public Utf8Info(String utf8, int i) {
1450: string = utf8;
1451: index = i;
1452: }
1453:
1454: public Utf8Info(DataInputStream in, int i) throws IOException {
1455: string = in.readUTF();
1456: index = i;
1457: }
1458:
1459: public int getTag() {
1460: return tag;
1461: }
1462:
1463: public int copy(ConstPool src, ConstPool dest, Map map) {
1464: return dest.addUtf8Info(string);
1465: }
1466:
1467: public void write(DataOutputStream out) throws IOException {
1468: out.writeByte(tag);
1469: out.writeUTF(string);
1470: }
1471:
1472: public void print(PrintWriter out) {
1473: out.print("UTF8 \"");
1474: out.print(string);
1475: out.println("\"");
1476: }
1477: }
|