summaryrefslogtreecommitdiffstats
path: root/src/main/javassist/bytecode
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/bytecode')
-rw-r--r--src/main/javassist/bytecode/AnnotationsAttribute.java1068
-rw-r--r--src/main/javassist/bytecode/MethodInfo.java755
-rw-r--r--src/main/javassist/bytecode/annotation/ClassMemberValue.java132
3 files changed, 1057 insertions, 898 deletions
diff --git a/src/main/javassist/bytecode/AnnotationsAttribute.java b/src/main/javassist/bytecode/AnnotationsAttribute.java
index a6dfe87a..2483c01b 100644
--- a/src/main/javassist/bytecode/AnnotationsAttribute.java
+++ b/src/main/javassist/bytecode/AnnotationsAttribute.java
@@ -15,30 +15,46 @@
package javassist.bytecode;
-import java.util.Map;
-import java.io.IOException;
-import java.io.DataInputStream;
-import java.io.ByteArrayOutputStream;
+import javassist.bytecode.annotation.Annotation;
+import javassist.bytecode.annotation.AnnotationMemberValue;
+import javassist.bytecode.annotation.AnnotationsWriter;
+import javassist.bytecode.annotation.ArrayMemberValue;
+import javassist.bytecode.annotation.BooleanMemberValue;
+import javassist.bytecode.annotation.ByteMemberValue;
+import javassist.bytecode.annotation.CharMemberValue;
+import javassist.bytecode.annotation.ClassMemberValue;
+import javassist.bytecode.annotation.DoubleMemberValue;
+import javassist.bytecode.annotation.EnumMemberValue;
+import javassist.bytecode.annotation.FloatMemberValue;
+import javassist.bytecode.annotation.IntegerMemberValue;
+import javassist.bytecode.annotation.LongMemberValue;
+import javassist.bytecode.annotation.MemberValue;
+import javassist.bytecode.annotation.ShortMemberValue;
+import javassist.bytecode.annotation.StringMemberValue;
-import javassist.bytecode.annotation.*;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
/**
* A class representing
* <code>RuntimeVisibleAnnotations_attribute</code> and
* <code>RuntimeInvisibleAnnotations_attribute</code>.
- *
+ * <p/>
* <p>To obtain an AnnotationAttribute object, invoke
* <code>getAttribute(AnnotationsAttribute.invisibleTag)</code>
* in <code>ClassFile</code>, <code>MethodInfo</code>,
* or <code>FieldInfo</code>. The obtained attribute is a
- * runtime invisible annotations attribute.
+ * runtime invisible annotations attribute.
* If the parameter is
* <code>AnnotationAttribute.visibleTag</code>, then the obtained
* attribute is a runtime visible one.
- *
+ * <p/>
* <p>If you want to record a new AnnotationAttribute object, execute the
* following snippet:
- *
+ * <p/>
* <ul><pre>
* ClassFile cf = ... ;
* ConstPool cp = cf.getConstPool();
@@ -50,471 +66,571 @@ import javassist.bytecode.annotation.*;
* cf.addAttribute(attr);
* </pre></ul>
*/
-public class AnnotationsAttribute extends AttributeInfo {
- /**
- * The name of the <code>RuntimeVisibleAnnotations</code> attribute.
- */
- public static final String visibleTag = "RuntimeVisibleAnnotations";
-
- /**
- * The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
- */
- public static final String invisibleTag = "RuntimeInvisibleAnnotations";
-
- /**
- * Constructs a <code>Runtime(In)VisisbleAnnotations_attribute</code>.
- *
- * @param cp constant pool
- * @param attrname attribute name (<code>visibleTag</code> or
- * <code>invisibleTag</code>).
- * @param info the contents of this attribute. It does not
- * include <code>attribute_name_index</code> or
- * <code>attribute_length</code>.
- */
- public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info) {
- super(cp, attrname, info);
- }
-
- /**
- * Constructs an empty
- * <code>Runtime(In)VisisbleAnnotations_attribute</code>.
- * A new annotation can be later added to the created attribute
- * by <code>setAnnotations()</code>.
- *
- * @param cp constant pool
- * @param attrname attribute name (<code>visibleTag</code> or
- * <code>invisibleTag</code>).
- * @see #setAnnotations(Annotation[])
- */
- public AnnotationsAttribute(ConstPool cp, String attrname) {
- this(cp, attrname, new byte[] { 0, 0 });
- }
-
- /**
- * @param n the attribute name.
- */
- AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
- throws IOException
- {
- super(cp, n, in);
- }
-
- /**
- * Returns <code>num_annotations</code>.
- */
- public int numAnnotations() {
- return ByteArray.readU16bit(info, 0);
- }
-
- /**
- * Copies this attribute and returns a new copy.
- */
- public AttributeInfo copy(ConstPool newCp, Map classnames) {
- Copier copier = new Copier(info, constPool, newCp, classnames);
- try {
- copier.annotationArray();
- return new AnnotationsAttribute(newCp, getName(), copier.close());
- }
- catch (Exception e) {
- throw new RuntimeException(e.toString());
- }
- }
-
- /**
- * Parses the annotations and returns a data structure representing
- * that parsed annotations. Note that changes of the node values of the
- * returned tree are not reflected on the annotations represented by
- * this object unless the tree is copied back to this object by
- * <code>setAnnotations()</code>.
- *
- * @see #setAnnotations(Annotation[])
- */
- public Annotation[] getAnnotations() {
- try {
- return new Parser(info, constPool).parseAnnotations();
- }
- catch (Exception e) {
- throw new RuntimeException(e.toString());
- }
- }
-
- /**
- * Changes the annotations represented by this object according to
- * the given array of <code>Annotation</code> objects.
- *
- * @param annotations the data structure representing the
- * new annotations.
- */
- public void setAnnotations(Annotation[] annotations) {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
- try {
- int n = annotations.length;
- writer.numAnnotations(n);
- for (int i = 0; i < n; ++i)
- annotations[i].write(writer);
-
- writer.close();
- }
- catch (IOException e) {
- throw new RuntimeException(e); // should never reach here.
- }
-
- set(output.toByteArray());
- }
-
- /**
- * Changes the annotations. A call to this method is equivalent to:
- * <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul>
- *
- * @param annotation the data structure representing
- * the new annotation.
- */
- public void setAnnotation(Annotation annotation) {
- setAnnotations(new Annotation[] { annotation });
- }
-
- /**
- * Returns a string representation of this object.
- */
- public String toString() {
- Annotation[] a = getAnnotations();
- StringBuffer sbuf = new StringBuffer();
- int i = 0;
- while (i < a.length) {
- sbuf.append(a[i++].toString());
- if (i != a.length)
- sbuf.append(", ");
- }
-
- return sbuf.toString();
- }
-
- static class Walker {
- byte[] info;
-
- Walker(byte[] attrInfo) {
- info = attrInfo;
- }
-
- final void parameters() throws Exception {
- int numParam = info[0] & 0xff;
- parameters(numParam, 1);
- }
-
- void parameters(int numParam, int pos) throws Exception {
- for (int i = 0; i < numParam; ++i)
- pos = annotationArray(pos);
- }
-
- final void annotationArray() throws Exception {
- annotationArray(0);
- }
-
- final int annotationArray(int pos) throws Exception {
- int num = ByteArray.readU16bit(info, pos);
- return annotationArray(pos + 2, num);
- }
-
- int annotationArray(int pos, int num) throws Exception {
- for (int i = 0; i < num; ++i)
- pos = annotation(pos);
-
- return pos;
- }
-
- final int annotation(int pos) throws Exception {
- int type = ByteArray.readU16bit(info, pos);
- int numPairs = ByteArray.readU16bit(info, pos + 2);
- return annotation(pos + 4, type, numPairs);
- }
-
- int annotation(int pos, int type, int numPairs) throws Exception {
- for (int j = 0; j < numPairs; ++j)
- pos = memberValuePair(pos);
-
- return pos;
- }
-
- final int memberValuePair(int pos) throws Exception {
- int nameIndex = ByteArray.readU16bit(info, pos);
- return memberValuePair(pos + 2, nameIndex);
- }
-
- int memberValuePair(int pos, int nameIndex) throws Exception {
- return memberValue(pos);
- }
-
- final int memberValue(int pos) throws Exception {
- int tag = info[pos] & 0xff;
- if (tag == 'e') {
- int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
- int constNameIndex = ByteArray.readU16bit(info, pos + 3);
- enumMemberValue(typeNameIndex, constNameIndex);
- return pos + 5;
- }
- else if (tag == 'c') {
- int index = ByteArray.readU16bit(info, pos + 1);
- classMemberValue(index);
- return pos + 3;
- }
- else if (tag == '@')
- return annotationMemberValue(pos + 1);
- else if (tag == '[') {
- int num = ByteArray.readU16bit(info, pos + 1);
- return arrayMemberValue(pos + 3, num);
- }
- else { // primitive types or String.
- int index = ByteArray.readU16bit(info, pos + 1);
- constValueMember(tag, index);
- return pos + 3;
- }
- }
-
- void constValueMember(int tag, int index) throws Exception {}
-
- void enumMemberValue(int typeNameIndex, int constNameIndex)
- throws Exception {}
-
- void classMemberValue(int index) throws Exception {}
-
- int annotationMemberValue(int pos) throws Exception {
- return annotation(pos);
- }
-
- int arrayMemberValue(int pos, int num) throws Exception {
- for (int i = 0; i < num; ++i) {
- pos = memberValue(pos);
- }
-
- return pos;
- }
- }
-
- static class Copier extends Walker {
- ByteArrayOutputStream output;
- AnnotationsWriter writer;
- ConstPool srcPool, destPool;
- Map classnames;
-
- /**
- * Constructs a copier. This copier renames some class names
- * into the new names specified by <code>map</code> when it copies
- * an annotation attribute.
- *
- * @param info the source attribute.
- * @param src the constant pool of the source class.
- * @param dest the constant pool of the destination class.
- * @param map pairs of replaced and substituted class names.
- * It can be null.
- */
- Copier(byte[] info, ConstPool src, ConstPool dest, Map map) {
- super(info);
- output = new ByteArrayOutputStream();
- writer = new AnnotationsWriter(output, dest);
- srcPool = src;
- destPool = dest;
- classnames = map;
- }
-
- byte[] close() throws IOException {
- writer.close();
- return output.toByteArray();
- }
-
- void parameters(int numParam, int pos) throws Exception {
- writer.numParameters(numParam);
- super.parameters(numParam, pos);
- }
-
- int annotationArray(int pos, int num) throws Exception {
- writer.numAnnotations(num);
- return super.annotationArray(pos, num);
- }
-
- int annotation(int pos, int type, int numPairs) throws Exception {
- writer.annotation(copy(type), numPairs);
- return super.annotation(pos, type, numPairs);
- }
-
- int memberValuePair(int pos, int nameIndex) throws Exception {
- writer.memberValuePair(copy(nameIndex));
- return super.memberValuePair(pos, nameIndex);
- }
-
- void constValueMember(int tag, int index) throws Exception {
- writer.constValueIndex(tag, copy(index));
- super.constValueMember(tag, index);
- }
-
- void enumMemberValue(int typeNameIndex, int constNameIndex)
- throws Exception
- {
- writer.enumConstValue(copy(typeNameIndex), copy(constNameIndex));
- super.enumMemberValue(typeNameIndex, constNameIndex);
- }
-
- void classMemberValue(int index) throws Exception {
- writer.classInfoIndex(copy(index));
- super.classMemberValue(index);
- }
-
- int annotationMemberValue(int pos) throws Exception {
- writer.annotationValue();
- return super.annotationMemberValue(pos);
- }
-
- int arrayMemberValue(int pos, int num) throws Exception {
- writer.arrayValue(num);
- return super.arrayMemberValue(pos, num);
- }
-
- /**
- * Copies a constant pool entry into the destination constant pool
- * and returns the index of the copied entry.
- *
- * @param srcIndex the index of the copied entry into the source
- * constant pool.
- * @return the index of the copied item into the destination
- * constant pool.
- */
- int copy(int srcIndex) {
- return srcPool.copy(srcIndex, destPool, classnames);
- }
- }
-
- static class Parser extends Walker {
- ConstPool pool;
- Annotation[][] allParams; // all parameters
- Annotation[] allAnno; // all annotations
- Annotation currentAnno; // current annotation
- MemberValue memberValue;
-
- /**
- * Constructs a parser. This parser constructs a parse tree of
- * the annotations.
- *
- * @param info the attribute.
- * @param src the constant pool.
- */
- Parser(byte[] info, ConstPool cp) {
- super(info);
- pool = cp;
- }
-
- Annotation[][] parseParameters() throws Exception {
- parameters();
- return allParams;
- }
-
- Annotation[] parseAnnotations() throws Exception {
- annotationArray();
- return allAnno;
- }
-
- void parameters(int numParam, int pos) throws Exception {
- Annotation[][] params = new Annotation[numParam][];
- for (int i = 0; i < numParam; ++i) {
- pos = annotationArray(pos);
- params[i] = allAnno;
- }
-
- allParams = params;
- }
-
- int annotationArray(int pos, int num) throws Exception {
- Annotation[] array = new Annotation[num];
- for (int i = 0; i < num; ++i) {
- pos = annotation(pos);
- array[i] = currentAnno;
- }
-
- allAnno = array;
- return pos;
- }
-
- int annotation(int pos, int type, int numPairs) throws Exception {
- currentAnno = new Annotation(type, pool);
- return super.annotation(pos, type, numPairs);
- }
-
- int memberValuePair(int pos, int nameIndex) throws Exception {
- pos = super.memberValuePair(pos, nameIndex);
- currentAnno.addMemberValue(nameIndex, memberValue);
- return pos;
- }
-
- void constValueMember(int tag, int index) throws Exception {
- MemberValue m;
- ConstPool cp = pool;
- switch (tag) {
- case 'B' :
- m = new ByteMemberValue(index, cp);
- break;
- case 'C' :
- m = new CharMemberValue(index, cp);
- break;
- case 'D' :
- m = new DoubleMemberValue(index, cp);
- break;
- case 'F' :
- m = new FloatMemberValue(index, cp);
- break;
- case 'I' :
- m = new IntegerMemberValue(index, cp);
- break;
- case 'J' :
- m = new LongMemberValue(index, cp);
- break;
- case 'S' :
- m = new ShortMemberValue(index, cp);
- break;
- case 'Z' :
- m = new BooleanMemberValue(index, cp);
- break;
- case 's' :
- m = new StringMemberValue(index, cp);
- break;
- default :
- throw new RuntimeException("unknown tag:" + tag);
- }
-
- memberValue = m;
- super.constValueMember(tag, index);
- }
-
- void enumMemberValue(int typeNameIndex, int constNameIndex)
- throws Exception
- {
- memberValue = new EnumMemberValue(typeNameIndex,
- constNameIndex, pool);
- super.enumMemberValue(typeNameIndex, constNameIndex);
- }
-
- void classMemberValue(int index) throws Exception {
- memberValue = new ClassMemberValue(index, pool);
- super.classMemberValue(index);
- }
-
- int annotationMemberValue(int pos) throws Exception {
- Annotation anno = currentAnno;
- pos = super.annotationMemberValue(pos);
- memberValue = new AnnotationMemberValue(currentAnno, pool);
- currentAnno = anno;
- return pos;
- }
-
- int arrayMemberValue(int pos, int num) throws Exception {
- ArrayMemberValue amv = new ArrayMemberValue(pool);
- MemberValue[] elements = new MemberValue[num];
- for (int i = 0; i < num; ++i) {
- pos = memberValue(pos);
- elements[i] = memberValue;
- }
-
- amv.setValue(elements);
- memberValue = amv;
- return pos;
- }
- }
+public class AnnotationsAttribute extends AttributeInfo
+{
+ /**
+ * The name of the <code>RuntimeVisibleAnnotations</code> attribute.
+ */
+ public static final String visibleTag = "RuntimeVisibleAnnotations";
+
+ /**
+ * The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
+ */
+ public static final String invisibleTag = "RuntimeInvisibleAnnotations";
+
+ private HashMap annotationMap;
+
+ /**
+ * Constructs a <code>Runtime(In)VisisbleAnnotations_attribute</code>.
+ *
+ * @param cp constant pool
+ * @param attrname attribute name (<code>visibleTag</code> or
+ * <code>invisibleTag</code>).
+ * @param info the contents of this attribute. It does not
+ * include <code>attribute_name_index</code> or
+ * <code>attribute_length</code>.
+ */
+ public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info)
+ {
+ super(cp, attrname, info);
+ }
+
+ /**
+ * Constructs an empty
+ * <code>Runtime(In)VisisbleAnnotations_attribute</code>.
+ * A new annotation can be later added to the created attribute
+ * by <code>setAnnotations()</code>.
+ *
+ * @param cp constant pool
+ * @param attrname attribute name (<code>visibleTag</code> or
+ * <code>invisibleTag</code>).
+ * @see #setAnnotations(Annotation[])
+ */
+ public AnnotationsAttribute(ConstPool cp, String attrname)
+ {
+ this(cp, attrname, new byte[]{0, 0});
+ }
+
+ /**
+ * @param n the attribute name.
+ */
+ AnnotationsAttribute(ConstPool cp, int n, DataInputStream in)
+ throws IOException
+ {
+ super(cp, n, in);
+ }
+
+ /**
+ * Returns <code>num_annotations</code>.
+ */
+ public int numAnnotations()
+ {
+ return ByteArray.readU16bit(info, 0);
+ }
+
+ /**
+ * Copies this attribute and returns a new copy.
+ */
+ public AttributeInfo copy(ConstPool newCp, Map classnames)
+ {
+ Copier copier = new Copier(info, constPool, newCp, classnames);
+ try
+ {
+ copier.annotationArray();
+ return new AnnotationsAttribute(newCp, getName(), copier.close());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ public Annotation getAnnotation(String type)
+ {
+ Annotation[] annotations = getAnnotations();
+ for (int i = 0; i < annotations.length; i++)
+ {
+ if (annotations[i].getTypeName().equals(type)) return annotations[i];
+ }
+ return null;
+ }
+
+ public void addAnnotation(Annotation annotation)
+ {
+ String type = annotation.getTypeName();
+ Annotation[] annotations = getAnnotations();
+ for (int i = 0; i < annotations.length; i++)
+ {
+ if (annotations[i].getTypeName().equals(type))
+ {
+ annotations[i] = annotation;
+ setAnnotations(annotations);
+ return;
+ }
+ }
+ Annotation[] newlist = new Annotation[annotations.length + 1];
+ System.arraycopy(annotations, 0, newlist, 0, annotations.length);
+ newlist[annotations.length] = annotation;
+ setAnnotations(newlist);
+ }
+
+ /**
+ * Parses the annotations and returns a data structure representing
+ * that parsed annotations. Note that changes of the node values of the
+ * returned tree are not reflected on the annotations represented by
+ * this object unless the tree is copied back to this object by
+ * <code>setAnnotations()</code>.
+ *
+ * @see #setAnnotations(Annotation[])
+ */
+ public Annotation[] getAnnotations()
+ {
+ try
+ {
+ return new Parser(info, constPool).parseAnnotations();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * Changes the annotations represented by this object according to
+ * the given array of <code>Annotation</code> objects.
+ *
+ * @param annotations the data structure representing the
+ * new annotations.
+ */
+ public void setAnnotations(Annotation[] annotations)
+ {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
+ try
+ {
+ int n = annotations.length;
+ writer.numAnnotations(n);
+ for (int i = 0; i < n; ++i)
+ annotations[i].write(writer);
+
+ writer.close();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e); // should never reach here.
+ }
+
+ set(output.toByteArray());
+ }
+
+ /**
+ * Changes the annotations. A call to this method is equivalent to:
+ * <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul>
+ *
+ * @param annotation the data structure representing
+ * the new annotation.
+ */
+ public void setAnnotation(Annotation annotation)
+ {
+ setAnnotations(new Annotation[]{annotation});
+ }
+
+ /**
+ * Returns a string representation of this object.
+ */
+ public String toString()
+ {
+ Annotation[] a = getAnnotations();
+ StringBuffer sbuf = new StringBuffer();
+ int i = 0;
+ while (i < a.length)
+ {
+ sbuf.append(a[i++].toString());
+ if (i != a.length)
+ sbuf.append(", ");
+ }
+
+ return sbuf.toString();
+ }
+
+ static class Walker
+ {
+ byte[] info;
+
+ Walker(byte[] attrInfo)
+ {
+ info = attrInfo;
+ }
+
+ final void parameters() throws Exception
+ {
+ int numParam = info[0] & 0xff;
+ parameters(numParam, 1);
+ }
+
+ void parameters(int numParam, int pos) throws Exception
+ {
+ for (int i = 0; i < numParam; ++i)
+ pos = annotationArray(pos);
+ }
+
+ final void annotationArray() throws Exception
+ {
+ annotationArray(0);
+ }
+
+ final int annotationArray(int pos) throws Exception
+ {
+ int num = ByteArray.readU16bit(info, pos);
+ return annotationArray(pos + 2, num);
+ }
+
+ int annotationArray(int pos, int num) throws Exception
+ {
+ for (int i = 0; i < num; ++i)
+ pos = annotation(pos);
+
+ return pos;
+ }
+
+ final int annotation(int pos) throws Exception
+ {
+ int type = ByteArray.readU16bit(info, pos);
+ int numPairs = ByteArray.readU16bit(info, pos + 2);
+ return annotation(pos + 4, type, numPairs);
+ }
+
+ int annotation(int pos, int type, int numPairs) throws Exception
+ {
+ for (int j = 0; j < numPairs; ++j)
+ pos = memberValuePair(pos);
+
+ return pos;
+ }
+
+ final int memberValuePair(int pos) throws Exception
+ {
+ int nameIndex = ByteArray.readU16bit(info, pos);
+ return memberValuePair(pos + 2, nameIndex);
+ }
+
+ int memberValuePair(int pos, int nameIndex) throws Exception
+ {
+ return memberValue(pos);
+ }
+
+ final int memberValue(int pos) throws Exception
+ {
+ int tag = info[pos] & 0xff;
+ if (tag == 'e')
+ {
+ int typeNameIndex = ByteArray.readU16bit(info, pos + 1);
+ int constNameIndex = ByteArray.readU16bit(info, pos + 3);
+ enumMemberValue(typeNameIndex, constNameIndex);
+ return pos + 5;
+ }
+ else if (tag == 'c')
+ {
+ int index = ByteArray.readU16bit(info, pos + 1);
+ classMemberValue(index);
+ return pos + 3;
+ }
+ else if (tag == '@')
+ return annotationMemberValue(pos + 1);
+ else if (tag == '[')
+ {
+ int num = ByteArray.readU16bit(info, pos + 1);
+ return arrayMemberValue(pos + 3, num);
+ }
+ else
+ { // primitive types or String.
+ int index = ByteArray.readU16bit(info, pos + 1);
+ constValueMember(tag, index);
+ return pos + 3;
+ }
+ }
+
+ void constValueMember(int tag, int index) throws Exception
+ {
+ }
+
+ void enumMemberValue(int typeNameIndex, int constNameIndex)
+ throws Exception
+ {
+ }
+
+ void classMemberValue(int index) throws Exception
+ {
+ }
+
+ int annotationMemberValue(int pos) throws Exception
+ {
+ return annotation(pos);
+ }
+
+ int arrayMemberValue(int pos, int num) throws Exception
+ {
+ for (int i = 0; i < num; ++i)
+ {
+ pos = memberValue(pos);
+ }
+
+ return pos;
+ }
+ }
+
+ static class Copier extends Walker
+ {
+ ByteArrayOutputStream output;
+ AnnotationsWriter writer;
+ ConstPool srcPool, destPool;
+ Map classnames;
+
+ /**
+ * Constructs a copier. This copier renames some class names
+ * into the new names specified by <code>map</code> when it copies
+ * an annotation attribute.
+ *
+ * @param info the source attribute.
+ * @param src the constant pool of the source class.
+ * @param dest the constant pool of the destination class.
+ * @param map pairs of replaced and substituted class names.
+ * It can be null.
+ */
+ Copier(byte[] info, ConstPool src, ConstPool dest, Map map)
+ {
+ super(info);
+ output = new ByteArrayOutputStream();
+ writer = new AnnotationsWriter(output, dest);
+ srcPool = src;
+ destPool = dest;
+ classnames = map;
+ }
+
+ byte[] close() throws IOException
+ {
+ writer.close();
+ return output.toByteArray();
+ }
+
+ void parameters(int numParam, int pos) throws Exception
+ {
+ writer.numParameters(numParam);
+ super.parameters(numParam, pos);
+ }
+
+ int annotationArray(int pos, int num) throws Exception
+ {
+ writer.numAnnotations(num);
+ return super.annotationArray(pos, num);
+ }
+
+ int annotation(int pos, int type, int numPairs) throws Exception
+ {
+ writer.annotation(copy(type), numPairs);
+ return super.annotation(pos, type, numPairs);
+ }
+
+ int memberValuePair(int pos, int nameIndex) throws Exception
+ {
+ writer.memberValuePair(copy(nameIndex));
+ return super.memberValuePair(pos, nameIndex);
+ }
+
+ void constValueMember(int tag, int index) throws Exception
+ {
+ writer.constValueIndex(tag, copy(index));
+ super.constValueMember(tag, index);
+ }
+
+ void enumMemberValue(int typeNameIndex, int constNameIndex)
+ throws Exception
+ {
+ writer.enumConstValue(copy(typeNameIndex), copy(constNameIndex));
+ super.enumMemberValue(typeNameIndex, constNameIndex);
+ }
+
+ void classMemberValue(int index) throws Exception
+ {
+ writer.classInfoIndex(copy(index));
+ super.classMemberValue(index);
+ }
+
+ int annotationMemberValue(int pos) throws Exception
+ {
+ writer.annotationValue();
+ return super.annotationMemberValue(pos);
+ }
+
+ int arrayMemberValue(int pos, int num) throws Exception
+ {
+ writer.arrayValue(num);
+ return super.arrayMemberValue(pos, num);
+ }
+
+ /**
+ * Copies a constant pool entry into the destination constant pool
+ * and returns the index of the copied entry.
+ *
+ * @param srcIndex the index of the copied entry into the source
+ * constant pool.
+ * @return the index of the copied item into the destination
+ * constant pool.
+ */
+ int copy(int srcIndex)
+ {
+ return srcPool.copy(srcIndex, destPool, classnames);
+ }
+ }
+
+ static class Parser extends Walker
+ {
+ ConstPool pool;
+ Annotation[][] allParams; // all parameters
+ Annotation[] allAnno; // all annotations
+ Annotation currentAnno; // current annotation
+ MemberValue memberValue;
+
+ /**
+ * Constructs a parser. This parser constructs a parse tree of
+ * the annotations.
+ *
+ * @param info the attribute.
+ * @param src the constant pool.
+ */
+ Parser(byte[] info, ConstPool cp)
+ {
+ super(info);
+ pool = cp;
+ }
+
+ Annotation[][] parseParameters() throws Exception
+ {
+ parameters();
+ return allParams;
+ }
+
+ Annotation[] parseAnnotations() throws Exception
+ {
+ annotationArray();
+ return allAnno;
+ }
+
+ void parameters(int numParam, int pos) throws Exception
+ {
+ Annotation[][] params = new Annotation[numParam][];
+ for (int i = 0; i < numParam; ++i)
+ {
+ pos = annotationArray(pos);
+ params[i] = allAnno;
+ }
+
+ allParams = params;
+ }
+
+ int annotationArray(int pos, int num) throws Exception
+ {
+ Annotation[] array = new Annotation[num];
+ for (int i = 0; i < num; ++i)
+ {
+ pos = annotation(pos);
+ array[i] = currentAnno;
+ }
+
+ allAnno = array;
+ return pos;
+ }
+
+ int annotation(int pos, int type, int numPairs) throws Exception
+ {
+ currentAnno = new Annotation(type, pool);
+ return super.annotation(pos, type, numPairs);
+ }
+
+ int memberValuePair(int pos, int nameIndex) throws Exception
+ {
+ pos = super.memberValuePair(pos, nameIndex);
+ currentAnno.addMemberValue(nameIndex, memberValue);
+ return pos;
+ }
+
+ void constValueMember(int tag, int index) throws Exception
+ {
+ MemberValue m;
+ ConstPool cp = pool;
+ switch (tag)
+ {
+ case 'B':
+ m = new ByteMemberValue(index, cp);
+ break;
+ case 'C':
+ m = new CharMemberValue(index, cp);
+ break;
+ case 'D':
+ m = new DoubleMemberValue(index, cp);
+ break;
+ case 'F':
+ m = new FloatMemberValue(index, cp);
+ break;
+ case 'I':
+ m = new IntegerMemberValue(index, cp);
+ break;
+ case 'J':
+ m = new LongMemberValue(index, cp);
+ break;
+ case 'S':
+ m = new ShortMemberValue(index, cp);
+ break;
+ case 'Z':
+ m = new BooleanMemberValue(index, cp);
+ break;
+ case 's':
+ m = new StringMemberValue(index, cp);
+ break;
+ default :
+ throw new RuntimeException("unknown tag:" + tag);
+ }
+
+ memberValue = m;
+ super.constValueMember(tag, index);
+ }
+
+ void enumMemberValue(int typeNameIndex, int constNameIndex)
+ throws Exception
+ {
+ memberValue = new EnumMemberValue(typeNameIndex,
+ constNameIndex, pool);
+ super.enumMemberValue(typeNameIndex, constNameIndex);
+ }
+
+ void classMemberValue(int index) throws Exception
+ {
+ memberValue = new ClassMemberValue(index, pool);
+ super.classMemberValue(index);
+ }
+
+ int annotationMemberValue(int pos) throws Exception
+ {
+ Annotation anno = currentAnno;
+ pos = super.annotationMemberValue(pos);
+ memberValue = new AnnotationMemberValue(currentAnno, pool);
+ currentAnno = anno;
+ return pos;
+ }
+
+ int arrayMemberValue(int pos, int num) throws Exception
+ {
+ ArrayMemberValue amv = new ArrayMemberValue(pool);
+ MemberValue[] elements = new MemberValue[num];
+ for (int i = 0; i < num; ++i)
+ {
+ pos = memberValue(pos);
+ elements[i] = memberValue;
+ }
+
+ amv.setValue(elements);
+ memberValue = amv;
+ return pos;
+ }
+ }
}
diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java
index 9e866578..b0744942 100644
--- a/src/main/javassist/bytecode/MethodInfo.java
+++ b/src/main/javassist/bytecode/MethodInfo.java
@@ -18,9 +18,9 @@ package javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.util.Map;
-import java.util.List;
import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
/**
* <code>method_info</code> structure.
@@ -28,364 +28,395 @@ import java.util.LinkedList;
* @see javassist.CtMethod#getMethodInfo()
* @see javassist.CtConstructor#getMethodInfo()
*/
-public final class MethodInfo {
- ConstPool constPool;
- int accessFlags;
- int name;
- int descriptor;
- LinkedList attribute; // may be null
-
- /**
- * The name of constructors: <code>&lt;init&gt</code>.
- */
- public static final String nameInit = "<init>";
-
- /**
- * The name of class initializer (static initializer):
- * <code>&lt;clinit&gt</code>.
- */
- public static final String nameClinit = "<clinit>";
-
- private MethodInfo(ConstPool cp) {
- constPool = cp;
- attribute = null;
- }
-
- /**
- * Constructs a <code>method_info</code> structure.
- * The initial value of <code>access_flags</code> is zero.
- *
- * @param cp a constant pool table
- * @param methodname method name
- * @param desc method descriptor
- *
- * @see Descriptor
- */
- public MethodInfo(ConstPool cp, String methodname, String desc) {
- this(cp);
- accessFlags = 0;
- name = cp.addUtf8Info(methodname);
- descriptor = constPool.addUtf8Info(desc);
- }
-
- MethodInfo(ConstPool cp, DataInputStream in) throws IOException {
- this(cp);
- read(in);
- }
-
- /**
- * Constructs a copy of <code>method_info</code> structure.
- * Class names appearing in the source <code>method_info</code>
- * are renamed according to <code>classnameMap</code>.
- *
- * <p>Note: only <code>Code</code> and <code>Exceptions</code>
- * attributes are copied from the source. The other attributes
- * are ignored.
- *
- * @param cp a constant pool table
- * @param methodname a method name
- * @param src a source <code>method_info</code>
- * @param classnameMap specifies pairs of replaced and substituted
- * name.
- * @see Descriptor
- */
- public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
- Map classnameMap) throws BadBytecode {
- this(cp);
- read(src, methodname, classnameMap);
- }
-
- void prune(ConstPool cp) {
- attribute = null;
- name = cp.addUtf8Info(getName());
- descriptor = cp.addUtf8Info(getDescriptor());
- constPool = cp;
- }
-
- /**
- * Returns a method name.
- */
- public String getName() {
- return constPool.getUtf8Info(name);
- }
-
- /**
- * Sets a method name.
- */
- public void setName(String newName) {
- name = constPool.addUtf8Info(newName);
- }
-
- /**
- * Returns true if this is not a constructor or a class initializer
- * (static initializer).
- */
- public boolean isMethod() {
- String n = getName();
- return !n.equals(nameInit) && !n.equals(nameClinit);
- }
-
- /**
- * Returns a constant pool table used by this method.
- */
- public ConstPool getConstPool() {
- return constPool;
- }
-
- /**
- * Returns true if this is a constructor.
- */
- public boolean isConstructor() {
- return getName().equals(nameInit);
- }
-
- /**
- * Returns true if this is a class initializer (static initializer).
- */
- public boolean isStaticInitializer() {
- return getName().equals(nameClinit);
- }
-
- /**
- * Returns access flags.
- *
- * @see AccessFlag
- */
- public int getAccessFlags() {
- return accessFlags;
- }
-
- /**
- * Sets access flags.
- *
- * @see AccessFlag
- */
- public void setAccessFlags(int acc) {
- accessFlags = acc;
- }
-
- /**
- * Returns a method descriptor.
- *
- * @see Descriptor
- */
- public String getDescriptor() {
- return constPool.getUtf8Info(descriptor);
- }
-
- /**
- * Sets a method descriptor.
- *
- * @see Descriptor
- */
- public void setDescriptor(String desc) {
- if (!desc.equals(getDescriptor()))
- descriptor = constPool.addUtf8Info(desc);
- }
-
- /**
- * Returns all the attributes.
- * A new element can be added to the returned list
- * and an existing element can be removed from the list.
- *
- * @return a list of <code>AttributeInfo</code> objects.
- * @see AttributeInfo
- */
- public List getAttributes() {
- if (attribute == null)
- attribute = new LinkedList();
-
- return attribute;
- }
-
- /**
- * Returns the attribute with the specified name.
- * If it is not found, this method returns null.
- *
- * @param name attribute name
- * @return an <code>AttributeInfo</code> object or null.
- */
- public AttributeInfo getAttribute(String name) {
- return AttributeInfo.lookup(attribute, name);
- }
-
- /**
- * Appends an attribute. If there is already an attribute with
- * the same name, the new one substitutes for it.
- */
- public void addAttribute(AttributeInfo info) {
- if (attribute == null)
- attribute = new LinkedList();
-
- AttributeInfo.remove(attribute, info.getName());
- attribute.add(info);
- }
-
- /**
- * Returns an Exceptions attribute.
- *
- * @return an Exceptions attribute
- * or null if it is not specified.
- */
- public ExceptionsAttribute getExceptionsAttribute() {
- AttributeInfo info
- = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag);
- return (ExceptionsAttribute)info;
- }
-
- /**
- * Returns a Code attribute.
- *
- * @return a Code attribute
- * or null if it is not specified.
- */
- public CodeAttribute getCodeAttribute() {
- AttributeInfo info
- = AttributeInfo.lookup(attribute, CodeAttribute.tag);
- return (CodeAttribute)info;
- }
-
- /**
- * Removes an Exception attribute.
- */
- public void removeExceptionsAttribute() {
- AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
- }
-
- /**
- * Adds an Exception attribute.
- *
- * <p>The added attribute must share the same constant pool table
- * as this <code>method_info</code> structure.
- */
- public void setExceptionsAttribute(ExceptionsAttribute cattr) {
- removeExceptionsAttribute();
- if (attribute == null)
- attribute = new LinkedList();
-
- attribute.add(cattr);
- }
-
- /**
- * Removes a Code attribute.
- */
- public void removeCodeAttribute() {
- AttributeInfo.remove(attribute, CodeAttribute.tag);
- }
-
- /**
- * Adds a Code attribute.
- *
- * <p>The added attribute must share the same constant pool table
- * as this <code>method_info</code> structure.
- */
- public void setCodeAttribute(CodeAttribute cattr) {
- removeCodeAttribute();
- if (attribute == null)
- attribute = new LinkedList();
-
- attribute.add(cattr);
- }
-
- /**
- * Returns the line number of the source line corresponding to the
- * specified bytecode contained in this method.
- *
- * @param pos the position of the bytecode (&gt;= 0).
- * an index into the code array.
- * @return -1 if this information is not available.
- */
- public int getLineNumber(int pos) {
- CodeAttribute ca = getCodeAttribute();
- if (ca == null)
- return -1;
-
- LineNumberAttribute ainfo =
- (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
- if (ainfo == null)
- return -1;
-
- return ainfo.toLineNumber(pos);
- }
-
- /**
- * Changes a super constructor called by this constructor.
- *
- * <p>This method modifies a call to <code>super()</code>,
- * which should be at the
- * head of a constructor body, so that a constructor in a different
- * super class is called. This method does not change actural
- * parameters. Hence the new super class must have a constructor
- * with the same signature as the original one.
- *
- * <p>This method should be called when the super class
- * of the class declaring this method is changed.
- *
- * <p>This method does not perform anything unless this
- * <code>MethodInfo</code> represents a constructor.
- *
- * @param superclass the new super class
- */
- public void setSuperclass(String superclass) throws BadBytecode {
- if (!isConstructor())
- return;
-
- CodeAttribute ca = getCodeAttribute();
- byte[] code = ca.getCode();
- CodeIterator iterator = ca.iterator();
- int pos = iterator.skipSuperConstructor();
- if (pos >= 0) { // not this()
- ConstPool cp = constPool;
- int mref = ByteArray.readU16bit(code, pos + 1);
- int nt = cp.getMethodrefNameAndType(mref);
- int sc = cp.addClassInfo(superclass);
- int mref2 = cp.addMethodrefInfo(sc, nt);
- ByteArray.write16bit(mref2, code, pos + 1);
- }
- }
-
- private void read(MethodInfo src, String methodname, Map classnames)
- throws BadBytecode
- {
- ConstPool destCp = constPool;
- accessFlags = src.accessFlags;
- name = destCp.addUtf8Info(methodname);
-
- ConstPool srcCp = src.constPool;
- String desc = srcCp.getUtf8Info(src.descriptor);
- String desc2 = Descriptor.rename(desc, classnames);
- descriptor = destCp.addUtf8Info(desc2);
-
- attribute = new LinkedList();
- ExceptionsAttribute eattr = src.getExceptionsAttribute();
- if (eattr != null)
- attribute.add(eattr.copy(destCp, classnames));
-
- CodeAttribute cattr = src.getCodeAttribute();
- if (cattr != null)
- attribute.add(cattr.copy(destCp, classnames));
- }
-
- private void read(DataInputStream in) throws IOException {
- accessFlags = in.readUnsignedShort();
- name = in.readUnsignedShort();
- descriptor = in.readUnsignedShort();
- int n = in.readUnsignedShort();
- attribute = new LinkedList();
- for (int i = 0; i < n; ++i)
- attribute.add(AttributeInfo.read(constPool, in));
- }
-
- void write(DataOutputStream out) throws IOException {
- out.writeShort(accessFlags);
- out.writeShort(name);
- out.writeShort(descriptor);
-
- if (attribute == null)
- out.writeShort(0);
- else {
- out.writeShort(attribute.size());
- AttributeInfo.writeAll(attribute, out);
- }
- }
+public final class MethodInfo
+{
+ ConstPool constPool;
+ int accessFlags;
+ int name;
+ int descriptor;
+ LinkedList attribute; // may be null
+
+ /**
+ * The name of constructors: <code>&lt;init&gt</code>.
+ */
+ public static final String nameInit = "<init>";
+
+ /**
+ * The name of class initializer (static initializer):
+ * <code>&lt;clinit&gt</code>.
+ */
+ public static final String nameClinit = "<clinit>";
+
+ private MethodInfo(ConstPool cp)
+ {
+ constPool = cp;
+ attribute = null;
+ }
+
+ /**
+ * Constructs a <code>method_info</code> structure.
+ * The initial value of <code>access_flags</code> is zero.
+ *
+ * @param cp a constant pool table
+ * @param methodname method name
+ * @param desc method descriptor
+ * @see Descriptor
+ */
+ public MethodInfo(ConstPool cp, String methodname, String desc)
+ {
+ this(cp);
+ accessFlags = 0;
+ name = cp.addUtf8Info(methodname);
+ descriptor = constPool.addUtf8Info(desc);
+ }
+
+ MethodInfo(ConstPool cp, DataInputStream in) throws IOException
+ {
+ this(cp);
+ read(in);
+ }
+
+ /**
+ * Constructs a copy of <code>method_info</code> structure.
+ * Class names appearing in the source <code>method_info</code>
+ * are renamed according to <code>classnameMap</code>.
+ * <p/>
+ * <p>Note: only <code>Code</code> and <code>Exceptions</code>
+ * attributes are copied from the source. The other attributes
+ * are ignored.
+ *
+ * @param cp a constant pool table
+ * @param methodname a method name
+ * @param src a source <code>method_info</code>
+ * @param classnameMap specifies pairs of replaced and substituted
+ * name.
+ * @see Descriptor
+ */
+ public MethodInfo(ConstPool cp, String methodname, MethodInfo src,
+ Map classnameMap) throws BadBytecode
+ {
+ this(cp);
+ read(src, methodname, classnameMap);
+ }
+
+ void prune(ConstPool cp)
+ {
+ new Exception("****** pruned *****").printStackTrace();
+ attribute = null;
+ name = cp.addUtf8Info(getName());
+ descriptor = cp.addUtf8Info(getDescriptor());
+ constPool = cp;
+ }
+
+ /**
+ * Returns a method name.
+ */
+ public String getName()
+ {
+ return constPool.getUtf8Info(name);
+ }
+
+ /**
+ * Sets a method name.
+ */
+ public void setName(String newName)
+ {
+ name = constPool.addUtf8Info(newName);
+ }
+
+ /**
+ * Returns true if this is not a constructor or a class initializer
+ * (static initializer).
+ */
+ public boolean isMethod()
+ {
+ String n = getName();
+ return !n.equals(nameInit) && !n.equals(nameClinit);
+ }
+
+ /**
+ * Returns a constant pool table used by this method.
+ */
+ public ConstPool getConstPool()
+ {
+ return constPool;
+ }
+
+ /**
+ * Returns true if this is a constructor.
+ */
+ public boolean isConstructor()
+ {
+ return getName().equals(nameInit);
+ }
+
+ /**
+ * Returns true if this is a class initializer (static initializer).
+ */
+ public boolean isStaticInitializer()
+ {
+ return getName().equals(nameClinit);
+ }
+
+ /**
+ * Returns access flags.
+ *
+ * @see AccessFlag
+ */
+ public int getAccessFlags()
+ {
+ return accessFlags;
+ }
+
+ /**
+ * Sets access flags.
+ *
+ * @see AccessFlag
+ */
+ public void setAccessFlags(int acc)
+ {
+ accessFlags = acc;
+ }
+
+ /**
+ * Returns a method descriptor.
+ *
+ * @see Descriptor
+ */
+ public String getDescriptor()
+ {
+ return constPool.getUtf8Info(descriptor);
+ }
+
+ /**
+ * Sets a method descriptor.
+ *
+ * @see Descriptor
+ */
+ public void setDescriptor(String desc)
+ {
+ if (!desc.equals(getDescriptor()))
+ descriptor = constPool.addUtf8Info(desc);
+ }
+
+ /**
+ * Returns all the attributes.
+ * A new element can be added to the returned list
+ * and an existing element can be removed from the list.
+ *
+ * @return a list of <code>AttributeInfo</code> objects.
+ * @see AttributeInfo
+ */
+ public List getAttributes()
+ {
+ if (attribute == null)
+ attribute = new LinkedList();
+
+ return attribute;
+ }
+
+ /**
+ * Returns the attribute with the specified name.
+ * If it is not found, this method returns null.
+ *
+ * @param name attribute name
+ * @return an <code>AttributeInfo</code> object or null.
+ */
+ public AttributeInfo getAttribute(String name)
+ {
+ return AttributeInfo.lookup(attribute, name);
+ }
+
+ /**
+ * Appends an attribute. If there is already an attribute with
+ * the same name, the new one substitutes for it.
+ */
+ public void addAttribute(AttributeInfo info)
+ {
+ if (attribute == null)
+ attribute = new LinkedList();
+
+ AttributeInfo.remove(attribute, info.getName());
+ attribute.add(info);
+ }
+
+ /**
+ * Returns an Exceptions attribute.
+ *
+ * @return an Exceptions attribute
+ * or null if it is not specified.
+ */
+ public ExceptionsAttribute getExceptionsAttribute()
+ {
+ AttributeInfo info
+ = AttributeInfo.lookup(attribute, ExceptionsAttribute.tag);
+ return (ExceptionsAttribute) info;
+ }
+
+ /**
+ * Returns a Code attribute.
+ *
+ * @return a Code attribute
+ * or null if it is not specified.
+ */
+ public CodeAttribute getCodeAttribute()
+ {
+ AttributeInfo info
+ = AttributeInfo.lookup(attribute, CodeAttribute.tag);
+ return (CodeAttribute) info;
+ }
+
+ /**
+ * Removes an Exception attribute.
+ */
+ public void removeExceptionsAttribute()
+ {
+ AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
+ }
+
+ /**
+ * Adds an Exception attribute.
+ * <p/>
+ * <p>The added attribute must share the same constant pool table
+ * as this <code>method_info</code> structure.
+ */
+ public void setExceptionsAttribute(ExceptionsAttribute cattr)
+ {
+ removeExceptionsAttribute();
+ if (attribute == null)
+ attribute = new LinkedList();
+
+ attribute.add(cattr);
+ }
+
+ /**
+ * Removes a Code attribute.
+ */
+ public void removeCodeAttribute()
+ {
+ AttributeInfo.remove(attribute, CodeAttribute.tag);
+ }
+
+ /**
+ * Adds a Code attribute.
+ * <p/>
+ * <p>The added attribute must share the same constant pool table
+ * as this <code>method_info</code> structure.
+ */
+ public void setCodeAttribute(CodeAttribute cattr)
+ {
+ removeCodeAttribute();
+ if (attribute == null)
+ attribute = new LinkedList();
+
+ attribute.add(cattr);
+ }
+
+ /**
+ * Returns the line number of the source line corresponding to the
+ * specified bytecode contained in this method.
+ *
+ * @param pos the position of the bytecode (&gt;= 0).
+ * an index into the code array.
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber(int pos)
+ {
+ CodeAttribute ca = getCodeAttribute();
+ if (ca == null)
+ return -1;
+
+ LineNumberAttribute ainfo =
+ (LineNumberAttribute) ca.getAttribute(LineNumberAttribute.tag);
+ if (ainfo == null)
+ return -1;
+
+ return ainfo.toLineNumber(pos);
+ }
+
+ /**
+ * Changes a super constructor called by this constructor.
+ * <p/>
+ * <p>This method modifies a call to <code>super()</code>,
+ * which should be at the
+ * head of a constructor body, so that a constructor in a different
+ * super class is called. This method does not change actural
+ * parameters. Hence the new super class must have a constructor
+ * with the same signature as the original one.
+ * <p/>
+ * <p>This method should be called when the super class
+ * of the class declaring this method is changed.
+ * <p/>
+ * <p>This method does not perform anything unless this
+ * <code>MethodInfo</code> represents a constructor.
+ *
+ * @param superclass the new super class
+ */
+ public void setSuperclass(String superclass) throws BadBytecode
+ {
+ if (!isConstructor())
+ return;
+
+ CodeAttribute ca = getCodeAttribute();
+ byte[] code = ca.getCode();
+ CodeIterator iterator = ca.iterator();
+ int pos = iterator.skipSuperConstructor();
+ if (pos >= 0)
+ { // not this()
+ ConstPool cp = constPool;
+ int mref = ByteArray.readU16bit(code, pos + 1);
+ int nt = cp.getMethodrefNameAndType(mref);
+ int sc = cp.addClassInfo(superclass);
+ int mref2 = cp.addMethodrefInfo(sc, nt);
+ ByteArray.write16bit(mref2, code, pos + 1);
+ }
+ }
+
+ private void read(MethodInfo src, String methodname, Map classnames)
+ throws BadBytecode
+ {
+ ConstPool destCp = constPool;
+ accessFlags = src.accessFlags;
+ name = destCp.addUtf8Info(methodname);
+
+ ConstPool srcCp = src.constPool;
+ String desc = srcCp.getUtf8Info(src.descriptor);
+ String desc2 = Descriptor.rename(desc, classnames);
+ descriptor = destCp.addUtf8Info(desc2);
+
+ attribute = new LinkedList();
+ ExceptionsAttribute eattr = src.getExceptionsAttribute();
+ if (eattr != null)
+ attribute.add(eattr.copy(destCp, classnames));
+
+ CodeAttribute cattr = src.getCodeAttribute();
+ if (cattr != null)
+ attribute.add(cattr.copy(destCp, classnames));
+ }
+
+ private void read(DataInputStream in) throws IOException
+ {
+ accessFlags = in.readUnsignedShort();
+ name = in.readUnsignedShort();
+ descriptor = in.readUnsignedShort();
+ int n = in.readUnsignedShort();
+ attribute = new LinkedList();
+ for (int i = 0; i < n; ++i)
+ attribute.add(AttributeInfo.read(constPool, in));
+ }
+
+ void write(DataOutputStream out) throws IOException
+ {
+ out.writeShort(accessFlags);
+ out.writeShort(name);
+ out.writeShort(descriptor);
+
+ if (attribute == null)
+ out.writeShort(0);
+ else
+ {
+ out.writeShort(attribute.size());
+ AttributeInfo.writeAll(attribute, out);
+ }
+ }
}
diff --git a/src/main/javassist/bytecode/annotation/ClassMemberValue.java b/src/main/javassist/bytecode/annotation/ClassMemberValue.java
index 78a6217d..09a1075b 100644
--- a/src/main/javassist/bytecode/annotation/ClassMemberValue.java
+++ b/src/main/javassist/bytecode/annotation/ClassMemberValue.java
@@ -17,6 +17,7 @@ package javassist.bytecode.annotation;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
+
import java.io.IOException;
/**
@@ -25,72 +26,83 @@ import java.io.IOException;
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
-public class ClassMemberValue extends MemberValue {
- int valueIndex;
+public class ClassMemberValue extends MemberValue
+{
+ int valueIndex;
- /**
- * Constructs a string constant value. The initial value is specified
- * by the constant pool entry at the given index.
- *
- * @param index the index of a CONSTANT_Utf8_info structure.
- */
- public ClassMemberValue(int index, ConstPool cp) {
- super('c', cp);
- this.valueIndex = index;
- }
+ /**
+ * Constructs a string constant value. The initial value is specified
+ * by the constant pool entry at the given index.
+ *
+ * @param index the index of a CONSTANT_Utf8_info structure.
+ */
+ public ClassMemberValue(int index, ConstPool cp)
+ {
+ super('c', cp);
+ this.valueIndex = index;
+ }
- /**
- * Constructs a string constant value.
- *
- * @param className the initial value.
- */
- public ClassMemberValue(String className, ConstPool cp) {
- super('c', cp);
- setValue(className);
- }
+ /**
+ * Constructs a string constant value.
+ *
+ * @param className the initial value.
+ */
+ public ClassMemberValue(String className, ConstPool cp)
+ {
+ super('c', cp);
+ setValue(className);
+ }
- /**
- * Constructs a string constant value.
- * The initial value is java.lang.Class.
- */
- public ClassMemberValue(ConstPool cp) {
- super('c', cp);
- setValue("java.lang.Class");
- }
+ /**
+ * Constructs a string constant value.
+ * The initial value is java.lang.Class.
+ */
+ public ClassMemberValue(ConstPool cp)
+ {
+ super('c', cp);
+ setValue("java.lang.Class");
+ }
- /**
- * Obtains the value of the member.
- *
- * @return fully-qualified class name.
- */
- public String getValue() {
- return Descriptor.toClassName(cp.getUtf8Info(valueIndex));
- }
+ /**
+ * Obtains the value of the member.
+ *
+ * @return fully-qualified class name.
+ */
+ public String getValue()
+ {
+ String v = cp.getUtf8Info(valueIndex);
+ return Descriptor.toClassName(v);
+ }
- /**
- * Sets the value of the member.
- *
- * @param newClassName fully-qualified class name.
- */
- public void setValue(String newClassName) {
- valueIndex = cp.addUtf8Info(Descriptor.of(newClassName));
- }
+ /**
+ * Sets the value of the member.
+ *
+ * @param newClassName fully-qualified class name.
+ */
+ public void setValue(String newClassName)
+ {
+ String setTo = Descriptor.of(newClassName);
+ valueIndex = cp.addUtf8Info(setTo);
+ }
- /**
- * Obtains the string representation of this object.
- */
- public String toString() {
- return "<" + getValue() + " class>";
- }
+ /**
+ * Obtains the string representation of this object.
+ */
+ public String toString()
+ {
+ return "<" + getValue() + " class>";
+ }
- void write(AnnotationsWriter writer) throws IOException {
- writer.constValueIndex(getValue());
- }
+ void write(AnnotationsWriter writer) throws IOException
+ {
+ writer.classInfoIndex(valueIndex);
+ }
- /**
- * Accepts a visitor.
- */
- public void accept(MemberValueVisitor visitor) {
- visitor.visitClassMemberValue(this);
- }
+ /**
+ * Accepts a visitor.
+ */
+ public void accept(MemberValueVisitor visitor)
+ {
+ visitor.visitClassMemberValue(this);
+ }
}