67 /** 68 * A node that represents an annotationn. 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 an 85 * two elements String array (for enumeration values), a 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 88 * value 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 the class descriptor of the annotation class. 98 */ 99 public AnnotationNode(final String desc) { 100 this(Opcodes.ASM4, desc); 101 } 102 103 /** 104 * Constructs a new {@link AnnotationNode}. 105 * 106 * @param api the ASM API version implemented by this visitor. Must be one 107 * of {@link Opcodes#ASM4}. 108 * @param desc the class descriptor of the annotation class. 109 */ 110 public AnnotationNode(final int api, final String desc) { 111 super(api); 112 this.desc = desc; 113 } 114 115 /** 116 * Constructs a new {@link AnnotationNode} to visit an array value. 117 * 118 * @param values where the visited values must be stored. 119 */ 120 AnnotationNode(final List<Object> values) { 121 super(Opcodes.ASM4); 122 this.values = values; 123 } 124 125 // ------------------------------------------------------------------------ 126 // Implementation of the AnnotationVisitor abstract class 127 // ------------------------------------------------------------------------ 128 129 @Override 130 public void visit(final String name, final Object value) { 131 if (values == null) { 132 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 133 } 134 if (this.desc != null) { 135 values.add(name); 136 } 137 values.add(value); 138 } 139 140 @Override 141 public void visitEnum( 142 final String name, 143 final String desc, 144 final String value) 145 { 146 if (values == null) { 147 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 148 } 149 if (this.desc != null) { 150 values.add(name); 151 } 152 values.add(new String[] { desc, value }); 153 } 154 155 @Override 156 public AnnotationVisitor visitAnnotation( 157 final String name, 158 final String desc) 159 { 160 if (values == null) { 161 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 162 } 163 if (this.desc != null) { 164 values.add(name); 165 } 166 AnnotationNode annotation = new AnnotationNode(desc); 167 values.add(annotation); 168 return annotation; 169 } 170 171 @Override 172 public AnnotationVisitor visitArray(final String name) { 173 if (values == null) { 174 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 175 } 176 if (this.desc != null) { 177 values.add(name); 178 } 179 List<Object> array = new ArrayList<Object>(); 180 values.add(array); 181 return new AnnotationNode(array); 182 } 183 184 @Override 185 public void visitEnd() { 186 } 187 188 // ------------------------------------------------------------------------ 189 // Accept methods 190 // ------------------------------------------------------------------------ 191 192 /** 193 * Checks that this annotation node is compatible with the given ASM API 194 * version. This methods checks that this node, and all its nodes 195 * recursively, do not contain elements that were introduced in more recent 196 * versions of the ASM API than the given version. 197 * 198 * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}. 199 */ 200 public void check(final int api) { 201 // nothing to do 202 } 203 204 /** 205 * Makes the given visitor visit this annotation. 206 * 207 * @param av an annotation visitor. Maybe <tt>null</tt>. 208 */ 209 public void accept(final AnnotationVisitor av) { 210 if (av != null) { 211 if (values != null) { 212 for (int i = 0; i < values.size(); i += 2) { 213 String name = (String) values.get(i); 214 Object value = values.get(i + 1); 215 accept(av, name, value); 216 } 217 } 218 av.visitEnd(); 219 } 220 } 221 222 /** 223 * Makes the given visitor visit a given annotation value. 224 * 225 * @param av an annotation visitor. Maybe <tt>null</tt>. 226 * @param name the value name. 227 * @param value the actual value. 228 */ 229 static void accept( 230 final AnnotationVisitor av, 231 final String name, 232 final Object value) 233 { 234 if (av != null) { 235 if (value instanceof String[]) { 236 String[] typeconst = (String[]) value; 237 av.visitEnum(name, typeconst[0], typeconst[1]); 238 } else if (value instanceof AnnotationNode) { 239 AnnotationNode an = (AnnotationNode) value; 240 an.accept(av.visitAnnotation(name, an.desc)); 241 } else if (value instanceof List) { 242 AnnotationVisitor v = av.visitArray(name); 243 List<?> array = (List<?>) value; 244 for (int j = 0; j < array.size(); ++j) { 245 accept(v, null, array.get(j)); 246 } 247 v.visitEnd(); 248 } else { 249 av.visit(name, value); 250 } 251 } 252 } 253 } | 67 /** 68 * A node that represents an annotationn. 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 an 85 * two elements String array (for enumeration values), a 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 */ 100 public AnnotationNode(final String desc) { 101 this(Opcodes.ASM5, desc); 102 } 103 104 /** 105 * Constructs a new {@link AnnotationNode}. 106 * 107 * @param api 108 * the ASM API version implemented by this visitor. Must be one 109 * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 110 * @param desc 111 * the class descriptor of the annotation class. 112 */ 113 public AnnotationNode(final int api, final String desc) { 114 super(api); 115 this.desc = desc; 116 } 117 118 /** 119 * Constructs a new {@link AnnotationNode} to visit an array value. 120 * 121 * @param values 122 * where the visited values must be stored. 123 */ 124 AnnotationNode(final List<Object> values) { 125 super(Opcodes.ASM5); 126 this.values = values; 127 } 128 129 // ------------------------------------------------------------------------ 130 // Implementation of the AnnotationVisitor abstract class 131 // ------------------------------------------------------------------------ 132 133 @Override 134 public void visit(final String name, final Object value) { 135 if (values == null) { 136 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 137 } 138 if (this.desc != null) { 139 values.add(name); 140 } 141 values.add(value); 142 } 143 144 @Override 145 public void visitEnum(final String name, final String desc, 146 final String value) { 147 if (values == null) { 148 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 149 } 150 if (this.desc != null) { 151 values.add(name); 152 } 153 values.add(new String[] { desc, value }); 154 } 155 156 @Override 157 public AnnotationVisitor visitAnnotation(final String name, 158 final String desc) { 159 if (values == null) { 160 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 161 } 162 if (this.desc != null) { 163 values.add(name); 164 } 165 AnnotationNode annotation = new AnnotationNode(desc); 166 values.add(annotation); 167 return annotation; 168 } 169 170 @Override 171 public AnnotationVisitor visitArray(final String name) { 172 if (values == null) { 173 values = new ArrayList<Object>(this.desc != null ? 2 : 1); 174 } 175 if (this.desc != null) { 176 values.add(name); 177 } 178 List<Object> array = new ArrayList<Object>(); 179 values.add(array); 180 return new AnnotationNode(array); 181 } 182 183 @Override 184 public void visitEnd() { 185 } 186 187 // ------------------------------------------------------------------------ 188 // Accept methods 189 // ------------------------------------------------------------------------ 190 191 /** 192 * Checks that this annotation node is compatible with the given ASM API 193 * version. This methods checks that this node, and all its nodes 194 * recursively, do not contain elements that were introduced in more recent 195 * versions of the ASM API than the given version. 196 * 197 * @param api 198 * an ASM API version. Must be one of {@link Opcodes#ASM4} or 199 * {@link Opcodes#ASM5}. 200 */ 201 public void check(final int api) { 202 // nothing to do 203 } 204 205 /** 206 * Makes the given visitor visit this annotation. 207 * 208 * @param av 209 * an annotation visitor. Maybe <tt>null</tt>. 210 */ 211 public void accept(final AnnotationVisitor av) { 212 if (av != null) { 213 if (values != null) { 214 for (int i = 0; i < values.size(); i += 2) { 215 String name = (String) values.get(i); 216 Object value = values.get(i + 1); 217 accept(av, name, value); 218 } 219 } 220 av.visitEnd(); 221 } 222 } 223 224 /** 225 * Makes the given visitor visit a given annotation value. 226 * 227 * @param av 228 * an annotation visitor. Maybe <tt>null</tt>. 229 * @param name 230 * the value name. 231 * @param value 232 * the actual value. 233 */ 234 static void accept(final AnnotationVisitor av, final String name, 235 final Object value) { 236 if (av != null) { 237 if (value instanceof String[]) { 238 String[] typeconst = (String[]) value; 239 av.visitEnum(name, typeconst[0], typeconst[1]); 240 } else if (value instanceof AnnotationNode) { 241 AnnotationNode an = (AnnotationNode) value; 242 an.accept(av.visitAnnotation(name, an.desc)); 243 } else if (value instanceof List) { 244 AnnotationVisitor v = av.visitArray(name); 245 List<?> array = (List<?>) value; 246 for (int j = 0; j < array.size(); ++j) { 247 accept(v, null, array.get(j)); 248 } 249 v.visitEnd(); 250 } else { 251 av.visit(name, value); 252 } 253 } 254 } 255 } |