001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.bytecode.annotation;
017:
018: import java.io.*;
019:
020: import javassist.bytecode.ByteArray;
021: import javassist.bytecode.ConstPool;
022:
023: /**
024: * A convenience class for constructing a
025: * <code>..Annotations_attribute</code>.
026: * See the source code of the <code>AnnotationsAttribute.Copier</code> class.
027: *
028: * <p>The following code snippet is an example of use of this class:
029: *
030: * <ul><pre>
031: * ConstPool pool = ...;
032: * output = new ByteArrayOutputStream();
033: * writer = new AnnotationsWriter(output, pool);
034: *
035: * writer.numAnnotations(1);
036: * writer.annotation("Author", 2);
037: * writer.memberValuePair("name");
038: * writer.constValueIndex("chiba");
039: * writer.memberValuePair("address");
040: * writer.constValueIndex("tokyo");
041: *
042: * writer.close();
043: * byte[] attribute_info = output.toByteArray();
044: * AnnotationsAttribute anno
045: * = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag,
046: * attribute_info);
047: * </pre></ul>
048: *
049: * <p>The code snippet above generates the annotation attribute
050: * corresponding to this annotation:
051: *
052: * <ul><pre>
053: * @Author(name = "chiba", address = "tokyo")
054: * </pre></ul>
055: *
056: * @see javassist.bytecode.AnnotationsAttribute
057: * @see javassist.bytecode.ParameterAnnotationsAttribute
058: */
059: public class AnnotationsWriter {
060: private OutputStream output;
061: private ConstPool pool;
062:
063: /**
064: * Constructs with the given output stream.
065: *
066: * @param os the output stream.
067: * @param cp the constant pool.
068: */
069: public AnnotationsWriter(OutputStream os, ConstPool cp) {
070: output = os;
071: pool = cp;
072: }
073:
074: /**
075: * Obtains the constant pool given to the constructor.
076: */
077: public ConstPool getConstPool() {
078: return pool;
079: }
080:
081: /**
082: * Closes the output stream.
083: *
084: */
085: public void close() throws IOException {
086: output.close();
087: }
088:
089: /**
090: * Writes <code>num_parameters</code> in
091: * <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
092: * This method must be followed by <code>num</code> calls to
093: * <code>numAnnotations()</code>.
094: */
095: public void numParameters(int num) throws IOException {
096: output.write(num);
097: }
098:
099: /**
100: * Writes <code>num_annotations</code> in
101: * <code>Runtime(In)VisibleAnnotations_attribute</code>.
102: * This method must be followed by <code>num</code> calls to
103: * <code>annotation()</code>.
104: */
105: public void numAnnotations(int num) throws IOException {
106: write16bit(num);
107: }
108:
109: /**
110: * Writes <code>annotation</code>.
111: * This method must be followed by <code>numMemberValuePairs</code>
112: * calls to <code>memberValuePair()</code>.
113: *
114: * @param type the annotation interface name.
115: * @param numMemberValuePairs <code>num_member_value_pairs</code>
116: * in <code>annotation</code>.
117: */
118: public void annotation(String type, int numMemberValuePairs)
119: throws IOException {
120: annotation(pool.addUtf8Info(type), numMemberValuePairs);
121: }
122:
123: /**
124: * Writes <code>annotation</code>.
125: * This method must be followed by <code>numMemberValuePairs</code>
126: * calls to <code>memberValuePair()</code>.
127: *
128: * @param typeIndex <code>type_index</code> in <code>annotation</code>.
129: * @param numMemberValuePairs <code>num_member_value_pairs</code>
130: * in <code>annotation</code>.
131: */
132: public void annotation(int typeIndex, int numMemberValuePairs)
133: throws IOException {
134: write16bit(typeIndex);
135: write16bit(numMemberValuePairs);
136: }
137:
138: /**
139: * Writes an element of a <code>member_value_pairs</code> array
140: * in <code>annotation</code>.
141: * This method must be followed by a
142: * call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
143: * etc.
144: *
145: * @param memberName the name of the annotation type member.
146: */
147: public void memberValuePair(String memberName) throws IOException {
148: memberValuePair(pool.addUtf8Info(memberName));
149: }
150:
151: /**
152: * Writes an element of a <code>member_value_pairs</code> array
153: * in <code>annotation</code>.
154: * This method must be followed by a
155: * call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
156: * etc.
157: *
158: * @param memberNameIndex <code>member_name_index</code>
159: * in <code>member_value_pairs</code> array.
160: */
161: public void memberValuePair(int memberNameIndex) throws IOException {
162: write16bit(memberNameIndex);
163: }
164:
165: /**
166: * Writes <code>tag</code> and <code>const_value_index</code>
167: * in <code>member_value</code>.
168: *
169: * @param value the constant value.
170: */
171: public void constValueIndex(boolean value) throws IOException {
172: constValueIndex('Z', pool.addIntegerInfo(value ? 1 : 0));
173: }
174:
175: /**
176: * Writes <code>tag</code> and <code>const_value_index</code>
177: * in <code>member_value</code>.
178: *
179: * @param value the constant value.
180: */
181: public void constValueIndex(byte value) throws IOException {
182: constValueIndex('B', pool.addIntegerInfo(value));
183: }
184:
185: /**
186: * Writes <code>tag</code> and <code>const_value_index</code>
187: * in <code>member_value</code>.
188: *
189: * @param value the constant value.
190: */
191: public void constValueIndex(char value) throws IOException {
192: constValueIndex('C', pool.addIntegerInfo(value));
193: }
194:
195: /**
196: * Writes <code>tag</code> and <code>const_value_index</code>
197: * in <code>member_value</code>.
198: *
199: * @param value the constant value.
200: */
201: public void constValueIndex(short value) throws IOException {
202: constValueIndex('S', pool.addIntegerInfo(value));
203: }
204:
205: /**
206: * Writes <code>tag</code> and <code>const_value_index</code>
207: * in <code>member_value</code>.
208: *
209: * @param value the constant value.
210: */
211: public void constValueIndex(int value) throws IOException {
212: constValueIndex('I', pool.addIntegerInfo(value));
213: }
214:
215: /**
216: * Writes <code>tag</code> and <code>const_value_index</code>
217: * in <code>member_value</code>.
218: *
219: * @param value the constant value.
220: */
221: public void constValueIndex(long value) throws IOException {
222: constValueIndex('J', pool.addLongInfo(value));
223: }
224:
225: /**
226: * Writes <code>tag</code> and <code>const_value_index</code>
227: * in <code>member_value</code>.
228: *
229: * @param value the constant value.
230: */
231: public void constValueIndex(float value) throws IOException {
232: constValueIndex('F', pool.addFloatInfo(value));
233: }
234:
235: /**
236: * Writes <code>tag</code> and <code>const_value_index</code>
237: * in <code>member_value</code>.
238: *
239: * @param value the constant value.
240: */
241: public void constValueIndex(double value) throws IOException {
242: constValueIndex('D', pool.addDoubleInfo(value));
243: }
244:
245: /**
246: * Writes <code>tag</code> and <code>const_value_index</code>
247: * in <code>member_value</code>.
248: *
249: * @param value the constant value.
250: */
251: public void constValueIndex(String value) throws IOException {
252: constValueIndex('s', pool.addUtf8Info(value));
253: }
254:
255: /**
256: * Writes <code>tag</code> and <code>const_value_index</code>
257: * in <code>member_value</code>.
258: *
259: * @param tag <code>tag</code> in <code>member_value</code>.
260: * @param index <code>const_value_index</code>
261: * in <code>member_value</code>.
262: */
263: public void constValueIndex(int tag, int index) throws IOException {
264: output.write(tag);
265: write16bit(index);
266: }
267:
268: /**
269: * Writes <code>tag</code> and <code>enum_const_value</code>
270: * in <code>member_value</code>.
271: *
272: * @param typeName the type name of the enum constant.
273: * @param constName the simple name of the enum constant.
274: */
275: public void enumConstValue(String typeName, String constName)
276: throws IOException {
277: enumConstValue(pool.addUtf8Info(typeName), pool
278: .addUtf8Info(constName));
279: }
280:
281: /**
282: * Writes <code>tag</code> and <code>enum_const_value</code>
283: * in <code>member_value</code>.
284: *
285: * @param typeNameIndex <code>type_name_index</code>
286: * in <code>member_value</code>.
287: * @param constNameIndex <code>const_name_index</code>
288: * in <code>member_value</code>.
289: */
290: public void enumConstValue(int typeNameIndex, int constNameIndex)
291: throws IOException {
292: output.write('e');
293: write16bit(typeNameIndex);
294: write16bit(constNameIndex);
295: }
296:
297: /**
298: * Writes <code>tag</code> and <code>class_info_index</code>
299: * in <code>member_value</code>.
300: *
301: * @param name the class name.
302: */
303: public void classInfoIndex(String name) throws IOException {
304: classInfoIndex(pool.addUtf8Info(name));
305: }
306:
307: /**
308: * Writes <code>tag</code> and <code>class_info_index</code>
309: * in <code>member_value</code>.
310: *
311: * @param index <code>class_info_index</code>
312: */
313: public void classInfoIndex(int index) throws IOException {
314: output.write('c');
315: write16bit(index);
316: }
317:
318: /**
319: * Writes <code>tag</code> and <code>annotation_value</code>
320: * in <code>member_value</code>.
321: * This method must be followed by a call to <code>annotation()</code>.
322: */
323: public void annotationValue() throws IOException {
324: output.write('@');
325: }
326:
327: /**
328: * Writes <code>tag</code> and <code>array_value</code>
329: * in <code>member_value</code>.
330: * This method must be followed by <code>numValues</code> calls
331: * to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
332: * etc.
333: *
334: * @param numValues <code>num_values</code>
335: * in <code>array_value</code>.
336: */
337: public void arrayValue(int numValues) throws IOException {
338: output.write('[');
339: write16bit(numValues);
340: }
341:
342: private void write16bit(int value) throws IOException {
343: byte[] buf = new byte[2];
344: ByteArray.write16bit(value, buf, 0);
345: output.write(buf);
346: }
347: }
|