1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm; 60 61 /** 62 * An {@link AnnotationVisitor} that generates annotations in bytecode form. 63 * 64 * @author Eric Bruneton 65 * @author Eugene Kuleshov 66 */ 67 final class AnnotationWriter extends AnnotationVisitor { 68 69 /** 70 * The class writer to which this annotation must be added. 71 */ 72 private final ClassWriter cw; 73 74 /** 75 * The number of values in this annotation. 76 */ 77 private int size; 78 79 /** 80 * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation 81 * writers used for annotation default and annotation arrays use unnamed 82 * values. 83 */ 84 private final boolean named; 85 86 /** 87 * The annotation values in bytecode form. This byte vector only contains 88 * the values themselves, i.e. the number of values must be stored as a 89 * unsigned short just before these bytes. 90 */ 91 private final ByteVector bv; 92 93 /** 94 * The byte vector to be used to store the number of values of this 95 * annotation. See {@link #bv}. 96 */ 97 private final ByteVector parent; 98 99 /** 100 * Where the number of values of this annotation must be stored in 101 * {@link #parent}. 102 */ 103 private final int offset; 104 105 /** 106 * Next annotation writer. This field is used to store annotation lists. 107 */ 108 AnnotationWriter next; 109 110 /** 111 * Previous annotation writer. This field is used to store annotation lists. 112 */ 113 AnnotationWriter prev; 114 115 // ------------------------------------------------------------------------ 116 // Constructor 117 // ------------------------------------------------------------------------ 118 119 /** 120 * Constructs a new {@link AnnotationWriter}. 121 * 122 * @param cw 123 * the class writer to which this annotation must be added. 124 * @param named 125 * <tt>true<tt> if values are named, <tt>false</tt> otherwise. 126 * @param bv 127 * where the annotation values must be stored. 128 * @param parent 129 * where the number of annotation values must be stored. 130 * @param offset 131 * where in <tt>parent</tt> the number of annotation values must 132 * be stored. 133 */ 134 AnnotationWriter(final ClassWriter cw, final boolean named, 135 final ByteVector bv, final ByteVector parent, final int offset) { 136 super(Opcodes.ASM5); 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 abstract class 146 // ------------------------------------------------------------------------ 147 148 @Override 149 public void visit(final String name, final Object value) { 150 ++size; 151 if (named) { 152 bv.putShort(cw.newUTF8(name)); 153 } 154 if (value instanceof String) { 155 bv.put12('s', cw.newUTF8((String) value)); 156 } else if (value instanceof Byte) { 157 bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); 158 } else if (value instanceof Boolean) { 159 int v = ((Boolean) value).booleanValue() ? 1 : 0; 160 bv.put12('Z', cw.newInteger(v).index); 161 } else if (value instanceof Character) { 162 bv.put12('C', cw.newInteger(((Character) value).charValue()).index); 163 } else if (value instanceof Short) { 164 bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); 165 } else if (value instanceof Type) { 166 bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); 167 } else if (value instanceof byte[]) { 168 byte[] v = (byte[]) value; 169 bv.put12('[', v.length); 170 for (int i = 0; i < v.length; i++) { 171 bv.put12('B', cw.newInteger(v[i]).index); 172 } 173 } else if (value instanceof boolean[]) { 174 boolean[] v = (boolean[]) value; 175 bv.put12('[', v.length); 176 for (int i = 0; i < v.length; i++) { 177 bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); 178 } 179 } else if (value instanceof short[]) { 180 short[] v = (short[]) value; 181 bv.put12('[', v.length); 182 for (int i = 0; i < v.length; i++) { 183 bv.put12('S', cw.newInteger(v[i]).index); 184 } 185 } else if (value instanceof char[]) { 186 char[] v = (char[]) value; 187 bv.put12('[', v.length); 188 for (int i = 0; i < v.length; i++) { 189 bv.put12('C', cw.newInteger(v[i]).index); 190 } 191 } else if (value instanceof int[]) { 192 int[] v = (int[]) value; 193 bv.put12('[', v.length); 194 for (int i = 0; i < v.length; i++) { 195 bv.put12('I', cw.newInteger(v[i]).index); 196 } 197 } else if (value instanceof long[]) { 198 long[] v = (long[]) value; 199 bv.put12('[', v.length); 200 for (int i = 0; i < v.length; i++) { 201 bv.put12('J', cw.newLong(v[i]).index); 202 } 203 } else if (value instanceof float[]) { 204 float[] v = (float[]) value; 205 bv.put12('[', v.length); 206 for (int i = 0; i < v.length; i++) { 207 bv.put12('F', cw.newFloat(v[i]).index); 208 } 209 } else if (value instanceof double[]) { 210 double[] v = (double[]) value; 211 bv.put12('[', v.length); 212 for (int i = 0; i < v.length; i++) { 213 bv.put12('D', cw.newDouble(v[i]).index); 214 } 215 } else { 216 Item i = cw.newConstItem(value); 217 bv.put12(".s.IFJDCS".charAt(i.type), i.index); 218 } 219 } 220 221 @Override 222 public void visitEnum(final String name, final String desc, 223 final String value) { 224 ++size; 225 if (named) { 226 bv.putShort(cw.newUTF8(name)); 227 } 228 bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); 229 } 230 231 @Override 232 public AnnotationVisitor visitAnnotation(final String name, 233 final String desc) { 234 ++size; 235 if (named) { 236 bv.putShort(cw.newUTF8(name)); 237 } 238 // write tag and type, and reserve space for values count 239 bv.put12('@', cw.newUTF8(desc)).putShort(0); 240 return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); 241 } 242 243 @Override 244 public AnnotationVisitor visitArray(final String name) { 245 ++size; 246 if (named) { 247 bv.putShort(cw.newUTF8(name)); 248 } 249 // write tag, and reserve space for array size 250 bv.put12('[', 0); 251 return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); 252 } 253 254 @Override 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 287 * where the annotations must be put. 288 */ 289 void put(final ByteVector out) { 290 int n = 0; 291 int size = 2; 292 AnnotationWriter aw = this; 293 AnnotationWriter last = null; 294 while (aw != null) { 295 ++n; 296 size += aw.bv.length; 297 aw.visitEnd(); // in case user forgot to call visitEnd 298 aw.prev = last; 299 last = aw; 300 aw = aw.next; 301 } 302 out.putInt(size); 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 * Puts the given annotation lists into the given byte vector. 313 * 314 * @param panns 315 * an array of annotation writer lists. 316 * @param off 317 * index of the first annotation to be written. 318 * @param out 319 * where the annotations must be put. 320 */ 321 static void put(final AnnotationWriter[] panns, final int off, 322 final ByteVector out) { 323 int size = 1 + 2 * (panns.length - off); 324 for (int i = off; i < panns.length; ++i) { 325 size += panns[i] == null ? 0 : panns[i].getSize(); 326 } 327 out.putInt(size).putByte(panns.length - off); 328 for (int i = off; i < panns.length; ++i) { 329 AnnotationWriter aw = panns[i]; 330 AnnotationWriter last = null; 331 int n = 0; 332 while (aw != null) { 333 ++n; 334 aw.visitEnd(); // in case user forgot to call visitEnd 335 aw.prev = last; 336 last = aw; 337 aw = aw.next; 338 } 339 out.putShort(n); 340 aw = last; 341 while (aw != null) { 342 out.putByteArray(aw.bv.data, 0, aw.bv.length); 343 aw = aw.prev; 344 } 345 } 346 } 347 348 /** 349 * Puts the given type reference and type path into the given bytevector. 350 * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. 351 * 352 * @param typeRef 353 * a reference to the annotated type. See {@link TypeReference}. 354 * @param typePath 355 * the path to the annotated type argument, wildcard bound, array 356 * element type, or static inner type within 'typeRef'. May be 357 * <tt>null</tt> if the annotation targets 'typeRef' as a whole. 358 * @param out 359 * where the type reference and type path must be put. 360 */ 361 static void putTarget(int typeRef, TypePath typePath, ByteVector out) { 362 switch (typeRef >>> 24) { 363 case 0x00: // CLASS_TYPE_PARAMETER 364 case 0x01: // METHOD_TYPE_PARAMETER 365 case 0x16: // METHOD_FORMAL_PARAMETER 366 out.putShort(typeRef >>> 16); 367 break; 368 case 0x13: // FIELD 369 case 0x14: // METHOD_RETURN 370 case 0x15: // METHOD_RECEIVER 371 out.putByte(typeRef >>> 24); 372 break; 373 case 0x47: // CAST 374 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT 375 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT 376 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT 377 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT 378 out.putInt(typeRef); 379 break; 380 // case 0x10: // CLASS_EXTENDS 381 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND 382 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND 383 // case 0x17: // THROWS 384 // case 0x42: // EXCEPTION_PARAMETER 385 // case 0x43: // INSTANCEOF 386 // case 0x44: // NEW 387 // case 0x45: // CONSTRUCTOR_REFERENCE 388 // case 0x46: // METHOD_REFERENCE 389 default: 390 out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8); 391 break; 392 } 393 if (typePath == null) { 394 out.putByte(0); 395 } else { 396 int length = typePath.b[typePath.offset] * 2 + 1; 397 out.putByteArray(typePath.b, typePath.offset, length); 398 } 399 } 400 }