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) { 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 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 } | 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) { 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 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 } |