31
31
import sun .reflect .annotation .AnnotationTypeMismatchExceptionProxy ;
32
32
import sun .reflect .annotation .EnumValue ;
33
33
import sun .reflect .annotation .EnumValueArray ;
34
+ import sun .reflect .annotation .TypeAnnotation ;
35
+ import sun .reflect .annotation .TypeAnnotationParser ;
34
36
import sun .reflect .annotation .TypeNotPresentExceptionProxy ;
35
37
36
38
import java .io .ByteArrayInputStream ;
@@ -184,14 +186,17 @@ public static int encodeThrowable(Throwable throwable, long buffer, int bufferSi
184
186
}
185
187
186
188
/**
187
- * Parses {@code rawAnnotations} into a list of {@link Annotation}s and then
188
- * serializes them to a byte array with {@link #encodeAnnotations(Collection)}.
189
+ * Parses {@code rawAnnotations} into a list of {@link Annotation}s (isTypeAnnotations == false)
190
+ * or {@link TypeAnnotation}s (isTypeAnnotations == true) and then
191
+ * serializes them to a byte array with {@link #encodeAnnotations(Collection)} or
192
+ * {@link #encodeTypeAnnotations(TypeAnnotation[])}.
189
193
*/
190
194
public static byte [] encodeAnnotations (byte [] rawAnnotations ,
195
+ boolean isTypeAnnotations ,
191
196
Class <?> declaringClass ,
192
197
ConstantPool cp ,
193
198
Class <? extends Annotation >[] selectAnnotationClasses ) {
194
- if (selectAnnotationClasses != null ) {
199
+ if (! isTypeAnnotations && selectAnnotationClasses != null ) {
195
200
if (selectAnnotationClasses .length == 0 ) {
196
201
throw new IllegalArgumentException ("annotation class selection must be null or non-empty" );
197
202
}
@@ -201,7 +206,11 @@ public static byte[] encodeAnnotations(byte[] rawAnnotations,
201
206
}
202
207
}
203
208
}
204
- return encodeAnnotations (AnnotationParser .parseSelectAnnotations (rawAnnotations , cp , declaringClass , false , selectAnnotationClasses ).values ());
209
+ if (isTypeAnnotations ) {
210
+ return encodeTypeAnnotations (TypeAnnotationParser .parseTypeAnnotations (rawAnnotations , cp , null , false , declaringClass ));
211
+ } else {
212
+ return encodeAnnotations (AnnotationParser .parseSelectAnnotations (rawAnnotations , cp , declaringClass , false , selectAnnotationClasses ).values ());
213
+ }
205
214
}
206
215
207
216
/**
@@ -399,18 +408,54 @@ private static void encodeAnnotation(DataOutputStream dos, Annotation a) throws
399
408
}
400
409
}
401
410
411
+ /**
412
+ * Encodes typeAnnotations to a byte array. The byte array can be decoded with {@link #decodeAnnotations(byte[], AnnotationDecoder)}.
413
+ */
414
+ public static byte [] encodeTypeAnnotations (TypeAnnotation [] typeAnnotations ) {
415
+ try {
416
+ ByteArrayOutputStream baos = new ByteArrayOutputStream (128 );
417
+ try (DataOutputStream dos = new DataOutputStream (baos )) {
418
+ writeLength (dos , typeAnnotations .length );
419
+ for (TypeAnnotation ta : typeAnnotations ) {
420
+ encodeTypeAnnotation (dos , ta );
421
+ }
422
+ }
423
+ return baos .toByteArray ();
424
+ } catch (Exception e ) {
425
+ throw new InternalError (e );
426
+ }
427
+ }
428
+
429
+ private static void encodeTypeAnnotation (DataOutputStream dos , TypeAnnotation ta ) throws Exception {
430
+ TypeAnnotation .TypeAnnotationTargetInfo ti = ta .getTargetInfo ();
431
+ TypeAnnotation .TypeAnnotationTarget target = ti .getTarget ();
432
+ dos .writeUTF (target .name ());
433
+ dos .writeInt (ti .getCount ());
434
+ dos .writeInt (ti .getSecondaryIndex ());
435
+ TypeAnnotation .LocationInfo li = ta .getLocationInfo ();
436
+ int depth = li .getDepth ();
437
+ dos .writeInt (depth );
438
+ for (int i = 0 ; i < depth ; i ++) {
439
+ TypeAnnotation .LocationInfo .Location loc = li .getLocationAt (i );
440
+ dos .write (loc .tag );
441
+ dos .writeShort (loc .index );
442
+ }
443
+ encodeAnnotation (dos , ta .getAnnotation ());
444
+ }
445
+
402
446
/**
403
447
* Helper for {@link #decodeAnnotations(byte[], AnnotationDecoder)} to convert a byte
404
448
* array (ostensibly produced by {@link VMSupport#encodeAnnotations}) into objects.
405
449
*
406
450
* @param <T> type to which a type name is {@linkplain #resolveType(String) resolved}
407
451
* @param <A> type of the object representing a decoded annotation
452
+ * @param <TA> type of the object representing a decoded type annotation
408
453
* @param <E> type of the object representing a decoded enum constant
409
454
* @param <EA> type of the object representing a decoded array of enum constants
410
455
* @param <MT> type of the object representing a missing type
411
456
* @param <ETM> type of the object representing a decoded element type mismatch
412
457
*/
413
- public interface AnnotationDecoder <T , A , E , EA , MT , ETM > {
458
+ public interface AnnotationDecoder <T , A , TA , E , EA , MT , ETM > {
414
459
/**
415
460
* Resolves a name in {@link Class#getName()} format to an object of type {@code T}.
416
461
*/
@@ -424,6 +469,11 @@ public interface AnnotationDecoder<T, A, E, EA, MT, ETM> {
424
469
*/
425
470
A newAnnotation (T type , Map .Entry <String , Object >[] elements );
426
471
472
+ /**
473
+ * Creates an object representing a decoded type annotation.
474
+ */
475
+ TA newTypeAnnotation (TypeAnnotation .TypeAnnotationTargetInfo targetInfo , TypeAnnotation .LocationInfo locationInfo , A annotation );
476
+
427
477
/**
428
478
* Creates an object representing a decoded enum.
429
479
*
@@ -468,7 +518,7 @@ public interface AnnotationDecoder<T, A, E, EA, MT, ETM> {
468
518
* @return an immutable list of {@code A} objects
469
519
*/
470
520
@ SuppressWarnings ("unchecked" )
471
- public static <T , A , E , EA , MT , ETM > List <A > decodeAnnotations (byte [] encoded , AnnotationDecoder <T , A , E , EA , MT , ETM > decoder ) {
521
+ public static <T , A , TA , E , EA , MT , ETM > List <A > decodeAnnotations (byte [] encoded , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) {
472
522
try {
473
523
ByteArrayInputStream bais = new ByteArrayInputStream (encoded );
474
524
DataInputStream dis = new DataInputStream (bais );
@@ -479,7 +529,7 @@ public static <T, A, E, EA, MT, ETM> List<A> decodeAnnotations(byte[] encoded, A
479
529
}
480
530
481
531
@ SuppressWarnings ({"rawtypes" , "unchecked" })
482
- private static <T , A , E , EA , MT , ETM > A decodeAnnotation (DataInputStream dis , AnnotationDecoder <T , A , E , EA , MT , ETM > decoder ) throws IOException {
532
+ private static <T , A , TA , E , EA , MT , ETM > A decodeAnnotation (DataInputStream dis , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) throws IOException {
483
533
String typeName = dis .readUTF ();
484
534
T type = decoder .resolveType (typeName );
485
535
int n = readLength (dis );
@@ -508,12 +558,13 @@ private static <T, A, E, EA, MT, ETM> A decodeAnnotation(DataInputStream dis, An
508
558
}
509
559
return decoder .newAnnotation (type , (Map .Entry <String , Object >[]) elements );
510
560
}
561
+
511
562
@ FunctionalInterface
512
563
interface IOReader {
513
564
Object read () throws IOException ;
514
565
}
515
566
516
- private static <T , A , E , EA , MT , ETM > Object decodeArray (DataInputStream dis , AnnotationDecoder <T , A , E , EA , MT , ETM > decoder ) throws IOException {
567
+ private static <T , A , TA , E , EA , MT , ETM > Object decodeArray (DataInputStream dis , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) throws IOException {
517
568
byte componentTag = dis .readByte ();
518
569
return switch (componentTag ) {
519
570
case 'B' -> readArray (dis , dis ::readByte );
@@ -540,7 +591,7 @@ private static <T, A, E, EA, MT, ETM> Object decodeArray(DataInputStream dis, An
540
591
* returns it as an object of type {@code E}.
541
592
*/
542
593
@ SuppressWarnings ("unchecked" )
543
- private static <T , A , E , EA , MT , ETM > EA readEnumArray (DataInputStream dis , AnnotationDecoder <T , A , E , EA , MT , ETM > decoder , T enumType ) throws IOException {
594
+ private static <T , A , TA , E , EA , MT , ETM > EA readEnumArray (DataInputStream dis , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder , T enumType ) throws IOException {
544
595
List <String > names = (List <String >) readArray (dis , dis ::readUTF );
545
596
return decoder .newEnumArray (enumType , names );
546
597
}
@@ -549,7 +600,7 @@ private static <T, A, E, EA, MT, ETM> EA readEnumArray(DataInputStream dis, Anno
549
600
* Reads a class encoded at the current read position of {@code dis} and
550
601
* returns it as an object of type {@code T}.
551
602
*/
552
- private static <T , A , E , EA , MT , ETM > T readClass (DataInputStream dis , AnnotationDecoder <T , A , E , EA , MT , ETM > decoder ) throws IOException {
603
+ private static <T , A , TA , E , EA , MT , ETM > T readClass (DataInputStream dis , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) throws IOException {
553
604
return decoder .resolveType (dis .readUTF ());
554
605
}
555
606
@@ -594,4 +645,45 @@ private static int readLength(DataInputStream dis) throws IOException {
594
645
}
595
646
return length ;
596
647
}
648
+
649
+ /**
650
+ * Decodes type annotations serialized in {@code encoded} to objects.
651
+ *
652
+ * @param <T> type to which a type name is resolved
653
+ * @param <A> type of the object representing a decoded annotation
654
+ * @param <E> type of the object representing a decoded enum constant
655
+ * @param <MT> type of the object representing a missing type
656
+ * @param <ETM> type of the object representing a decoded element type mismatch
657
+ * @return an immutable list of {@code A} objects
658
+ */
659
+ @ SuppressWarnings ("unchecked" )
660
+ public static <T , A , TA , E , EA , MT , ETM > List <TA > decodeTypeAnnotations (byte [] encoded , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) {
661
+ try {
662
+ ByteArrayInputStream bais = new ByteArrayInputStream (encoded );
663
+ DataInputStream dis = new DataInputStream (bais );
664
+ return (List <TA >) readArray (dis , () -> decodeTypeAnnotation (dis , decoder ));
665
+ } catch (Exception e ) {
666
+ throw new InternalError (e );
667
+ }
668
+ }
669
+
670
+ private static <T , A , TA , E , EA , MT , ETM > TA decodeTypeAnnotation (DataInputStream dis , AnnotationDecoder <T , A , TA , E , EA , MT , ETM > decoder ) throws IOException {
671
+ TypeAnnotation .TypeAnnotationTarget target = TypeAnnotation .TypeAnnotationTarget .valueOf (dis .readUTF ());
672
+ int count = dis .readInt ();
673
+ int secondaryIndex = dis .readInt ();
674
+ TypeAnnotation .TypeAnnotationTargetInfo ti = new TypeAnnotation .TypeAnnotationTargetInfo (target , count , secondaryIndex );
675
+ int depth = dis .readInt ();
676
+ TypeAnnotation .LocationInfo li ;
677
+ if (depth == 0 ) {
678
+ li = TypeAnnotation .LocationInfo .BASE_LOCATION ;
679
+ } else {
680
+ TypeAnnotation .LocationInfo .Location [] locs = new TypeAnnotation .LocationInfo .Location [depth ];
681
+ for (int i = 0 ; i != depth ; i ++) {
682
+ locs [i ] = new TypeAnnotation .LocationInfo .Location (dis .readByte (), dis .readShort ());
683
+ }
684
+ li = new TypeAnnotation .LocationInfo (depth , locs );
685
+ }
686
+ A annotation = decodeAnnotation (dis , decoder );
687
+ return decoder .newTypeAnnotation (ti , li , annotation );
688
+ }
597
689
}
0 commit comments