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