001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package org.ejb3unit.asm;
030:
031: /**
032: * An {@link AnnotationVisitor} that generates annotations in bytecode form.
033: *
034: * @author Eric Bruneton
035: * @author Eugene Kuleshov
036: */
037: final class AnnotationWriter implements AnnotationVisitor {
038:
039: /**
040: * The class writer to which this annotation must be added.
041: */
042: private final ClassWriter cw;
043:
044: /**
045: * The number of values in this annotation.
046: */
047: private int size;
048:
049: /**
050: * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
051: * writers used for annotation default and annotation arrays use unnamed
052: * values.
053: */
054: private final boolean named;
055:
056: /**
057: * The annotation values in bytecode form. This byte vector only contains
058: * the values themselves, i.e. the number of values must be stored as a
059: * unsigned short just before these bytes.
060: */
061: private final ByteVector bv;
062:
063: /**
064: * The byte vector to be used to store the number of values of this
065: * annotation. See {@link #bv}.
066: */
067: private final ByteVector parent;
068:
069: /**
070: * Where the number of values of this annotation must be stored in
071: * {@link #parent}.
072: */
073: private final int offset;
074:
075: /**
076: * Next annotation writer. This field is used to store annotation lists.
077: */
078: AnnotationWriter next;
079:
080: /**
081: * Previous annotation writer. This field is used to store annotation lists.
082: */
083: AnnotationWriter prev;
084:
085: // ------------------------------------------------------------------------
086: // Constructor
087: // ------------------------------------------------------------------------
088:
089: /**
090: * Constructs a new {@link AnnotationWriter}.
091: *
092: * @param cw
093: * the class writer to which this annotation must be added.
094: * @param named
095: * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
096: * @param bv where the annotation values must be stored.
097: * @param parent where the number of annotation values must be stored.
098: * @param offset where in <tt>parent</tt> the number of annotation values must
099: * be stored.
100: */
101: AnnotationWriter(final ClassWriter cw, final boolean named,
102: final ByteVector bv, final ByteVector parent,
103: final int offset) {
104: this .cw = cw;
105: this .named = named;
106: this .bv = bv;
107: this .parent = parent;
108: this .offset = offset;
109: }
110:
111: // ------------------------------------------------------------------------
112: // Implementation of the AnnotationVisitor interface
113: // ------------------------------------------------------------------------
114:
115: public void visit(final String name, final Object value) {
116: ++size;
117: if (named) {
118: bv.putShort(cw.newUTF8(name));
119: }
120: if (value instanceof String) {
121: bv.put12('s', cw.newUTF8((String) value));
122: } else if (value instanceof Byte) {
123: bv.put12('B',
124: cw.newInteger(((Byte) value).byteValue()).index);
125: } else if (value instanceof Boolean) {
126: int v = ((Boolean) value).booleanValue() ? 1 : 0;
127: bv.put12('Z', cw.newInteger(v).index);
128: } else if (value instanceof Character) {
129: bv.put12('C', cw
130: .newInteger(((Character) value).charValue()).index);
131: } else if (value instanceof Short) {
132: bv.put12('S',
133: cw.newInteger(((Short) 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(final String name, final String desc,
191: final String value) {
192: ++size;
193: if (named) {
194: bv.putShort(cw.newUTF8(name));
195: }
196: bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
197: }
198:
199: public AnnotationVisitor visitAnnotation(final String name,
200: final String desc) {
201: ++size;
202: if (named) {
203: bv.putShort(cw.newUTF8(name));
204: }
205: // write tag and type, and reserve space for values count
206: bv.put12('@', cw.newUTF8(desc)).putShort(0);
207: return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
208: }
209:
210: public AnnotationVisitor visitArray(final String name) {
211: ++size;
212: if (named) {
213: bv.putShort(cw.newUTF8(name));
214: }
215: // write tag, and reserve space for array size
216: bv.put12('[', 0);
217: return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
218: }
219:
220: public void visitEnd() {
221: if (parent != null) {
222: byte[] data = parent.data;
223: data[offset] = (byte) (size >>> 8);
224: data[offset + 1] = (byte) size;
225: }
226: }
227:
228: // ------------------------------------------------------------------------
229: // Utility methods
230: // ------------------------------------------------------------------------
231:
232: /**
233: * Returns the size of this annotation writer list.
234: *
235: * @return the size of this annotation writer list.
236: */
237: int getSize() {
238: int size = 0;
239: AnnotationWriter aw = this ;
240: while (aw != null) {
241: size += aw.bv.length;
242: aw = aw.next;
243: }
244: return size;
245: }
246:
247: /**
248: * Puts the annotations of this annotation writer list into the given byte
249: * vector.
250: *
251: * @param out
252: * where the annotations must be put.
253: */
254: void put(final ByteVector out) {
255: int n = 0;
256: int size = 2;
257: AnnotationWriter aw = this ;
258: AnnotationWriter last = null;
259: while (aw != null) {
260: ++n;
261: size += aw.bv.length;
262: aw.visitEnd(); // in case user forgot to call visitEnd
263: aw.prev = last;
264: last = aw;
265: aw = aw.next;
266: }
267: out.putInt(size);
268: out.putShort(n);
269: aw = last;
270: while (aw != null) {
271: out.putByteArray(aw.bv.data, 0, aw.bv.length);
272: aw = aw.prev;
273: }
274: }
275:
276: /**
277: * Puts the given annotation lists into the given byte vector.
278: *
279: * @param panns
280: * an array of annotation writer lists.
281: * @param out
282: * where the annotations must be put.
283: */
284: static void put(final AnnotationWriter[] panns, final ByteVector out) {
285: int size = 1 + 2 * panns.length;
286: for (int i = 0; i < panns.length; ++i) {
287: size += panns[i] == null ? 0 : panns[i].getSize();
288: }
289: out.putInt(size).putByte(panns.length);
290: for (int i = 0; i < panns.length; ++i) {
291: AnnotationWriter aw = panns[i];
292: AnnotationWriter last = null;
293: int n = 0;
294: while (aw != null) {
295: ++n;
296: aw.visitEnd(); // in case user forgot to call visitEnd
297: aw.prev = last;
298: last = aw;
299: aw = aw.next;
300: }
301: out.putShort(n);
302: aw = last;
303: while (aw != null) {
304: out.putByteArray(aw.bv.data, 0, aw.bv.length);
305: aw = aw.prev;
306: }
307: }
308: }
309: }
|