KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > asm > AnnotationWriter


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package com.tc.asm;
31
32 /**
33  * An {@link AnnotationVisitor} that generates annotations in bytecode form.
34  *
35  * @author Eric Bruneton
36  * @author Eugene Kuleshov
37  */

38 final class AnnotationWriter implements AnnotationVisitor {
39
40     /**
41      * The class writer to which this annotation must be added.
42      */

43     private final ClassWriter cw;
44
45     /**
46      * The number of values in this annotation.
47      */

48     private int size;
49
50     /**
51      * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
52      * writers used for annotation default and annotation arrays use unnamed
53      * values.
54      */

55     private final boolean named;
56
57     /**
58      * The annotation values in bytecode form. This byte vector only contains
59      * the values themselves, i.e. the number of values must be stored as a
60      * unsigned short just before these bytes.
61      */

62     private final ByteVector bv;
63
64     /**
65      * The byte vector to be used to store the number of values of this
66      * annotation. See {@link #bv}.
67      */

68     private final ByteVector parent;
69
70     /**
71      * Where the number of values of this annotation must be stored in
72      * {@link #parent}.
73      */

74     private final int offset;
75
76     /**
77      * Next annotation writer. This field is used to store annotation lists.
78      */

79     AnnotationWriter next;
80
81     /**
82      * Previous annotation writer. This field is used to store annotation lists.
83      */

84     AnnotationWriter prev;
85
86     // ------------------------------------------------------------------------
87
// Constructor
88
// ------------------------------------------------------------------------
89

90     /**
91      * Constructs a new {@link AnnotationWriter}.
92      *
93      * @param cw the class writer to which this annotation must be added.
94      * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
95      * @param bv where the annotation values must be stored.
96      * @param parent where the number of annotation values must be stored.
97      * @param offset where in <tt>parent</tt> the number of annotation values must
98      * be stored.
99      */

100     AnnotationWriter(
101         final ClassWriter cw,
102         final boolean named,
103         final ByteVector bv,
104         final ByteVector parent,
105         final int offset)
106     {
107         this.cw = cw;
108         this.named = named;
109         this.bv = bv;
110         this.parent = parent;
111         this.offset = offset;
112     }
113
114     // ------------------------------------------------------------------------
115
// Implementation of the AnnotationVisitor interface
116
// ------------------------------------------------------------------------
117

118     public void visit(final String JavaDoc name, final Object JavaDoc value) {
119         ++size;
120         if (named) {
121             bv.putShort(cw.newUTF8(name));
122         }
123         if (value instanceof String JavaDoc) {
124             bv.put12('s', cw.newUTF8((String JavaDoc) value));
125         } else if (value instanceof Byte JavaDoc) {
126             bv.put12('B', cw.newInteger(((Byte JavaDoc) value).byteValue()).index);
127         } else if (value instanceof Boolean JavaDoc) {
128             int v = ((Boolean JavaDoc) value).booleanValue() ? 1 : 0;
129             bv.put12('Z', cw.newInteger(v).index);
130         } else if (value instanceof Character JavaDoc) {
131             bv.put12('C', cw.newInteger(((Character JavaDoc) value).charValue()).index);
132         } else if (value instanceof Short JavaDoc) {
133             bv.put12('S', cw.newInteger(((Short JavaDoc) value).shortValue()).index);
134         } else if (value instanceof Type) {
135             bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
136         } else if (value instanceof byte[]) {
137             byte[] v = (byte[]) value;
138             bv.put12('[', v.length);
139             for (int i = 0; i < v.length; i++) {
140                 bv.put12('B', cw.newInteger(v[i]).index);
141             }
142         } else if (value instanceof boolean[]) {
143             boolean[] v = (boolean[]) value;
144             bv.put12('[', v.length);
145             for (int i = 0; i < v.length; i++) {
146                 bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
147             }
148         } else if (value instanceof short[]) {
149             short[] v = (short[]) value;
150             bv.put12('[', v.length);
151             for (int i = 0; i < v.length; i++) {
152                 bv.put12('S', cw.newInteger(v[i]).index);
153             }
154         } else if (value instanceof char[]) {
155             char[] v = (char[]) value;
156             bv.put12('[', v.length);
157             for (int i = 0; i < v.length; i++) {
158                 bv.put12('C', cw.newInteger(v[i]).index);
159             }
160         } else if (value instanceof int[]) {
161             int[] v = (int[]) value;
162             bv.put12('[', v.length);
163             for (int i = 0; i < v.length; i++) {
164                 bv.put12('I', cw.newInteger(v[i]).index);
165             }
166         } else if (value instanceof long[]) {
167             long[] v = (long[]) value;
168             bv.put12('[', v.length);
169             for (int i = 0; i < v.length; i++) {
170                 bv.put12('J', cw.newLong(v[i]).index);
171             }
172         } else if (value instanceof float[]) {
173             float[] v = (float[]) value;
174             bv.put12('[', v.length);
175             for (int i = 0; i < v.length; i++) {
176                 bv.put12('F', cw.newFloat(v[i]).index);
177             }
178         } else if (value instanceof double[]) {
179             double[] v = (double[]) value;
180             bv.put12('[', v.length);
181             for (int i = 0; i < v.length; i++) {
182                 bv.put12('D', cw.newDouble(v[i]).index);
183             }
184         } else {
185             Item i = cw.newConstItem(value);
186             bv.put12(".s.IFJDCS".charAt(i.type), i.index);
187         }
188     }
189
190     public void visitEnum(
191         final String JavaDoc name,
192         final String JavaDoc desc,
193         final String JavaDoc value)
194     {
195         ++size;
196         if (named) {
197             bv.putShort(cw.newUTF8(name));
198         }
199         bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
200     }
201
202     public AnnotationVisitor visitAnnotation(
203         final String JavaDoc name,
204         final String JavaDoc desc)
205     {
206         ++size;
207         if (named) {
208             bv.putShort(cw.newUTF8(name));
209         }
210         // write tag and type, and reserve space for values count
211
bv.put12('@', cw.newUTF8(desc)).putShort(0);
212         return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
213     }
214
215     public AnnotationVisitor visitArray(final String JavaDoc name) {
216         ++size;
217         if (named) {
218             bv.putShort(cw.newUTF8(name));
219         }
220         // write tag, and reserve space for array size
221
bv.put12('[', 0);
222         return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
223     }
224
225     public void visitEnd() {
226         if (parent != null) {
227             byte[] data = parent.data;
228             data[offset] = (byte) (size >>> 8);
229             data[offset + 1] = (byte) size;
230         }
231     }
232
233     // ------------------------------------------------------------------------
234
// Utility methods
235
// ------------------------------------------------------------------------
236

237     /**
238      * Returns the size of this annotation writer list.
239      *
240      * @return the size of this annotation writer list.
241      */

242     int getSize() {
243         int size = 0;
244         AnnotationWriter aw = this;
245         while (aw != null) {
246             size += aw.bv.length;
247             aw = aw.next;
248         }
249         return size;
250     }
251
252     /**
253      * Puts the annotations of this annotation writer list into the given byte
254      * vector.
255      *
256      * @param out where the annotations must be put.
257      */

258     void put(final ByteVector out) {
259         int n = 0;
260         int size = 2;
261         AnnotationWriter aw = this;
262         AnnotationWriter last = null;
263         while (aw != null) {
264             ++n;
265             size += aw.bv.length;
266             aw.visitEnd(); // in case user forgot to call visitEnd
267
aw.prev = last;
268             last = aw;
269             aw = aw.next;
270         }
271         out.putInt(size);
272         out.putShort(n);
273         aw = last;
274         while (aw != null) {
275             out.putByteArray(aw.bv.data, 0, aw.bv.length);
276             aw = aw.prev;
277         }
278     }
279
280     /**
281      * Puts the given annotation lists into the given byte vector.
282      *
283      * @param panns an array of annotation writer lists.
284      * @param out where the annotations must be put.
285      */

286     static void put(final AnnotationWriter[] panns, final ByteVector out) {
287         int size = 1 + 2 * panns.length;
288         for (int i = 0; i < panns.length; ++i) {
289             size += panns[i] == null ? 0 : panns[i].getSize();
290         }
291         out.putInt(size).putByte(panns.length);
292         for (int i = 0; i < panns.length; ++i) {
293             AnnotationWriter aw = panns[i];
294             AnnotationWriter last = null;
295             int n = 0;
296             while (aw != null) {
297                 ++n;
298                 aw.visitEnd(); // in case user forgot to call visitEnd
299
aw.prev = last;
300                 last = aw;
301                 aw = aw.next;
302             }
303             out.putShort(n);
304             aw = last;
305             while (aw != null) {
306                 out.putByteArray(aw.bv.data, 0, aw.bv.length);
307                 aw = aw.prev;
308             }
309         }
310     }
311 }
312
Popular Tags