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 the class writer to which this annotation must be added. 123 * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise. 124 * @param bv where the annotation values must be stored. 125 * @param parent where the number of annotation values must be stored. 126 * @param offset where in <tt>parent</tt> the number of annotation values must 127 * be stored. 128 */ 129 AnnotationWriter( 130 final ClassWriter cw, 131 final boolean named, 132 final ByteVector bv, 133 final ByteVector parent, 134 final int offset) 135 { 136 super(Opcodes.ASM4); 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( 223 final String name, 224 final String desc, 225 final String value) 226 { 227 ++size; 228 if (named) { 229 bv.putShort(cw.newUTF8(name)); 230 } 231 bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); 232 } 233 234 @Override 235 public AnnotationVisitor visitAnnotation( 236 final String name, 237 final String desc) 238 { 239 ++size; 240 if (named) { 241 bv.putShort(cw.newUTF8(name)); 242 } 243 // write tag and type, and reserve space for values count 244 bv.put12('@', cw.newUTF8(desc)).putShort(0); 245 return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); 246 } 247 248 @Override 249 public AnnotationVisitor visitArray(final String name) { 250 ++size; 251 if (named) { 252 bv.putShort(cw.newUTF8(name)); 253 } 254 // write tag, and reserve space for array size 255 bv.put12('[', 0); 256 return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); 257 } 258 259 @Override 260 public void visitEnd() { 261 if (parent != null) { 262 byte[] data = parent.data; 263 data[offset] = (byte) (size >>> 8); 264 data[offset + 1] = (byte) size; 265 } 266 } 267 268 // ------------------------------------------------------------------------ 269 // Utility methods 270 // ------------------------------------------------------------------------ 271 272 /** 273 * Returns the size of this annotation writer list. 274 * 275 * @return the size of this annotation writer list. 276 */ 277 int getSize() { 278 int size = 0; 279 AnnotationWriter aw = this; 280 while (aw != null) { 281 size += aw.bv.length; 282 aw = aw.next; 283 } 284 return size; 285 } 286 287 /** 288 * Puts the annotations of this annotation writer list into the given byte 289 * vector. 290 * 291 * @param out where the annotations must be put. 292 */ 293 void put(final ByteVector out) { 294 int n = 0; 295 int size = 2; 296 AnnotationWriter aw = this; 297 AnnotationWriter last = null; 298 while (aw != null) { 299 ++n; 300 size += aw.bv.length; 301 aw.visitEnd(); // in case user forgot to call visitEnd 302 aw.prev = last; 303 last = aw; 304 aw = aw.next; 305 } 306 out.putInt(size); 307 out.putShort(n); 308 aw = last; 309 while (aw != null) { 310 out.putByteArray(aw.bv.data, 0, aw.bv.length); 311 aw = aw.prev; 312 } 313 } 314 315 /** 316 * Puts the given annotation lists into the given byte vector. 317 * 318 * @param panns an array of annotation writer lists. 319 * @param off index of the first annotation to be written. 320 * @param out where the annotations must be put. 321 */ 322 static void put( 323 final AnnotationWriter[] panns, 324 final int off, 325 final ByteVector out) 326 { 327 int size = 1 + 2 * (panns.length - off); 328 for (int i = off; i < panns.length; ++i) { 329 size += panns[i] == null ? 0 : panns[i].getSize(); 330 } 331 out.putInt(size).putByte(panns.length - off); 332 for (int i = off; i < panns.length; ++i) { 333 AnnotationWriter aw = panns[i]; 334 AnnotationWriter last = null; 335 int n = 0; 336 while (aw != null) { 337 ++n; 338 aw.visitEnd(); // in case user forgot to call visitEnd 339 aw.prev = last; 340 last = aw; 341 aw = aw.next; 342 } 343 out.putShort(n); 344 aw = last; 345 while (aw != null) { 346 out.putByteArray(aw.bv.data, 0, aw.bv.length); 347 aw = aw.prev; 348 } 349 } 350 } 351 }