View Javadoc
1   /*
2    * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  /*
27   * This file is available under and governed by the GNU General Public
28   * License version 2 only, as published by the Free Software Foundation.
29   * However, the following notice accompanied the original version of this
30   * file:
31   *
32   * ASM: a very small and fast Java bytecode manipulation framework
33   * Copyright (c) 2000-2007 INRIA, France Telecom
34   * All rights reserved.
35   *
36   * Redistribution and use in source and binary forms, with or without
37   * modification, are permitted provided that the following conditions
38   * are met:
39   * 1. Redistributions of source code must retain the above copyright
40   *    notice, this list of conditions and the following disclaimer.
41   * 2. Redistributions in binary form must reproduce the above copyright
42   *    notice, this list of conditions and the following disclaimer in the
43   *    documentation and/or other materials provided with the distribution.
44   * 3. Neither the name of the copyright holders nor the names of its
45   *    contributors may be used to endorse or promote products derived from
46   *    this software without specific prior written permission.
47   *
48   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
52   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58   * THE POSSIBILITY OF SUCH DAMAGE.
59   */
60  package com.sun.xml.internal.ws.org.objectweb.asm;
61  
62  /**
63   * An {@link AnnotationVisitor} that generates annotations in bytecode form.
64   *
65   * @author Eric Bruneton
66   * @author Eugene Kuleshov
67   */
68  final class AnnotationWriter implements AnnotationVisitor {
69  
70      /**
71       * The class writer to which this annotation must be added.
72       */
73      private final ClassWriter cw;
74  
75      /**
76       * The number of values in this annotation.
77       */
78      private int size;
79  
80      /**
81       * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
82       * writers used for annotation default and annotation arrays use unnamed
83       * values.
84       */
85      private final boolean named;
86  
87      /**
88       * The annotation values in bytecode form. This byte vector only contains
89       * the values themselves, i.e. the number of values must be stored as a
90       * unsigned short just before these bytes.
91       */
92      private final ByteVector bv;
93  
94      /**
95       * The byte vector to be used to store the number of values of this
96       * annotation. See {@link #bv}.
97       */
98      private final ByteVector parent;
99  
100     /**
101      * Where the number of values of this annotation must be stored in
102      * {@link #parent}.
103      */
104     private final int offset;
105 
106     /**
107      * Next annotation writer. This field is used to store annotation lists.
108      */
109     AnnotationWriter next;
110 
111     /**
112      * Previous annotation writer. This field is used to store annotation lists.
113      */
114     AnnotationWriter prev;
115 
116     // ------------------------------------------------------------------------
117     // Constructor
118     // ------------------------------------------------------------------------
119 
120     /**
121      * Constructs a new {@link AnnotationWriter}.
122      *
123      * @param cw the class writer to which this annotation must be added.
124      * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
125      * @param bv where the annotation values must be stored.
126      * @param parent where the number of annotation values must be stored.
127      * @param offset where in <tt>parent</tt> the number of annotation values must
128      *      be stored.
129      */
130     AnnotationWriter(
131         final ClassWriter cw,
132         final boolean named,
133         final ByteVector bv,
134         final ByteVector parent,
135         final int offset)
136     {
137         this.cw = cw;
138         this.named = named;
139         this.bv = bv;
140         this.parent = parent;
141         this.offset = offset;
142     }
143 
144     // ------------------------------------------------------------------------
145     // Implementation of the AnnotationVisitor interface
146     // ------------------------------------------------------------------------
147 
148     public void visit(final String name, final Object value) {
149         ++size;
150         if (named) {
151             bv.putShort(cw.newUTF8(name));
152         }
153         if (value instanceof String) {
154             bv.put12('s', cw.newUTF8((String) value));
155         } else if (value instanceof Byte) {
156             bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
157         } else if (value instanceof Boolean) {
158             int v = ((Boolean) value).booleanValue() ? 1 : 0;
159             bv.put12('Z', cw.newInteger(v).index);
160         } else if (value instanceof Character) {
161             bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
162         } else if (value instanceof Short) {
163             bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
164         } else if (value instanceof Type) {
165             bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
166         } else if (value instanceof byte[]) {
167             byte[] v = (byte[]) value;
168             bv.put12('[', v.length);
169             for (int i = 0; i < v.length; i++) {
170                 bv.put12('B', cw.newInteger(v[i]).index);
171             }
172         } else if (value instanceof boolean[]) {
173             boolean[] v = (boolean[]) value;
174             bv.put12('[', v.length);
175             for (int i = 0; i < v.length; i++) {
176                 bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
177             }
178         } else if (value instanceof short[]) {
179             short[] v = (short[]) value;
180             bv.put12('[', v.length);
181             for (int i = 0; i < v.length; i++) {
182                 bv.put12('S', cw.newInteger(v[i]).index);
183             }
184         } else if (value instanceof char[]) {
185             char[] v = (char[]) value;
186             bv.put12('[', v.length);
187             for (int i = 0; i < v.length; i++) {
188                 bv.put12('C', cw.newInteger(v[i]).index);
189             }
190         } else if (value instanceof int[]) {
191             int[] v = (int[]) value;
192             bv.put12('[', v.length);
193             for (int i = 0; i < v.length; i++) {
194                 bv.put12('I', cw.newInteger(v[i]).index);
195             }
196         } else if (value instanceof long[]) {
197             long[] v = (long[]) value;
198             bv.put12('[', v.length);
199             for (int i = 0; i < v.length; i++) {
200                 bv.put12('J', cw.newLong(v[i]).index);
201             }
202         } else if (value instanceof float[]) {
203             float[] v = (float[]) value;
204             bv.put12('[', v.length);
205             for (int i = 0; i < v.length; i++) {
206                 bv.put12('F', cw.newFloat(v[i]).index);
207             }
208         } else if (value instanceof double[]) {
209             double[] v = (double[]) value;
210             bv.put12('[', v.length);
211             for (int i = 0; i < v.length; i++) {
212                 bv.put12('D', cw.newDouble(v[i]).index);
213             }
214         } else {
215             Item i = cw.newConstItem(value);
216             bv.put12(".s.IFJDCS".charAt(i.type), i.index);
217         }
218     }
219 
220     public void visitEnum(
221         final String name,
222         final String desc,
223         final String value)
224     {
225         ++size;
226         if (named) {
227             bv.putShort(cw.newUTF8(name));
228         }
229         bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
230     }
231 
232     public AnnotationVisitor visitAnnotation(
233         final String name,
234         final String desc)
235     {
236         ++size;
237         if (named) {
238             bv.putShort(cw.newUTF8(name));
239         }
240         // write tag and type, and reserve space for values count
241         bv.put12('@', cw.newUTF8(desc)).putShort(0);
242         return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
243     }
244 
245     public AnnotationVisitor visitArray(final String name) {
246         ++size;
247         if (named) {
248             bv.putShort(cw.newUTF8(name));
249         }
250         // write tag, and reserve space for array size
251         bv.put12('[', 0);
252         return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
253     }
254 
255     public void visitEnd() {
256         if (parent != null) {
257             byte[] data = parent.data;
258             data[offset] = (byte) (size >>> 8);
259             data[offset + 1] = (byte) size;
260         }
261     }
262 
263     // ------------------------------------------------------------------------
264     // Utility methods
265     // ------------------------------------------------------------------------
266 
267     /**
268      * Returns the size of this annotation writer list.
269      *
270      * @return the size of this annotation writer list.
271      */
272     int getSize() {
273         int size = 0;
274         AnnotationWriter aw = this;
275         while (aw != null) {
276             size += aw.bv.length;
277             aw = aw.next;
278         }
279         return size;
280     }
281 
282     /**
283      * Puts the annotations of this annotation writer list into the given byte
284      * vector.
285      *
286      * @param out where the annotations must be put.
287      */
288     void put(final ByteVector out) {
289         int n = 0;
290         int size = 2;
291         AnnotationWriter aw = this;
292         AnnotationWriter last = null;
293         while (aw != null) {
294             ++n;
295             size += aw.bv.length;
296             aw.visitEnd(); // in case user forgot to call visitEnd
297             aw.prev = last;
298             last = aw;
299             aw = aw.next;
300         }
301         out.putInt(size);
302         out.putShort(n);
303         aw = last;
304         while (aw != null) {
305             out.putByteArray(aw.bv.data, 0, aw.bv.length);
306             aw = aw.prev;
307         }
308     }
309 
310     /**
311      * Puts the given annotation lists into the given byte vector.
312      *
313      * @param panns an array of annotation writer lists.
314      * @param off index of the first annotation to be written.
315      * @param out where the annotations must be put.
316      */
317     static void put(
318         final AnnotationWriter[] panns,
319         final int off,
320         final ByteVector out)
321     {
322         int size = 1 + 2 * (panns.length - off);
323         for (int i = off; i < panns.length; ++i) {
324             size += panns[i] == null ? 0 : panns[i].getSize();
325         }
326         out.putInt(size).putByte(panns.length - off);
327         for (int i = off; i < panns.length; ++i) {
328             AnnotationWriter aw = panns[i];
329             AnnotationWriter last = null;
330             int n = 0;
331             while (aw != null) {
332                 ++n;
333                 aw.visitEnd(); // in case user forgot to call visitEnd
334                 aw.prev = last;
335                 last = aw;
336                 aw = aw.next;
337             }
338             out.putShort(n);
339             aw = last;
340             while (aw != null) {
341                 out.putByteArray(aw.bv.data, 0, aw.bv.length);
342                 aw = aw.prev;
343             }
344         }
345     }
346 }