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.tree; 60 61 import java.util.ArrayList; 62 import java.util.List; 63 64 import jdk.internal.org.objectweb.asm.AnnotationVisitor; 65 import jdk.internal.org.objectweb.asm.Opcodes; 66 67 /** 68 * A node that represents an annotation. 69 * 70 * @author Eric Bruneton 71 */ 72 public class AnnotationNode extends AnnotationVisitor { 73 74 /** 75 * The class descriptor of the annotation class. 76 */ 77 public String desc; 78 79 /** 80 * The name value pairs of this annotation. Each name value pair is stored 81 * as two consecutive elements in the list. The name is a {@link String}, 82 * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, 83 * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, 84 * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a 85 * two elements String array (for enumeration values), an 86 * {@link AnnotationNode}, or a {@link List} of values of one of the 87 * preceding types. The list may be <tt>null</tt> if there is no name value 88 * pair. 89 */ 90 public List<Object> values; 91 92 /** 93 * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this 94 * constructor</i>. Instead, they must use the 95 * {@link #AnnotationNode(int, String)} version. 96 * 97 * @param desc 98 * the class descriptor of the annotation class. 99 * @throws IllegalStateException 100 * If a subclass calls this constructor. 101 */ 102 public AnnotationNode(final String desc) { 103 this(Opcodes.ASM6, desc); 104 if (getClass() != AnnotationNode.class) { 105 throw new IllegalStateException(); 106 } 107 } 108 109 /** 110 * Constructs a new {@link AnnotationNode}. 111 * 112 * @param api 113 * the ASM API version implemented by this visitor. Must be one 114 * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. 115 * @param desc 116 * the class descriptor of the annotation class. 117 */ 118 public AnnotationNode(final int api, final String desc) { 119 super(api); 120 this.desc = desc; 121 } 122 123 /** 124 * Constructs a new {@link AnnotationNode} to visit an array value. 125 * 126 * @param values 127 * where the visited values must be stored. 128 */ 129 AnnotationNode(final List<Object> values) { 130 super(Opcodes.ASM6); 131 this.values = values; 132 } 133 134 // ------------------------------------------------------------------------ 135 // Implementation of the AnnotationVisitor abstract class 136 // ------------------------------------------------------------------------ 137 138 @Override 139 public void visit(final String name, final Object value) { 140 if (values == null) { 141 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 142 } 143 if (this.desc != null) { 144 values.add(name); 145 } 146 if (value instanceof byte[]) { 147 byte[] v = (byte[]) value; 148 ArrayList<Byte> l = new ArrayList<Byte>(v.length); 149 for (byte b : v) { 150 l.add(b); 151 } 152 values.add(l); 153 } else if (value instanceof boolean[]) { 154 boolean[] v = (boolean[]) value; 155 ArrayList<Boolean> l = new ArrayList<Boolean>(v.length); 156 for (boolean b : v) { 157 l.add(b); 158 } 159 values.add(l); 160 } else if (value instanceof short[]) { 161 short[] v = (short[]) value; 162 ArrayList<Short> l = new ArrayList<Short>(v.length); 163 for (short s : v) { 164 l.add(s); 165 } 166 values.add(l); 167 } else if (value instanceof char[]) { 168 char[] v = (char[]) value; 169 ArrayList<Character> l = new ArrayList<Character>(v.length); 170 for (char c : v) { 171 l.add(c); 172 } 173 values.add(l); 174 } else if (value instanceof int[]) { 175 int[] v = (int[]) value; 176 ArrayList<Integer> l = new ArrayList<Integer>(v.length); 177 for (int i : v) { 178 l.add(i); 179 } 180 values.add(l); 181 } else if (value instanceof long[]) { 182 long[] v = (long[]) value; 183 ArrayList<Long> l = new ArrayList<Long>(v.length); 184 for (long lng : v) { 185 l.add(lng); 186 } 187 values.add(l); 188 } else if (value instanceof float[]) { 189 float[] v = (float[]) value; 190 ArrayList<Float> l = new ArrayList<Float>(v.length); 191 for (float f : v) { 192 l.add(f); 193 } 194 values.add(l); 195 } else if (value instanceof double[]) { 196 double[] v = (double[]) value; 197 ArrayList<Double> l = new ArrayList<Double>(v.length); 198 for (double d : v) { 199 l.add(d); 200 } 201 values.add(l); 202 } else { 203 values.add(value); 204 } 205 } 206 207 @Override 208 public void visitEnum(final String name, final String desc, 209 final String value) { 210 if (values == null) { 211 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 212 } 213 if (this.desc != null) { 214 values.add(name); 215 } 216 values.add(new String[] { desc, value }); 217 } 218 219 @Override 220 public AnnotationVisitor visitAnnotation(final String name, 221 final String desc) { 222 if (values == null) { 223 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 224 } 225 if (this.desc != null) { 226 values.add(name); 227 } 228 AnnotationNode annotation = new AnnotationNode(desc); 229 values.add(annotation); 230 return annotation; 231 } 232 233 @Override 234 public AnnotationVisitor visitArray(final String name) { 235 if (values == null) { 236 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 237 } 238 if (this.desc != null) { 239 values.add(name); 240 } 241 List<Object> array = new ArrayList<Object>(); 242 values.add(array); 243 return new AnnotationNode(array); 244 } 245 246 @Override 247 public void visitEnd() { 248 } 249 250 // ------------------------------------------------------------------------ 251 // Accept methods 252 // ------------------------------------------------------------------------ 253 254 /** 255 * Checks that this annotation node is compatible with the given ASM API 256 * version. This methods checks that this node, and all its nodes 257 * recursively, do not contain elements that were introduced in more recent 258 * versions of the ASM API than the given version. 259 * 260 * @param api 261 * an ASM API version. Must be one of {@link Opcodes#ASM4}, 262 * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. 263 */ 264 public void check(final int api) { 265 // nothing to do 266 } 267 268 /** 269 * Makes the given visitor visit this annotation. 270 * 271 * @param av 272 * an annotation visitor. Maybe <tt>null</tt>. 273 */ 274 public void accept(final AnnotationVisitor av) { 275 if (av != null) { 276 if (values != null) { 277 for (int i = 0; i < values.size(); i += 2) { 278 String name = (String) values.get(i); 279 Object value = values.get(i + 1); 280 accept(av, name, value); 281 } 282 } 283 av.visitEnd(); 284 } 285 } 286 287 /** 288 * Makes the given visitor visit a given annotation value. 289 * 290 * @param av 291 * an annotation visitor. Maybe <tt>null</tt>. 292 * @param name 293 * the value name. 294 * @param value 295 * the actual value. 296 */ 297 static void accept(final AnnotationVisitor av, final String name, 298 final Object value) { 299 if (av != null) { 300 if (value instanceof String[]) { 301 String[] typeconst = (String[]) value; 302 av.visitEnum(name, typeconst[0], typeconst[1]); 303 } else if (value instanceof AnnotationNode) { 304 AnnotationNode an = (AnnotationNode) value; 305 an.accept(av.visitAnnotation(name, an.desc)); 306 } else if (value instanceof List) { 307 AnnotationVisitor v = av.visitArray(name); 308 if (v != null) { 309 List<?> array = (List<?>) value; 310 for (int j = 0; j < array.size(); ++j) { 311 accept(v, null, array.get(j)); 312 } 313 v.visitEnd(); 314 } 315 } else { 316 av.visit(name, value); 317 } 318 } 319 } 320 }