diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-06-10 15:56:45 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2004-06-10 15:56:45 +0000 |
commit | 6f0d550f399ed4d5bee1d42caccb51b4f460e401 (patch) | |
tree | 3d0b9e645be2627252509dc4d9f8395c0e8045b8 /src/main/javassist/bytecode | |
parent | 134ee70a9fd4959cbf6b9b6f3b9d1498247ec1e5 (diff) | |
download | javassist-6f0d550f399ed4d5bee1d42caccb51b4f460e401.tar.gz javassist-6f0d550f399ed4d5bee1d42caccb51b4f460e401.zip |
Added javassist.bytecode.AnnotationsAttribute and support classes.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@110 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist/bytecode')
11 files changed, 1124 insertions, 23 deletions
diff --git a/src/main/javassist/bytecode/AnnotationsAttribute.java b/src/main/javassist/bytecode/AnnotationsAttribute.java new file mode 100644 index 00000000..ba593bb6 --- /dev/null +++ b/src/main/javassist/bytecode/AnnotationsAttribute.java @@ -0,0 +1,465 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.bytecode; + +import java.util.Map; +import java.io.IOException; +import java.io.DataInputStream; +import java.io.ByteArrayOutputStream; + +import javassist.bytecode.annotation.*; + +/** + * A class representing + * <code>RuntimeVisibleAnnotations_attribute</code> and + * <code>RuntimeInvisibleAnnotations_attribute</code>. + */ +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>. + * + * @param cp constant pool + * @param attrname attribute name (<code>visibleTag</code> or + * <code>invisibleTag</code>). + */ + 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. + * This method works even if this object is an instance of + * <code>ParameterAnnotationsAttribute</code>. + */ + public AttributeInfo copy(ConstPool newCp, Map classnames) { + return new Copier(newCp, classnames).copy(this); + } + + AnnotationsAttribute makeCopy(ConstPool newCp, byte[] info) { + return new AnnotationsAttribute(newCp, getName(), info); + } + + /** + * Runs the parser to analyze this annotation. + * It invokes methods on the given visitor object while parsing. + * + * @see AnnotationsWriter + */ + public void accept(AnnotationsVisitor visitor) throws Exception { + int num = numAnnotations(); + int pos = 2; + visitor.beginAnnotationsArray(num); + for (int i = 0; i < num; ++i) + pos = readAnnotation(visitor, pos); + + visitor.endAnnotationsArray(); + } + + int readAnnotation(AnnotationsVisitor visitor, int pos) throws Exception { + int type = ByteArray.readU16bit(info, pos); + int numPairs = ByteArray.readU16bit(info, pos + 2); + visitor.beginAnnotation(constPool, type, numPairs); + pos += 4; + for (int j = 0; j < numPairs; ++j) + pos = readMemberValuePair(visitor, pos); + + visitor.endAnnotation(); + return pos; + } + + private int readMemberValuePair(AnnotationsVisitor visitor, int pos) + throws Exception + { + int nameIndex = ByteArray.readU16bit(info, pos); + visitor.beginMemberValuePair(constPool, nameIndex); + pos = readMemberValue(visitor, pos + 2); + visitor.endMemberValuePair(); + return pos; + } + + private int readMemberValue(AnnotationsVisitor visitor, 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); + visitor.enumConstValue(constPool, typeNameIndex, constNameIndex); + return pos + 5; + } + else if (tag == 'c') { + int index = ByteArray.readU16bit(info, pos + 1); + visitor.classInfoIndex(constPool, index); + return pos + 3; + } + else if (tag == '@') { + visitor.beginAnnotationValue(); + pos = readAnnotation(visitor, pos + 1); + visitor.endAnnotationValue(); + return pos; + } + else if (tag == '[') { + int num = ByteArray.readU16bit(info, pos + 1); + pos += 3; + visitor.beginArrayValue(num); + for (int i = 0; i < num; ++i) { + pos = readMemberValue(visitor, pos); + visitor.arrayElement(i); + } + + visitor.endArrayValue(); + return pos; + } + else { // primitive types or String. + int index = ByteArray.readU16bit(info, pos + 1); + visitor.constValueIndex(constPool, tag, index); + return pos + 3; + } + } + + /** + * A visitor for copying the contents of an + * <code>AnnotationsAttribute</code>. + * + * <p>This class is typically used as following: + * <ul><pre> + * new Copier(dest, map).copy(src) + * </pre></ul> + * + * <p>This expression returns a copy of the source annotations attribute. + * + * @see AnnotationsAttribute#accept(AnnotationsVisitor) + * @see AnnotationsWriter + */ + public static class Copier extends AnnotationsVisitor { + protected ByteArrayOutputStream output; + protected AnnotationsWriter writer; + protected ConstPool destPool; + protected Map classnames; + + /** + * 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. + */ + protected int copy(ConstPool srcPool, int srcIndex) { + return srcPool.copy(srcIndex, destPool, 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 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. + */ + public Copier(ConstPool dest, Map map) { + output = new ByteArrayOutputStream(); + writer = new AnnotationsWriter(output, dest); + destPool = dest; + classnames = map; + } + + /** + * Does copying. This calls <code>accept()</code> + * on <code>src</code> with this visitor object. + * + * @param src the source attribute. It can be an instance + * of <code>ParameterAnnotationsAttribute</code>. + * @return a copy of the source attribute. + */ + public AnnotationsAttribute copy(AnnotationsAttribute src) { + try { + src.accept(this); + writer.close(); + } + catch (Exception e) { + throw new RuntimeException(e.toString()); + } + + return src.makeCopy(destPool, output.toByteArray()); + } + + /** + * Writes <code>num_parameters</code>. + */ + public void beginParameters(int num) throws IOException { + writer.numParameters(num); + } + + /** + * Does nothing. + */ + public void endParameters() {} + + /** + * Writes <code>num_annotations</code>. + */ + public void beginAnnotationsArray(int num) throws IOException { + writer.numAnnotations(num); + } + + /** + * Does nothing. + */ + public void endAnnotationsArray() {} + + /** + * Writes <code>type_index</code> and + * <code>num_member_value_pairs</code>. + */ + public void beginAnnotation(ConstPool cp, + int typeIndex, int numMemberValuePairs) + throws IOException + { + writer.annotation(copy(cp, typeIndex), numMemberValuePairs); + } + + /** + * Does nothing. + */ + public void endAnnotation() {} + + /** + * Writes <code>member_name_index</code>. + */ + public void beginMemberValuePair(ConstPool cp, int memberNameIndex) + throws IOException + { + writer.memberValuePair(copy(cp, memberNameIndex)); + } + + /** + * Does nothing. + */ + public void endMemberValuePair() {} + + /** + * Writes <code>tag</code> and <code>const_value_index</code>. + */ + public void constValueIndex(ConstPool cp, int tag, int index) + throws IOException + { + writer.constValueIndex(tag, copy(cp, index)); + } + + /** + * Writes <code>tag</code> and <code>enum_const_value</code>. + */ + public void enumConstValue(ConstPool cp, int typeNameIndex, + int constNameIndex) + throws IOException + { + writer.enumConstValue(copy(cp, typeNameIndex), + copy(cp, constNameIndex)); + } + + /** + * Writes <code>tag</code> and <code>class_info_index</code>. + */ + public void classInfoIndex(ConstPool cp, int index) throws IOException { + writer.classInfoIndex(copy(cp, index)); + } + + /** + * Writes <code>tag</code>. + */ + public void beginAnnotationValue() throws IOException { + writer.annotationValue(); + } + + /** + * Does nothing. + */ + public void endAnnotationValue() {} + + /** + * Writes <code>num_values</code> in <code>array_value</code>. + */ + public void beginArrayValue(int numValues) throws IOException { + writer.arrayValue(numValues); + } + + /** + * Does nothing. + */ + public void arrayElement(int i) {} + + /** + * Invoked when the parser ends parsing <code>array_value</code> + * in <code>member_value</code>. + */ + public void endArrayValue() {} + } + + /** + * Returns a string representation of this object. + */ + public String toString() { + return getName() + ":" + new Printer().toString(this); + } + + static class Printer extends AnnotationsVisitor { + private StringBuffer sbuf; + + public Printer() { + sbuf = new StringBuffer(); + } + + public String toString(AnnotationsAttribute src) { + try { + src.accept(this); + return sbuf.toString(); + } + catch (RuntimeException e) { + throw e; + } + catch (Exception e) { + throw new RuntimeException(e.toString()); + } + } + + public void beginParameters(int num) { + sbuf.append("parameters[").append(num).append("]{"); + } + + public void endParameters() { + sbuf.append('}'); + } + + public void beginAnnotationsArray(int num) { + sbuf.append("annotations[").append(num).append("]{"); + } + + public void endAnnotationsArray() { + sbuf.append('}'); + } + + public void beginAnnotation(ConstPool cp, + int typeIndex, int numMemberValuePairs) { + String name = Descriptor.toClassName(cp.getUtf8Info(typeIndex)); + sbuf.append('@').append(name).append('{'); + } + + public void endAnnotation() { + sbuf.append('}'); + } + + public void beginMemberValuePair(ConstPool cp, int memberNameIndex) { + sbuf.append(cp.getUtf8Info(memberNameIndex)).append('='); + } + + public void endMemberValuePair() { + sbuf.append(", "); + } + + public void constValueIndex(ConstPool cp, int tag, int index) { + if (tag == 'Z' || tag == 'B' || tag == 'C' || tag == 'S' + || tag == 'I') + sbuf.append(cp.getIntegerInfo(index)); + else if (tag == 'J') + sbuf.append(cp.getLongInfo(index)); + else if (tag == 'F') + sbuf.append(cp.getFloatInfo(index)); + else if (tag == 'D') + sbuf.append(cp.getDoubleInfo(index)); + else if (tag == 's') + sbuf.append('"').append(cp.getUtf8Info(index)).append('"'); + else + throw new RuntimeException("unknown tag:" + tag ); + } + + public void enumConstValue(ConstPool cp, int typeNameIndex, + int constNameIndex) { + String name + = Descriptor.toClassName(cp.getUtf8Info(typeNameIndex)); + sbuf.append(name) + .append('.').append(cp.getUtf8Info(constNameIndex)); + } + + public void classInfoIndex(ConstPool cp, int index) + throws IOException + { + sbuf.append(Descriptor.toClassName(cp.getUtf8Info(index))) + .append(" class"); + } + + public void beginAnnotationValue() {} + + public void endAnnotationValue() {} + + public void beginArrayValue(int numValues) { + sbuf.append("array[").append(numValues).append("]{"); + } + + public void arrayElement(int i) { + sbuf.append(", "); + } + + public void endArrayValue() { + sbuf.append('}'); + } + } + +} diff --git a/src/main/javassist/bytecode/AttributeInfo.java b/src/main/javassist/bytecode/AttributeInfo.java index 82fa7087..b3f02873 100644 --- a/src/main/javassist/bytecode/AttributeInfo.java +++ b/src/main/javassist/bytecode/AttributeInfo.java @@ -89,6 +89,12 @@ public class AttributeInfo { return new DeprecatedAttribute(cp, name, in); else if (nameStr.equals(InnerClassesAttribute.tag)) return new InnerClassesAttribute(cp, name, in); + else if (nameStr.equals(AnnotationsAttribute.visibleTag) + || nameStr.equals(AnnotationsAttribute.invisibleTag)) + return new AnnotationsAttribute(cp, name, in); + else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag) + || nameStr.equals(ParameterAnnotationsAttribute.invisibleTag)) + return new ParameterAnnotationsAttribute(cp, name, in); else return new AttributeInfo(cp, name, in); } diff --git a/src/main/javassist/bytecode/ConstPool.java b/src/main/javassist/bytecode/ConstPool.java index d517b531..6a024dbf 100644 --- a/src/main/javassist/bytecode/ConstPool.java +++ b/src/main/javassist/bytecode/ConstPool.java @@ -578,6 +578,7 @@ public final class ConstPool { * @param n the <i>n</i>-th item * @param dest destination constant pool table * @param classnames the map or null. + * @return the index of the copied item into the destination ClassPool. */ public int copy(int n, ConstPool dest, Map classnames) { if (n == 0) diff --git a/src/main/javassist/bytecode/Descriptor.java b/src/main/javassist/bytecode/Descriptor.java index 9590d632..9c5b69c7 100644 --- a/src/main/javassist/bytecode/Descriptor.java +++ b/src/main/javassist/bytecode/Descriptor.java @@ -47,29 +47,29 @@ public class Descriptor { } /** - * Converts to a classname from a descriptor + * Returns the internal representation of the class name in the + * JVM. */ - public static String fromDescriptor(String descriptor) { - String newname = toJavaName(descriptor).substring(1); - return newname.substring(0, newname.length() - 1); + public static String toJvmName(CtClass clazz) { + if (clazz.isArray()) + return of(clazz); + else + return toJvmName(clazz.getName()); } /** - * Converts to a descriptor from a classname + * Converts to a Java class name from a descriptor */ - public static String toDescriptor(String classname) { - return "L" + toJvmName(classname) + ";"; + public static String toClassName(String descriptor) { + String newname = toJavaName(descriptor); + return newname.substring(1, newname.length() - 1); } /** - * Returns the internal representation of the class name in the - * JVM. + * Converts to a descriptor from a Java class name */ - public static String toJvmName(CtClass clazz) { - if (clazz.isArray()) - return of(clazz); - else - return toJvmName(clazz.getName()); + public static String of(String classname) { + return "L" + toJvmName(classname) + ";"; } /** diff --git a/src/main/javassist/bytecode/ParameterAnnotationsAttribute.java b/src/main/javassist/bytecode/ParameterAnnotationsAttribute.java new file mode 100644 index 00000000..932be9ee --- /dev/null +++ b/src/main/javassist/bytecode/ParameterAnnotationsAttribute.java @@ -0,0 +1,110 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.bytecode; + +import java.io.IOException; +import java.io.DataInputStream; + +import javassist.bytecode.annotation.*; + +/** + * A class representing <code>RuntimeVisibleAnnotations_attribute</code> and + * <code>RuntimeInvisibleAnnotations_attribute</code>. + */ +public class ParameterAnnotationsAttribute extends AnnotationsAttribute { + /** + * The name of the <code>RuntimeVisibleParameterAnnotations</code> + * attribute. + */ + public static final String visibleTag + = "RuntimeVisibleParameterAnnotations"; + + /** + * The name of the <code>RuntimeInvisibleParameterAnnotations</code> + * attribute. + */ + public static final String invisibleTag + = "RuntimeInvisibleParameterAnnotations";
+ /** + * Constructs + * a <code>Runtime(In)VisisbleParameterAnnotations_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 ParameterAnnotationsAttribute(ConstPool cp, String attrname, + byte[] info) { + super(cp, attrname, info); + } + + /** + * Constructs an empty + * <code>Runtime(In)VisisbleParameterAnnotations_attribute</code>. + * + * @param cp constant pool + * @param attrname attribute name (<code>visibleTag</code> or + * <code>invisibleTag</code>). + */ + public ParameterAnnotationsAttribute(ConstPool cp, String attrname) { + this(cp, attrname, new byte[] { 0 }); + } + + /** + * @param n the attribute name. + */ + ParameterAnnotationsAttribute(ConstPool cp, int n, DataInputStream in) + throws IOException + { + super(cp, n, in); + } + + /** + * Returns <code>num_parameters</code>. + */ + public int numParameters() { + return info[0] & 0xff; + } + + AnnotationsAttribute makeCopy(ConstPool newCp, byte[] info) { + return new ParameterAnnotationsAttribute(newCp, getName(), info); + } + + /** + * Runs the parser to analyze this annotation. + * + * @see AnnotationsWriter + */ + public void accept(AnnotationsVisitor visitor) throws Exception { + int numParam = numParameters(); + int pos = 1; + visitor.beginParameters(numParam); + for (int i = 0; i < numParam; ++i) { + int num= ByteArray.readU16bit(info, pos); + visitor.beginAnnotationsArray(num); + for (int j = 0; j < num; ++j) { + pos = readAnnotation(visitor, pos); + } + + visitor.endAnnotationsArray(); + } + + visitor.endParameters(); + } +} diff --git a/src/main/javassist/bytecode/annotation/AnnotationInfo.java b/src/main/javassist/bytecode/annotation/AnnotationInfo.java index aac523d9..bdb53352 100644 --- a/src/main/javassist/bytecode/annotation/AnnotationInfo.java +++ b/src/main/javassist/bytecode/annotation/AnnotationInfo.java @@ -33,7 +33,7 @@ import java.util.Iterator; * Comment * * @author <a href="mailto:bill@jboss.org">Bill Burke</a> - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * **/ public class AnnotationInfo @@ -120,7 +120,7 @@ public class AnnotationInfo if (!clazz.isInterface()) throw new RuntimeException("Only interfaces are allowed for AnnotationInfo creation."); this.cp = cp; // beta1 type_index = (short) cp.addClassInfo(clazz); - type_index = (short)cp.addUtf8Info(Descriptor.toDescriptor(clazz.getName())); + type_index = (short)cp.addUtf8Info(Descriptor.of(clazz.getName())); CtMethod methods[] = clazz.getDeclaredMethods(); if (methods.length > 0) { @@ -144,7 +144,7 @@ public class AnnotationInfo public String getAnnotationType() { - String name = Descriptor.fromDescriptor(cp.getUtf8Info(type_index)); + String name = Descriptor.toClassName(cp.getUtf8Info(type_index)); return name; } diff --git a/src/main/javassist/bytecode/annotation/AnnotationsVisitor.java b/src/main/javassist/bytecode/annotation/AnnotationsVisitor.java new file mode 100644 index 00000000..18c7c74f --- /dev/null +++ b/src/main/javassist/bytecode/annotation/AnnotationsVisitor.java @@ -0,0 +1,163 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.bytecode.annotation; + +import javassist.bytecode.ConstPool; + +/** + * Visitor for parsing an annotations attribute. + * + * @see AnnotationsAttribute#accept(AnnotationsVisitor) + * @see ParameterAnnotationsAttribute#accept(AnnotationsVisitor) + */ +public class AnnotationsVisitor { + /** + * Invoked when the parser starts parsing a + * <code>parameter_annotations</code> array. + * If the annotations attribute is not a parameter annotations attribute, + * this method is never invoked. + * + * @param numParameters <code>num_parameters</code>. + */ + public void beginParameters(int numParameters) throws Exception {} + + /** + * Invoked when the parser ends parsing a + * <code>parameter_annotations</code> array. + * If the annotations attribute is not a parameter annotations attribute, + * this method is never invoked. + */ + public void endParameters() throws Exception {} + + /** + * Invoked when the parser starts parsing an + * <code>annotations</code> array in + * <code>..Annotations_attribute</code>. + * + * @param numAnnotations <code>num_annotations</code>. + */ + public void beginAnnotationsArray(int numAnnotations) + throws Exception {} + + /** + * Invoked when the parser ends parsing an + * <code>annotations</code> array in + * <code>..Annotations_attribute</code>. + */ + public void endAnnotationsArray() throws Exception {} + + /** + * Invoked when the parser starts parsing an element of + * <code>annotations</code> array in + * <code>Runtime(In)VisibleAnnotations_attribute</code> + * or <code>parameter_annotations</code> array. + * + * @param cp the constant pool. + * @param typeIndex <code>type_index</code>. + * @param numMemberValuePairs <code>num_member_value_pairs</code>. + */ + public void beginAnnotation(ConstPool cp, + int typeIndex, int numMemberValuePairs) throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * <code>annotations</code> array in + * <code>Runtime(In)VisibleAnnotations_attribute</code> + * or <code>parameter_annotations</code> array. + */ + public void endAnnotation() throws Exception {} + + /** + * Invoked when the parser starts parsing an element of + * <code>member_value_pairs</code> array in <code>annotation</code>. + * + * @param cp the constant pool. + * @param memberNameIndex <code>member_name_index</code>. + */ + public void beginMemberValuePair(ConstPool cp, int memberNameIndex) + throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * <code>member_value_pairs</code> array in <code>annotation</code>. + */ + public void endMemberValuePair() throws Exception {} + + /** + * Invoked when the parser parses <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param cp the constant pool. + * @param tag <code>tag</code>. + * @param index <code>const_value_index</code>. + */ + public void constValueIndex(ConstPool cp, int tag, int index) + throws Exception {} + + /** + * Invoked when the parser parses <code>enum_const_value</code> + * in <code>member_value</code>. + * + * @param cp the constant pool. + * @param typeNameIndex <code>type_name_index</code>. + * @param constNameIndex <code>const_name_index</code>. + */ + public void enumConstValue(ConstPool cp, int typeNameIndex, + int constNameIndex) throws Exception {} + + /** + * Invoked when the parser parses <code>class_info_index</code> + * in <code>member_value</code>. + * + * @param cp the constant pool. + * @param index <code>class_info_index</code>. + */ + public void classInfoIndex(ConstPool cp, int index) throws Exception {} + + /** + * Invoked when the parser starts parsing <code>annotation_value</code> + * in <code>member_value</code>. + */ + public void beginAnnotationValue() throws Exception {} + + /** + * Invoked when the parser endss parsing <code>annotation_value</code> + * in <code>member_value</code>. + */ + public void endAnnotationValue() throws Exception {} + + /** + * Invoked when the parser starts parsing <code>array_value</code> + * in <code>member_value</code>. + * + * @param numValues <code>num_values</code>. + */ + public void beginArrayValue(int numValues) throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * <code>array_value</code>. + * + * @param i the index of that element. + */ + public void arrayElement(int i) throws Exception {} + + /** + * Invoked when the parser ends parsing <code>array_value</code> + * in <code>member_value</code>. + */ + public void endArrayValue() throws Exception {} +} diff --git a/src/main/javassist/bytecode/annotation/AnnotationsWriter.java b/src/main/javassist/bytecode/annotation/AnnotationsWriter.java new file mode 100644 index 00000000..791fbb39 --- /dev/null +++ b/src/main/javassist/bytecode/annotation/AnnotationsWriter.java @@ -0,0 +1,348 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ + +package javassist.bytecode.annotation; + +import java.io.*; + +import javassist.bytecode.ByteArray; +import javassist.bytecode.ConstPool; + +/** + * A convenience class for constructing a + * <code>..Annotations_attribute</code>. + * It is typically used together with <code>AnnotationsVisitor</code>. + * See the source code of the <code>AnnotationsAttribute.Copier</code> class. + * + * <p>The following code snippet is an example of use of this class: + * + * <ul><pre> + * ConstPool pool = ...; + * output = new ByteArrayOutputStream(); + * writer = new AnnotationsWriter(output, pool); + * + * writer.numAnnotations(1); + * writer.annotation("Author", 2); + * writer.memberValuePair("name"); + * writer.constValueIndex("chiba"); + * writer.memberValuePair("address"); + * writer.constValueIndex("tokyo"); + * + * writer.close(); + * byte[] attribute_info = output.toByteArray(); + * AnnotationsAttribute anno + * = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag, + * attribute_info); + * </pre></ul> + * + * <p>The code snippet above generates the annotation attribute + * corresponding to this annotation: + * + * <ul><pre> + * @Author(name = "chiba", address = "tokyo") + * </pre></ul> + * + * @see AnnotationsAttribute + * @see ParameterAnnotationsAttribute + * @see AnnotationsVisitor + */ +public class AnnotationsWriter { + private OutputStream output; + private ConstPool pool; + + /** + * Constructs with the given output stream. + * + * @param os the output stream. + * @param cp the constant pool. + */ + public AnnotationsWriter(OutputStream os, ConstPool cp) { + output = os; + pool = cp; + } + + /** + * Closes the output stream. + * + */ + public void close() throws IOException { + output.close(); + } + + /** + * Writes <code>num_parameters</code> in + * <code>Runtime(In)VisibleParameterAnnotations_attribute</code>. + * This method must be followed by <code>num</code> calls to + * <code>numAnnotations()</code>. + */ + public void numParameters(int num) throws IOException { + output.write(num); + } + + /** + * Writes <code>num_annotations</code> in + * <code>Runtime(In)VisibleAnnotations_attribute</code>. + * This method must be followed by <code>num</code> calls to + * <code>annotation()</code>. + */ + public void numAnnotations(int num) throws IOException { + write16bit(num); + } + + /** + * Writes <code>annotation</code>. + * This method must be followed by <code>numMemberValuePairs</code> + * calls to <code>memberValuePair()</code>. + * + * @param type the annotation interface name. + * @param numMemberValuePairs <code>num_member_value_pairs</code> + * in <code>annotation</code>. + */ + public void annotation(String type, int numMemberValuePairs) + throws IOException + { + annotation(pool.addUtf8Info(type), numMemberValuePairs); + } + + /** + * Writes <code>annotation</code>. + * This method must be followed by <code>numMemberValuePairs</code> + * calls to <code>memberValuePair()</code>. + * + * @param typeIndex <code>type_index</code> in <code>annotation</code>. + * @param numMemberValuePairs <code>num_member_value_pairs</code> + * in <code>annotation</code>. + */ + public void annotation(int typeIndex, int numMemberValuePairs) + throws IOException + { + write16bit(typeIndex); + write16bit(numMemberValuePairs); + } + + /** + * Writes an element of a <code>member_value_pairs</code> array + * in <code>annotation</code>. + * This method must be followed by a + * call to <code>constValueIndex()</code>, <code>enumConstValue()</code>, + * etc. + * + * @param memberName the name of the annotation type member. + */ + public void memberValuePair(String memberName) throws IOException { + memberValuePair(pool.addUtf8Info(memberName)); + } + + /** + * Writes an element of a <code>member_value_pairs</code> array + * in <code>annotation</code>. + * This method must be followed by a + * call to <code>constValueIndex()</code>, <code>enumConstValue()</code>, + * etc. + * + * @param memberNameIndex <code>member_name_index</code> + * in <code>member_value_pairs</code> array. + */ + public void memberValuePair(int memberNameIndex) throws IOException { + write16bit(memberNameIndex); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(boolean value) throws IOException { + constValueIndex('Z', pool.addIntegerInfo(value ? 1 : 0)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(byte value) throws IOException { + constValueIndex('B', pool.addIntegerInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(char value) throws IOException { + constValueIndex('C', pool.addIntegerInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(short value) throws IOException { + constValueIndex('S', pool.addIntegerInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(int value) throws IOException { + constValueIndex('I', pool.addIntegerInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(long value) throws IOException { + constValueIndex('J', pool.addLongInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(float value) throws IOException { + constValueIndex('F', pool.addFloatInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(double value) throws IOException { + constValueIndex('D', pool.addDoubleInfo(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param value the constant value. + */ + public void constValueIndex(String value) throws IOException { + constValueIndex('s', pool.addUtf8Info(value)); + } + + /** + * Writes <code>tag</code> and <code>const_value_index</code> + * in <code>member_value</code>. + * + * @param tag <code>tag</code> in <code>member_value</code>. + * @param index <code>const_value_index</code> + * in <code>member_value</code>. + */ + public void constValueIndex(int tag, int index) + throws IOException + { + output.write(tag); + write16bit(index); + } + + /** + * Writes <code>tag</code> and <code>enum_const_value</code> + * in <code>member_value</code>. + * + * @param typeName the type name of the enum constant. + * @param constName the simple name of the enum constant. + */ + public void enumConstValue(String typeName, String constName) + throws IOException + { + enumConstValue(pool.addUtf8Info(typeName), + pool.addUtf8Info(constName)); + } + + /** + * Writes <code>tag</code> and <code>enum_const_value</code> + * in <code>member_value</code>. + * + * @param typeNameIndex <code>type_name_index</code> + * in <code>member_value</code>. + * @param constNameIndex <code>const_name_index</code> + * in <code>member_value</code>. + */ + public void enumConstValue(int typeNameIndex, int constNameIndex) + throws IOException + { + output.write('e'); + write16bit(typeNameIndex); + write16bit(constNameIndex); + } + + /** + * Writes <code>tag</code> and <code>class_info_index</code> + * in <code>member_value</code>. + * + * @param name the class name. + */ + public void classInfoIndex(String name) throws IOException { + classInfoIndex(pool.addUtf8Info(name)); + } + + /** + * Writes <code>tag</code> and <code>class_info_index</code> + * in <code>member_value</code>. + * + * @param index <code>class_info_index</code> + */ + public void classInfoIndex(int index) throws IOException { + output.write('c'); + write16bit(index); + } + + /** + * Writes <code>tag</code> and <code>annotation_value</code> + * in <code>member_value</code>. + * This method must be followed by a call to <code>annotation()</code>. + */ + public void annotationValue() throws IOException { + output.write('@'); + } + + /** + * Writes <code>tag</code> and <code>array_value</code> + * in <code>member_value</code>. + * This method must be followed by a <code>numValues</code> + * call to <code>constValueIndex()</code>, <code>enumConstValue()</code>, + * etc. + * + * @param numValues <code>num_values</code> + * in <code>array_value</code>. + */ + public void arrayValue(int numValues) throws IOException { + output.write('['); + write16bit(numValues); + } + + private void write16bit(int value) throws IOException { + byte[] buf = new byte[2]; + ByteArray.write16bit(value, buf, 0); + output.write(buf); + } +} diff --git a/src/main/javassist/bytecode/annotation/ClassMemberValue.java b/src/main/javassist/bytecode/annotation/ClassMemberValue.java index 8a075f03..2dedd90f 100644 --- a/src/main/javassist/bytecode/annotation/ClassMemberValue.java +++ b/src/main/javassist/bytecode/annotation/ClassMemberValue.java @@ -24,7 +24,7 @@ import java.io.IOException; * Comment * * @author <a href="mailto:bill@jboss.org">Bill Burke</a> - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * **/ public class ClassMemberValue extends MemberValue @@ -46,13 +46,13 @@ public class ClassMemberValue extends MemberValue public String getClassName() { // beta1 return cp.getClassInfo(class_info_index); - return Descriptor.fromDescriptor(cp.getUtf8Info(class_info_index)); + return Descriptor.toClassName(cp.getUtf8Info(class_info_index)); } public void setClassName(String name) { // beta1 class_info_index = (short)cp.addClassInfo(name); - class_info_index = (short)cp.addUtf8Info(Descriptor.toDescriptor(name)); + class_info_index = (short)cp.addUtf8Info(Descriptor.of(name)); } public String toString() diff --git a/src/main/javassist/bytecode/annotation/EnumMemberValue.java b/src/main/javassist/bytecode/annotation/EnumMemberValue.java index f2c395a0..12247aed 100644 --- a/src/main/javassist/bytecode/annotation/EnumMemberValue.java +++ b/src/main/javassist/bytecode/annotation/EnumMemberValue.java @@ -25,7 +25,7 @@ import java.io.IOException; * Comment * * @author <a href="mailto:bill@jboss.org">Bill Burke</a> - * @version $Revision: 1.4 $ + * @version $Revision: 1.5 $ * **/ public class EnumMemberValue extends MemberValue @@ -56,7 +56,7 @@ public class EnumMemberValue extends MemberValue */ public String getEnumType() { - return Descriptor.fromDescriptor(cp.getUtf8Info(type_name_index)); + return Descriptor.toClassName(cp.getUtf8Info(type_name_index)); } /** @@ -65,7 +65,7 @@ public class EnumMemberValue extends MemberValue */ public void setEnumType(String classname) { - type_name_index = (short)cp.addUtf8Info(Descriptor.toDescriptor(classname)); + type_name_index = (short)cp.addUtf8Info(Descriptor.of(classname)); } public String getEnumVal() diff --git a/src/main/javassist/bytecode/annotation/package.html b/src/main/javassist/bytecode/annotation/package.html new file mode 100644 index 00000000..4be4ae9f --- /dev/null +++ b/src/main/javassist/bytecode/annotation/package.html @@ -0,0 +1,8 @@ +<html> +<body> +Annotations. + +<p>This package provides low-level API for editing annotations attributes. + +</body> +</html> |