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 org.objectweb.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 name, final Object value) { 119 ++size; 120 if (named) { 121 bv.putShort(cw.newUTF8(name)); 122 } 123 if (value instanceof String) { 124 bv.put12('s', cw.newUTF8((String) value)); 125 } else if (value instanceof Byte) { 126 bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); 127 } else if (value instanceof Boolean) { 128 int v = ((Boolean) value).booleanValue() ? 1 : 0; 129 bv.put12('Z', cw.newInteger(v).index); 130 } else if (value instanceof Character) { 131 bv.put12('C', cw.newInteger(((Character) value).charValue()).index); 132 } else if (value instanceof Short) { 133 bv.put12('S', 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( 191 final String name, 192 final String desc, 193 final String 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 name, 204 final String 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 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