From 6f0d550f399ed4d5bee1d42caccb51b4f460e401 Mon Sep 17 00:00:00 2001 From: chiba Date: Thu, 10 Jun 2004 15:56:45 +0000 Subject: [PATCH] Added javassist.bytecode.AnnotationsAttribute and support classes. git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@110 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- Readme.html | 2 +- .../bytecode/AnnotationsAttribute.java | 465 ++++++++++++++++++ .../javassist/bytecode/AttributeInfo.java | 6 + src/main/javassist/bytecode/ConstPool.java | 1 + src/main/javassist/bytecode/Descriptor.java | 28 +- .../ParameterAnnotationsAttribute.java | 110 +++++ .../bytecode/annotation/AnnotationInfo.java | 6 +- .../annotation/AnnotationsVisitor.java | 163 ++++++ .../annotation/AnnotationsWriter.java | 348 +++++++++++++ .../bytecode/annotation/ClassMemberValue.java | 6 +- .../bytecode/annotation/EnumMemberValue.java | 6 +- .../bytecode/annotation/package.html | 8 + 12 files changed, 1125 insertions(+), 24 deletions(-) create mode 100644 src/main/javassist/bytecode/AnnotationsAttribute.java create mode 100644 src/main/javassist/bytecode/ParameterAnnotationsAttribute.java create mode 100644 src/main/javassist/bytecode/annotation/AnnotationsVisitor.java create mode 100644 src/main/javassist/bytecode/annotation/AnnotationsWriter.java create mode 100644 src/main/javassist/bytecode/annotation/package.html 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.


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 + * RuntimeVisibleAnnotations_attribute and + * RuntimeInvisibleAnnotations_attribute. + */ +public class AnnotationsAttribute extends AttributeInfo { + /** + * The name of the RuntimeVisibleAnnotations attribute. + */ + public static final String visibleTag = "RuntimeVisibleAnnotations"; + + /** + * The name of the RuntimeInvisibleAnnotations attribute. + */ + public static final String invisibleTag = "RuntimeInvisibleAnnotations"; + + /** + * Constructs a Runtime(In)VisisbleAnnotations_attribute. + * + * @param cp constant pool + * @param attrname attribute name (visibleTag or + * invisibleTag). + * @param info the contents of this attribute. It does not + * include attribute_name_index or + * attribute_length. + */ + public AnnotationsAttribute(ConstPool cp, String attrname, byte[] info) { + super(cp, attrname, info); + } + + /** + * Constructs an empty + * Runtime(In)VisisbleAnnotations_attribute. + * + * @param cp constant pool + * @param attrname attribute name (visibleTag or + * invisibleTag). + */ + 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 num_annotations. + */ + 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 + * ParameterAnnotationsAttribute. + */ + 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 + * AnnotationsAttribute. + * + *

This class is typically used as following: + *

+ * + *

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 map 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 accept() + * on src with this visitor object. + * + * @param src the source attribute. It can be an instance + * of ParameterAnnotationsAttribute. + * @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 num_parameters. + */ + public void beginParameters(int num) throws IOException { + writer.numParameters(num); + } + + /** + * Does nothing. + */ + public void endParameters() {} + + /** + * Writes num_annotations. + */ + public void beginAnnotationsArray(int num) throws IOException { + writer.numAnnotations(num); + } + + /** + * Does nothing. + */ + public void endAnnotationsArray() {} + + /** + * Writes type_index and + * num_member_value_pairs. + */ + public void beginAnnotation(ConstPool cp, + int typeIndex, int numMemberValuePairs) + throws IOException + { + writer.annotation(copy(cp, typeIndex), numMemberValuePairs); + } + + /** + * Does nothing. + */ + public void endAnnotation() {} + + /** + * Writes member_name_index. + */ + public void beginMemberValuePair(ConstPool cp, int memberNameIndex) + throws IOException + { + writer.memberValuePair(copy(cp, memberNameIndex)); + } + + /** + * Does nothing. + */ + public void endMemberValuePair() {} + + /** + * Writes tag and const_value_index. + */ + public void constValueIndex(ConstPool cp, int tag, int index) + throws IOException + { + writer.constValueIndex(tag, copy(cp, index)); + } + + /** + * Writes tag and enum_const_value. + */ + public void enumConstValue(ConstPool cp, int typeNameIndex, + int constNameIndex) + throws IOException + { + writer.enumConstValue(copy(cp, typeNameIndex), + copy(cp, constNameIndex)); + } + + /** + * Writes tag and class_info_index. + */ + public void classInfoIndex(ConstPool cp, int index) throws IOException { + writer.classInfoIndex(copy(cp, index)); + } + + /** + * Writes tag. + */ + public void beginAnnotationValue() throws IOException { + writer.annotationValue(); + } + + /** + * Does nothing. + */ + public void endAnnotationValue() {} + + /** + * Writes num_values in array_value. + */ + public void beginArrayValue(int numValues) throws IOException { + writer.arrayValue(numValues); + } + + /** + * Does nothing. + */ + public void arrayElement(int i) {} + + /** + * Invoked when the parser ends parsing array_value + * in member_value. + */ + 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 n-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 RuntimeVisibleAnnotations_attribute and + * RuntimeInvisibleAnnotations_attribute. + */ +public class ParameterAnnotationsAttribute extends AnnotationsAttribute { + /** + * The name of the RuntimeVisibleParameterAnnotations + * attribute. + */ + public static final String visibleTag + = "RuntimeVisibleParameterAnnotations"; + + /** + * The name of the RuntimeInvisibleParameterAnnotations + * attribute. + */ + public static final String invisibleTag + = "RuntimeInvisibleParameterAnnotations"; + /** + * Constructs + * a Runtime(In)VisisbleParameterAnnotations_attribute. + * + * @param cp constant pool + * @param attrname attribute name (visibleTag or + * invisibleTag). + * @param info the contents of this attribute. It does not + * include attribute_name_index or + * attribute_length. + */ + public ParameterAnnotationsAttribute(ConstPool cp, String attrname, + byte[] info) { + super(cp, attrname, info); + } + + /** + * Constructs an empty + * Runtime(In)VisisbleParameterAnnotations_attribute. + * + * @param cp constant pool + * @param attrname attribute name (visibleTag or + * invisibleTag). + */ + 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 num_parameters. + */ + 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 Bill Burke - * @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 + * parameter_annotations array. + * If the annotations attribute is not a parameter annotations attribute, + * this method is never invoked. + * + * @param numParameters num_parameters. + */ + public void beginParameters(int numParameters) throws Exception {} + + /** + * Invoked when the parser ends parsing a + * parameter_annotations 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 + * annotations array in + * ..Annotations_attribute. + * + * @param numAnnotations num_annotations. + */ + public void beginAnnotationsArray(int numAnnotations) + throws Exception {} + + /** + * Invoked when the parser ends parsing an + * annotations array in + * ..Annotations_attribute. + */ + public void endAnnotationsArray() throws Exception {} + + /** + * Invoked when the parser starts parsing an element of + * annotations array in + * Runtime(In)VisibleAnnotations_attribute + * or parameter_annotations array. + * + * @param cp the constant pool. + * @param typeIndex type_index. + * @param numMemberValuePairs num_member_value_pairs. + */ + public void beginAnnotation(ConstPool cp, + int typeIndex, int numMemberValuePairs) throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * annotations array in + * Runtime(In)VisibleAnnotations_attribute + * or parameter_annotations array. + */ + public void endAnnotation() throws Exception {} + + /** + * Invoked when the parser starts parsing an element of + * member_value_pairs array in annotation. + * + * @param cp the constant pool. + * @param memberNameIndex member_name_index. + */ + public void beginMemberValuePair(ConstPool cp, int memberNameIndex) + throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * member_value_pairs array in annotation. + */ + public void endMemberValuePair() throws Exception {} + + /** + * Invoked when the parser parses const_value_index + * in member_value. + * + * @param cp the constant pool. + * @param tag tag. + * @param index const_value_index. + */ + public void constValueIndex(ConstPool cp, int tag, int index) + throws Exception {} + + /** + * Invoked when the parser parses enum_const_value + * in member_value. + * + * @param cp the constant pool. + * @param typeNameIndex type_name_index. + * @param constNameIndex const_name_index. + */ + public void enumConstValue(ConstPool cp, int typeNameIndex, + int constNameIndex) throws Exception {} + + /** + * Invoked when the parser parses class_info_index + * in member_value. + * + * @param cp the constant pool. + * @param index class_info_index. + */ + public void classInfoIndex(ConstPool cp, int index) throws Exception {} + + /** + * Invoked when the parser starts parsing annotation_value + * in member_value. + */ + public void beginAnnotationValue() throws Exception {} + + /** + * Invoked when the parser endss parsing annotation_value + * in member_value. + */ + public void endAnnotationValue() throws Exception {} + + /** + * Invoked when the parser starts parsing array_value + * in member_value. + * + * @param numValues num_values. + */ + public void beginArrayValue(int numValues) throws Exception {} + + /** + * Invoked when the parser ends parsing an element of + * array_value. + * + * @param i the index of that element. + */ + public void arrayElement(int i) throws Exception {} + + /** + * Invoked when the parser ends parsing array_value + * in member_value. + */ + 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 + * ..Annotations_attribute. + * It is typically used together with AnnotationsVisitor. + * See the source code of the AnnotationsAttribute.Copier class. + * + *

The following code snippet is an example of use of this class: + * + *

+ * + *

The code snippet above generates the annotation attribute + * corresponding to this annotation: + * + *

+ * + * @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 num_parameters in + * Runtime(In)VisibleParameterAnnotations_attribute. + * This method must be followed by num calls to + * numAnnotations(). + */ + public void numParameters(int num) throws IOException { + output.write(num); + } + + /** + * Writes num_annotations in + * Runtime(In)VisibleAnnotations_attribute. + * This method must be followed by num calls to + * annotation(). + */ + public void numAnnotations(int num) throws IOException { + write16bit(num); + } + + /** + * Writes annotation. + * This method must be followed by numMemberValuePairs + * calls to memberValuePair(). + * + * @param type the annotation interface name. + * @param numMemberValuePairs num_member_value_pairs + * in annotation. + */ + public void annotation(String type, int numMemberValuePairs) + throws IOException + { + annotation(pool.addUtf8Info(type), numMemberValuePairs); + } + + /** + * Writes annotation. + * This method must be followed by numMemberValuePairs + * calls to memberValuePair(). + * + * @param typeIndex type_index in annotation. + * @param numMemberValuePairs num_member_value_pairs + * in annotation. + */ + public void annotation(int typeIndex, int numMemberValuePairs) + throws IOException + { + write16bit(typeIndex); + write16bit(numMemberValuePairs); + } + + /** + * Writes an element of a member_value_pairs array + * in annotation. + * This method must be followed by a + * call to constValueIndex(), enumConstValue(), + * 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 member_value_pairs array + * in annotation. + * This method must be followed by a + * call to constValueIndex(), enumConstValue(), + * etc. + * + * @param memberNameIndex member_name_index + * in member_value_pairs array. + */ + public void memberValuePair(int memberNameIndex) throws IOException { + write16bit(memberNameIndex); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(boolean value) throws IOException { + constValueIndex('Z', pool.addIntegerInfo(value ? 1 : 0)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(byte value) throws IOException { + constValueIndex('B', pool.addIntegerInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(char value) throws IOException { + constValueIndex('C', pool.addIntegerInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(short value) throws IOException { + constValueIndex('S', pool.addIntegerInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(int value) throws IOException { + constValueIndex('I', pool.addIntegerInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(long value) throws IOException { + constValueIndex('J', pool.addLongInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(float value) throws IOException { + constValueIndex('F', pool.addFloatInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(double value) throws IOException { + constValueIndex('D', pool.addDoubleInfo(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param value the constant value. + */ + public void constValueIndex(String value) throws IOException { + constValueIndex('s', pool.addUtf8Info(value)); + } + + /** + * Writes tag and const_value_index + * in member_value. + * + * @param tag tag in member_value. + * @param index const_value_index + * in member_value. + */ + public void constValueIndex(int tag, int index) + throws IOException + { + output.write(tag); + write16bit(index); + } + + /** + * Writes tag and enum_const_value + * in member_value. + * + * @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 tag and enum_const_value + * in member_value. + * + * @param typeNameIndex type_name_index + * in member_value. + * @param constNameIndex const_name_index + * in member_value. + */ + public void enumConstValue(int typeNameIndex, int constNameIndex) + throws IOException + { + output.write('e'); + write16bit(typeNameIndex); + write16bit(constNameIndex); + } + + /** + * Writes tag and class_info_index + * in member_value. + * + * @param name the class name. + */ + public void classInfoIndex(String name) throws IOException { + classInfoIndex(pool.addUtf8Info(name)); + } + + /** + * Writes tag and class_info_index + * in member_value. + * + * @param index class_info_index + */ + public void classInfoIndex(int index) throws IOException { + output.write('c'); + write16bit(index); + } + + /** + * Writes tag and annotation_value + * in member_value. + * This method must be followed by a call to annotation(). + */ + public void annotationValue() throws IOException { + output.write('@'); + } + + /** + * Writes tag and array_value + * in member_value. + * This method must be followed by a numValues + * call to constValueIndex(), enumConstValue(), + * etc. + * + * @param numValues num_values + * in array_value. + */ + 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 Bill Burke - * @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 Bill Burke - * @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 @@ + + +Annotations. + +

This package provides low-level API for editing annotations attributes. + + + -- 2.39.5