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 | |
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
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | src/main/javassist/bytecode/AnnotationsAttribute.java | 465 | ||||
-rw-r--r-- | src/main/javassist/bytecode/AttributeInfo.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/ConstPool.java | 1 | ||||
-rw-r--r-- | src/main/javassist/bytecode/Descriptor.java | 28 | ||||
-rw-r--r-- | src/main/javassist/bytecode/ParameterAnnotationsAttribute.java | 110 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/AnnotationInfo.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/AnnotationsVisitor.java | 163 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/AnnotationsWriter.java | 348 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/ClassMemberValue.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/EnumMemberValue.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/annotation/package.html | 8 |
12 files changed, 1125 insertions, 24 deletions
diff --git a/Readme.html b/Readme.html index fbf088f9..8ce4d36a 100644 --- a/Readme.html +++ b/Readme.html @@ -555,7 +555,7 @@ Remy Sanlaville, Muga Nishizawa, Alexey Loubyansky, Saori Oki, Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos, Denis Taye, Colin Sampaleanu, Robert Bialek, Asato Shimotaki, Howard Lewis Ship, Richard Jones, Marjan Sterjev, -Bruce McDonald, and Mark Brennan +Bruce McDonald, Mark Brennan, and Vlad Skarzhevskyy. for their contributions. <p><br> 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> |