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 net.sf.retrotranslator.runtime.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 the class writer to which this annotation must be added.
093: * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
094: * @param bv where the annotation values must be stored.
095: * @param parent where the number of annotation values must be stored.
096: * @param offset where in <tt>parent</tt> the number of annotation values must
097: * be stored.
098: */
099: AnnotationWriter(final ClassWriter cw, final boolean named,
100: final ByteVector bv, final ByteVector parent,
101: final int offset) {
102: this .cw = cw;
103: this .named = named;
104: this .bv = bv;
105: this .parent = parent;
106: this .offset = offset;
107: }
108:
109: // ------------------------------------------------------------------------
110: // Implementation of the AnnotationVisitor interface
111: // ------------------------------------------------------------------------
112:
113: public void visit(final String name, final Object value) {
114: ++size;
115: if (named) {
116: bv.putShort(cw.newUTF8(name));
117: }
118: if (value instanceof String) {
119: bv.put12('s', cw.newUTF8((String) value));
120: } else if (value instanceof Byte) {
121: bv.put12('B',
122: cw.newInteger(((Byte) value).byteValue()).index);
123: } else if (value instanceof Boolean) {
124: int v = ((Boolean) value).booleanValue() ? 1 : 0;
125: bv.put12('Z', cw.newInteger(v).index);
126: } else if (value instanceof Character) {
127: bv.put12('C', cw
128: .newInteger(((Character) value).charValue()).index);
129: } else if (value instanceof Short) {
130: bv.put12('S',
131: cw.newInteger(((Short) value).shortValue()).index);
132: } else if (value instanceof Type) {
133: bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
134: } else if (value instanceof byte[]) {
135: byte[] v = (byte[]) value;
136: bv.put12('[', v.length);
137: for (int i = 0; i < v.length; i++) {
138: bv.put12('B', cw.newInteger(v[i]).index);
139: }
140: } else if (value instanceof boolean[]) {
141: boolean[] v = (boolean[]) value;
142: bv.put12('[', v.length);
143: for (int i = 0; i < v.length; i++) {
144: bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
145: }
146: } else if (value instanceof short[]) {
147: short[] v = (short[]) value;
148: bv.put12('[', v.length);
149: for (int i = 0; i < v.length; i++) {
150: bv.put12('S', cw.newInteger(v[i]).index);
151: }
152: } else if (value instanceof char[]) {
153: char[] v = (char[]) value;
154: bv.put12('[', v.length);
155: for (int i = 0; i < v.length; i++) {
156: bv.put12('C', cw.newInteger(v[i]).index);
157: }
158: } else if (value instanceof int[]) {
159: int[] v = (int[]) value;
160: bv.put12('[', v.length);
161: for (int i = 0; i < v.length; i++) {
162: bv.put12('I', cw.newInteger(v[i]).index);
163: }
164: } else if (value instanceof long[]) {
165: long[] v = (long[]) value;
166: bv.put12('[', v.length);
167: for (int i = 0; i < v.length; i++) {
168: bv.put12('J', cw.newLong(v[i]).index);
169: }
170: } else if (value instanceof float[]) {
171: float[] v = (float[]) value;
172: bv.put12('[', v.length);
173: for (int i = 0; i < v.length; i++) {
174: bv.put12('F', cw.newFloat(v[i]).index);
175: }
176: } else if (value instanceof double[]) {
177: double[] v = (double[]) value;
178: bv.put12('[', v.length);
179: for (int i = 0; i < v.length; i++) {
180: bv.put12('D', cw.newDouble(v[i]).index);
181: }
182: } else {
183: Item i = cw.newConstItem(value);
184: bv.put12(".s.IFJDCS".charAt(i.type), i.index);
185: }
186: }
187:
188: public void visitEnum(final String name, final String desc,
189: final String value) {
190: ++size;
191: if (named) {
192: bv.putShort(cw.newUTF8(name));
193: }
194: bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
195: }
196:
197: public AnnotationVisitor visitAnnotation(final String name,
198: final String desc) {
199: ++size;
200: if (named) {
201: bv.putShort(cw.newUTF8(name));
202: }
203: // write tag and type, and reserve space for values count
204: bv.put12('@', cw.newUTF8(desc)).putShort(0);
205: return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
206: }
207:
208: public AnnotationVisitor visitArray(final String name) {
209: ++size;
210: if (named) {
211: bv.putShort(cw.newUTF8(name));
212: }
213: // write tag, and reserve space for array size
214: bv.put12('[', 0);
215: return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
216: }
217:
218: public void visitEnd() {
219: if (parent != null) {
220: byte[] data = parent.data;
221: data[offset] = (byte) (size >>> 8);
222: data[offset + 1] = (byte) size;
223: }
224: }
225:
226: // ------------------------------------------------------------------------
227: // Utility methods
228: // ------------------------------------------------------------------------
229:
230: /**
231: * Returns the size of this annotation writer list.
232: *
233: * @return the size of this annotation writer list.
234: */
235: int getSize() {
236: int size = 0;
237: AnnotationWriter aw = this ;
238: while (aw != null) {
239: size += aw.bv.length;
240: aw = aw.next;
241: }
242: return size;
243: }
244:
245: /**
246: * Puts the annotations of this annotation writer list into the given byte
247: * vector.
248: *
249: * @param out where the annotations must be put.
250: */
251: void put(final ByteVector out) {
252: int n = 0;
253: int size = 2;
254: AnnotationWriter aw = this ;
255: AnnotationWriter last = null;
256: while (aw != null) {
257: ++n;
258: size += aw.bv.length;
259: aw.visitEnd(); // in case user forgot to call visitEnd
260: aw.prev = last;
261: last = aw;
262: aw = aw.next;
263: }
264: out.putInt(size);
265: out.putShort(n);
266: aw = last;
267: while (aw != null) {
268: out.putByteArray(aw.bv.data, 0, aw.bv.length);
269: aw = aw.prev;
270: }
271: }
272:
273: /**
274: * Puts the given annotation lists into the given byte vector.
275: *
276: * @param panns an array of annotation writer lists.
277: * @param out where the annotations must be put.
278: */
279: static void put(final AnnotationWriter[] panns, final ByteVector out) {
280: int size = 1 + 2 * panns.length;
281: for (int i = 0; i < panns.length; ++i) {
282: size += panns[i] == null ? 0 : panns[i].getSize();
283: }
284: out.putInt(size).putByte(panns.length);
285: for (int i = 0; i < panns.length; ++i) {
286: AnnotationWriter aw = panns[i];
287: AnnotationWriter last = null;
288: int n = 0;
289: while (aw != null) {
290: ++n;
291: aw.visitEnd(); // in case user forgot to call visitEnd
292: aw.prev = last;
293: last = aw;
294: aw = aw.next;
295: }
296: out.putShort(n);
297: aw = last;
298: while (aw != null) {
299: out.putByteArray(aw.bv.data, 0, aw.bv.length);
300: aw = aw.prev;
301: }
302: }
303: }
304: }
|