git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@110 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
@@ -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> |
@@ -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('}'); | |||
} | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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) |
@@ -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) + ";"; | |||
} | |||
/** |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
@@ -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 {} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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() |
@@ -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() |
@@ -0,0 +1,8 @@ | |||
<html> | |||
<body> | |||
Annotations. | |||
<p>This package provides low-level API for editing annotations attributes. | |||
</body> | |||
</html> |