/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- 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,
* or the Apache License Version 2.0.
*
* 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.
IOException;
import java.io.
OutputStream;
import javassist.bytecode.
ByteArray;
import javassist.bytecode.
ConstPool;
/**
* A convenience class for constructing a
* <code>..Annotations_attribute</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:
*
* <pre>
* ConstPool pool = ...;
* output = new ByteArrayOutputStream();
* writer = new AnnotationsWriter(output, pool);
*
* writer.numAnnotations(1);
* writer.annotation("Author", 2);
* writer.memberValuePair("name"); // element_value_pair
* writer.constValueIndex("chiba");
* writer.memberValuePair("address"); // element_value_pair
* writer.constValueIndex("tokyo");
*
* writer.close();
* byte[] attribute_info = output.toByteArray();
* AnnotationsAttribute anno
* = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag,
* attribute_info);
* </pre>
*
* <p>The code snippet above generates the annotation attribute
* corresponding to this annotation:
*
* <pre>
* @Author(name = "chiba", address = "tokyo")
* </pre>
*
* @see javassist.bytecode.AnnotationsAttribute
* @see javassist.bytecode.ParameterAnnotationsAttribute
*/
public class
AnnotationsWriter {
protected
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;
}
/**
* Obtains the constant pool given to the constructor.
*/
public
ConstPool getConstPool() {
return
pool;
}
/**
* 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_element_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_element_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>element_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 element name.
*/
public void
memberValuePair(
String memberName) throws
IOException {
memberValuePair(
pool.
addUtf8Info(
memberName));
}
/**
* Writes an element of a <code>element_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>element_name_index</code>
* in <code>element_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>element_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>element_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>element_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>element_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>element_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>element_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>element_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>element_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>element_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>element_value</code>.
*
* @param tag <code>tag</code> in <code>element_value</code>.
* @param index <code>const_value_index</code>
* in <code>element_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>element_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>element_value</code>.
*
* @param typeNameIndex <code>type_name_index</code>
* in <code>element_value</code>.
* @param constNameIndex <code>const_name_index</code>
* in <code>element_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>element_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>element_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>element_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>element_value</code>.
* This method must be followed by <code>numValues</code> calls
* 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);
}
protected void
write16bit(int
value) throws
IOException {
byte[]
buf = new byte[2];
ByteArray.
write16bit(
value,
buf, 0);
output.
write(
buf);
}
}