History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/reflect/annotation/AnnotationParser.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/reflect/annotation/AnnotationParser.java+805−0
@@ -0,0 +1,805 @@
1/*
2 * Copyright (c) 2003, 2005, 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
26package sun.reflect.annotation;
27
28import java.lang.annotation.*;
29import java.util.*;
30import java.nio.ByteBuffer;
31import java.nio.BufferUnderflowException;
32import java.lang.reflect.*;
33import sun.reflect.ConstantPool;
34
35import sun.reflect.generics.parser.SignatureParser;
36import sun.reflect.generics.tree.TypeSignature;
37import sun.reflect.generics.factory.GenericsFactory;
38import sun.reflect.generics.factory.CoreReflectionFactory;
39import sun.reflect.generics.visitor.Reifier;
40import sun.reflect.generics.scope.ClassScope;
41
42/**
43 * Parser for Java programming language annotations. Translates
44 * annotation byte streams emitted by compiler into annotation objects.
45 *
46 * @author Josh Bloch
47 * @since 1.5
48 */
49public class AnnotationParser {
50 /**
51 * Parses the annotations described by the specified byte array.
52 * resolving constant references in the specified constant pool.
53 * The array must contain an array of annotations as described
54 * in the RuntimeVisibleAnnotations_attribute:
55 *
56 * u2 num_annotations;
57 * annotation annotations[num_annotations];
58 *
59 * @throws AnnotationFormatError if an annotation is found to be
60 * malformed.
61 */
62 public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
63 byte[] rawAnnotations,
64 ConstantPool constPool,
65 Class<?> container) {
66 if (rawAnnotations == null)
67 return Collections.emptyMap();
68
69 try {
70 return parseAnnotations2(rawAnnotations, constPool, container);
71 } catch(BufferUnderflowException e) {
72 throw new AnnotationFormatError("Unexpected end of annotations.");
73 } catch(IllegalArgumentException e) {
74 // Type mismatch in constant pool
75 throw new AnnotationFormatError(e);
76 }
77 }
78
79 private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
80 byte[] rawAnnotations,
81 ConstantPool constPool,
82 Class<?> container) {
83 Map<Class<? extends Annotation>, Annotation> result =
84 new LinkedHashMap<Class<? extends Annotation>, Annotation>();
85 ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
86 int numAnnotations = buf.getShort() & 0xFFFF;
87 for (int i = 0; i < numAnnotations; i++) {
88 Annotation a = parseAnnotation(buf, constPool, container, false);
89 if (a != null) {
90 Class<? extends Annotation> klass = a.annotationType();
91 AnnotationType type = AnnotationType.getInstance(klass);
92 if (type.retention() == RetentionPolicy.RUNTIME)
93 if (result.put(klass, a) != null)
94 throw new AnnotationFormatError(
95 "Duplicate annotation for class: "+klass+": " + a);
96 }
97 }
98 return result;
99 }
100
101 /**
102 * Parses the parameter annotations described by the specified byte array.
103 * resolving constant references in the specified constant pool.
104 * The array must contain an array of annotations as described
105 * in the RuntimeVisibleParameterAnnotations_attribute:
106 *
107 * u1 num_parameters;
108 * {
109 * u2 num_annotations;
110 * annotation annotations[num_annotations];
111 * } parameter_annotations[num_parameters];
112 *
113 * Unlike parseAnnotations, rawAnnotations must not be null!
114 * A null value must be handled by the caller. This is so because
115 * we cannot determine the number of parameters if rawAnnotations
116 * is null. Also, the caller should check that the number
117 * of parameters indicated by the return value of this method
118 * matches the actual number of method parameters. A mismatch
119 * indicates that an AnnotationFormatError should be thrown.
120 *
121 * @throws AnnotationFormatError if an annotation is found to be
122 * malformed.
123 */
124 public static Annotation[][] parseParameterAnnotations(
125 byte[] rawAnnotations,
126 ConstantPool constPool,
127 Class<?> container) {
128 try {
129 return parseParameterAnnotations2(rawAnnotations, constPool, container);
130 } catch(BufferUnderflowException e) {
131 throw new AnnotationFormatError(
132 "Unexpected end of parameter annotations.");
133 } catch(IllegalArgumentException e) {
134 // Type mismatch in constant pool
135 throw new AnnotationFormatError(e);
136 }
137 }
138
139 private static Annotation[][] parseParameterAnnotations2(
140 byte[] rawAnnotations,
141 ConstantPool constPool,
142 Class<?> container) {
143 ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
144 int numParameters = buf.get() & 0xFF;
145 Annotation[][] result = new Annotation[numParameters][];
146
147 for (int i = 0; i < numParameters; i++) {
148 int numAnnotations = buf.getShort() & 0xFFFF;
149 List<Annotation> annotations =
150 new ArrayList<Annotation>(numAnnotations);
151 for (int j = 0; j < numAnnotations; j++) {
152 Annotation a = parseAnnotation(buf, constPool, container, false);
153 if (a != null) {
154 AnnotationType type = AnnotationType.getInstance(
155 a.annotationType());
156 if (type.retention() == RetentionPolicy.RUNTIME)
157 annotations.add(a);
158 }
159 }
160 result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
161 }
162 return result;
163 }
164
165 private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
166 new Annotation[0];
167
168 /**
169 * Parses the annotation at the current position in the specified
170 * byte buffer, resolving constant references in the specified constant
171 * pool. The cursor of the byte buffer must point to an "annotation
172 * structure" as described in the RuntimeVisibleAnnotations_attribute:
173 *
174 * annotation {
175 * u2 type_index;
176 * u2 num_member_value_pairs;
177 * { u2 member_name_index;
178 * member_value value;
179 * } member_value_pairs[num_member_value_pairs];
180 * }
181 * }
182 *
183 * Returns the annotation, or null if the annotation's type cannot
184 * be found by the VM, or is not a valid annotation type.
185 *
186 * @param exceptionOnMissingAnnotationClass if true, throw
187 * TypeNotPresentException if a referenced annotation type is not
188 * available at runtime
189 */
190 private static Annotation parseAnnotation(ByteBuffer buf,
191 ConstantPool constPool,
192 Class<?> container,
193 boolean exceptionOnMissingAnnotationClass) {
194 int typeIndex = buf.getShort() & 0xFFFF;
195 Class<? extends Annotation> annotationClass = null;
196 String sig = "[unknown]";
197 try {
198 try {
199 sig = constPool.getUTF8At(typeIndex);
200 annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
201 } catch (IllegalArgumentException ex) {
202 // support obsolete early jsr175 format class files
203 annotationClass = constPool.getClassAt(typeIndex);
204 }
205 } catch (NoClassDefFoundError e) {
206 if (exceptionOnMissingAnnotationClass)
207 // note: at this point sig is "[unknown]" or VM-style
208 // name instead of a binary name
209 throw new TypeNotPresentException(sig, e);
210 skipAnnotation(buf, false);
211 return null;
212 }
213 catch (TypeNotPresentException e) {
214 if (exceptionOnMissingAnnotationClass)
215 throw e;
216 skipAnnotation(buf, false);
217 return null;
218 }
219 AnnotationType type = null;
220 try {
221 type = AnnotationType.getInstance(annotationClass);
222 } catch (IllegalArgumentException e) {
223 skipAnnotation(buf, false);
224 return null;
225 }
226
227 Map<String, Class<?>> memberTypes = type.memberTypes();
228 Map<String, Object> memberValues =
229 new LinkedHashMap<String, Object>(type.memberDefaults());
230
231 int numMembers = buf.getShort() & 0xFFFF;
232 for (int i = 0; i < numMembers; i++) {
233 int memberNameIndex = buf.getShort() & 0xFFFF;
234 String memberName = constPool.getUTF8At(memberNameIndex);
235 Class<?> memberType = memberTypes.get(memberName);
236
237 if (memberType == null) {
238 // Member is no longer present in annotation type; ignore it
239 skipMemberValue(buf);
240 } else {
241 Object value = parseMemberValue(memberType, buf, constPool, container);
242 if (value instanceof AnnotationTypeMismatchExceptionProxy)
243 ((AnnotationTypeMismatchExceptionProxy) value).
244 setMember(type.members().get(memberName));
245 memberValues.put(memberName, value);
246 }
247 }
248 return annotationForMap(annotationClass, memberValues);
249 }
250
251 /**
252 * Returns an annotation of the given type backed by the given
253 * member -> value map.
254 */
255 public static Annotation annotationForMap(
256 Class<? extends Annotation> type, Map<String, Object> memberValues)
257 {
258 return (Annotation) Proxy.newProxyInstance(
259 type.getClassLoader(), new Class[] { type },
260 new AnnotationInvocationHandler(type, memberValues));
261 }
262
263 /**
264 * Parses the annotation member value at the current position in the
265 * specified byte buffer, resolving constant references in the specified
266 * constant pool. The cursor of the byte buffer must point to a
267 * "member_value structure" as described in the
268 * RuntimeVisibleAnnotations_attribute:
269 *
270 * member_value {
271 * u1 tag;
272 * union {
273 * u2 const_value_index;
274 * {
275 * u2 type_name_index;
276 * u2 const_name_index;
277 * } enum_const_value;
278 * u2 class_info_index;
279 * annotation annotation_value;
280 * {
281 * u2 num_values;
282 * member_value values[num_values];
283 * } array_value;
284 * } value;
285 * }
286 *
287 * The member must be of the indicated type. If it is not, this
288 * method returns an AnnotationTypeMismatchExceptionProxy.
289 */
290 public static Object parseMemberValue(Class<?> memberType,
291 ByteBuffer buf,
292 ConstantPool constPool,
293 Class<?> container) {
294 Object result = null;
295 int tag = buf.get();
296 switch(tag) {
297 case 'e':
298 return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
299 case 'c':
300 result = parseClassValue(buf, constPool, container);
301 break;
302 case '@':
303 result = parseAnnotation(buf, constPool, container, true);
304 break;
305 case '[':
306 return parseArray(memberType, buf, constPool, container);
307 default:
308 result = parseConst(tag, buf, constPool);
309 }
310
311 if (!(result instanceof ExceptionProxy) &&
312 !memberType.isInstance(result))
313 result = new AnnotationTypeMismatchExceptionProxy(
314 result.getClass() + "[" + result + "]");
315 return result;
316 }
317
318 /**
319 * Parses the primitive or String annotation member value indicated by
320 * the specified tag byte at the current position in the specified byte
321 * buffer, resolving constant reference in the specified constant pool.
322 * The cursor of the byte buffer must point to an annotation member value
323 * of the type indicated by the specified tag, as described in the
324 * RuntimeVisibleAnnotations_attribute:
325 *
326 * u2 const_value_index;
327 */
328 private static Object parseConst(int tag,
329 ByteBuffer buf, ConstantPool constPool) {
330 int constIndex = buf.getShort() & 0xFFFF;
331 switch(tag) {
332 case 'B':
333 return Byte.valueOf((byte) constPool.getIntAt(constIndex));
334 case 'C':
335 return Character.valueOf((char) constPool.getIntAt(constIndex));
336 case 'D':
337 return Double.valueOf(constPool.getDoubleAt(constIndex));
338 case 'F':
339 return Float.valueOf(constPool.getFloatAt(constIndex));
340 case 'I':
341 return Integer.valueOf(constPool.getIntAt(constIndex));
342 case 'J':
343 return Long.valueOf(constPool.getLongAt(constIndex));
344 case 'S':
345 return Short.valueOf((short) constPool.getIntAt(constIndex));
346 case 'Z':
347 return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
348 case 's':
349 return constPool.getUTF8At(constIndex);
350 default:
351 throw new AnnotationFormatError(
352 "Invalid member-value tag in annotation: " + tag);
353 }
354 }
355
356 /**
357 * Parses the Class member value at the current position in the
358 * specified byte buffer, resolving constant references in the specified
359 * constant pool. The cursor of the byte buffer must point to a "class
360 * info index" as described in the RuntimeVisibleAnnotations_attribute:
361 *
362 * u2 class_info_index;
363 */
364 private static Object parseClassValue(ByteBuffer buf,
365 ConstantPool constPool,
366 Class<?> container) {
367 int classIndex = buf.getShort() & 0xFFFF;
368 try {
369 try {
370 String sig = constPool.getUTF8At(classIndex);
371 return parseSig(sig, container);
372 } catch (IllegalArgumentException ex) {
373 // support obsolete early jsr175 format class files
374 return constPool.getClassAt(classIndex);
375 }
376 } catch (NoClassDefFoundError e) {
377 return new TypeNotPresentExceptionProxy("[unknown]", e);
378 }
379 catch (TypeNotPresentException e) {
380 return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
381 }
382 }
383
384 private static Class<?> parseSig(String sig, Class<?> container) {
385 if (sig.equals("V")) return void.class;
386 SignatureParser parser = SignatureParser.make();
387 TypeSignature typeSig = parser.parseTypeSig(sig);
388 GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container));
389 Reifier reify = Reifier.make(factory);
390 typeSig.accept(reify);
391 Type result = reify.getResult();
392 return toClass(result);
393 }
394 static Class<?> toClass(Type o) {
395 if (o instanceof GenericArrayType)
396 return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
397 0)
398 .getClass();
399 return (Class)o;
400 }
401
402 /**
403 * Parses the enum constant member value at the current position in the
404 * specified byte buffer, resolving constant references in the specified
405 * constant pool. The cursor of the byte buffer must point to a
406 * "enum_const_value structure" as described in the
407 * RuntimeVisibleAnnotations_attribute:
408 *
409 * {
410 * u2 type_name_index;
411 * u2 const_name_index;
412 * } enum_const_value;
413 */
414 private static Object parseEnumValue(Class<? extends Enum> enumType, ByteBuffer buf,
415 ConstantPool constPool,
416 Class<?> container) {
417 int typeNameIndex = buf.getShort() & 0xFFFF;
418 String typeName = constPool.getUTF8At(typeNameIndex);
419 int constNameIndex = buf.getShort() & 0xFFFF;
420 String constName = constPool.getUTF8At(constNameIndex);
421
422 if (!typeName.endsWith(";")) {
423 // support now-obsolete early jsr175-format class files.
424 if (!enumType.getName().equals(typeName))
425 return new AnnotationTypeMismatchExceptionProxy(
426 typeName + "." + constName);
427 } else if (enumType != parseSig(typeName, container)) {
428 return new AnnotationTypeMismatchExceptionProxy(
429 typeName + "." + constName);
430 }
431
432 try {
433 return Enum.valueOf(enumType, constName);
434 } catch(IllegalArgumentException e) {
435 return new EnumConstantNotPresentExceptionProxy(
436 (Class<? extends Enum>)enumType, constName);
437 }
438 }
439
440 /**
441 * Parses the array value at the current position in the specified byte
442 * buffer, resolving constant references in the specified constant pool.
443 * The cursor of the byte buffer must point to an array value struct
444 * as specified in the RuntimeVisibleAnnotations_attribute:
445 *
446 * {
447 * u2 num_values;
448 * member_value values[num_values];
449 * } array_value;
450 *
451 * If the array values do not match arrayType, an
452 * AnnotationTypeMismatchExceptionProxy will be returned.
453 */
454 private static Object parseArray(Class<?> arrayType,
455 ByteBuffer buf,
456 ConstantPool constPool,
457 Class<?> container) {
458 int length = buf.getShort() & 0xFFFF; // Number of array components
459 Class<?> componentType = arrayType.getComponentType();
460
461 if (componentType == byte.class) {
462 return parseByteArray(length, buf, constPool);
463 } else if (componentType == char.class) {
464 return parseCharArray(length, buf, constPool);
465 } else if (componentType == double.class) {
466 return parseDoubleArray(length, buf, constPool);
467 } else if (componentType == float.class) {
468 return parseFloatArray(length, buf, constPool);
469 } else if (componentType == int.class) {
470 return parseIntArray(length, buf, constPool);
471 } else if (componentType == long.class) {
472 return parseLongArray(length, buf, constPool);
473 } else if (componentType == short.class) {
474 return parseShortArray(length, buf, constPool);
475 } else if (componentType == boolean.class) {
476 return parseBooleanArray(length, buf, constPool);
477 } else if (componentType == String.class) {
478 return parseStringArray(length, buf, constPool);
479 } else if (componentType == Class.class) {
480 return parseClassArray(length, buf, constPool, container);
481 } else if (componentType.isEnum()) {
482 return parseEnumArray(length, (Class<? extends Enum>)componentType, buf,
483 constPool, container);
484 } else {
485 assert componentType.isAnnotation();
486 return parseAnnotationArray(length, (Class <? extends Annotation>)componentType, buf,
487 constPool, container);
488 }
489 }
490
491 private static Object parseByteArray(int length,
492 ByteBuffer buf, ConstantPool constPool) {
493 byte[] result = new byte[length];
494 boolean typeMismatch = false;
495 int tag = 0;
496
497 for (int i = 0; i < length; i++) {
498 tag = buf.get();
499 if (tag == 'B') {
500 int index = buf.getShort() & 0xFFFF;
501 result[i] = (byte) constPool.getIntAt(index);
502 } else {
503 skipMemberValue(tag, buf);
504 typeMismatch = true;
505 }
506 }
507 return typeMismatch ? exceptionProxy(tag) : result;
508 }
509
510 private static Object parseCharArray(int length,
511 ByteBuffer buf, ConstantPool constPool) {
512 char[] result = new char[length];
513 boolean typeMismatch = false;
514 byte tag = 0;
515
516 for (int i = 0; i < length; i++) {
517 tag = buf.get();
518 if (tag == 'C') {
519 int index = buf.getShort() & 0xFFFF;
520 result[i] = (char) constPool.getIntAt(index);
521 } else {
522 skipMemberValue(tag, buf);
523 typeMismatch = true;
524 }
525 }
526 return typeMismatch ? exceptionProxy(tag) : result;
527 }
528
529 private static Object parseDoubleArray(int length,
530 ByteBuffer buf, ConstantPool constPool) {
531 double[] result = new double[length];
532 boolean typeMismatch = false;
533 int tag = 0;
534
535 for (int i = 0; i < length; i++) {
536 tag = buf.get();
537 if (tag == 'D') {
538 int index = buf.getShort() & 0xFFFF;
539 result[i] = constPool.getDoubleAt(index);
540 } else {
541 skipMemberValue(tag, buf);
542 typeMismatch = true;
543 }
544 }
545 return typeMismatch ? exceptionProxy(tag) : result;
546 }
547
548 private static Object parseFloatArray(int length,
549 ByteBuffer buf, ConstantPool constPool) {
550 float[] result = new float[length];
551 boolean typeMismatch = false;
552 int tag = 0;
553
554 for (int i = 0; i < length; i++) {
555 tag = buf.get();
556 if (tag == 'F') {
557 int index = buf.getShort() & 0xFFFF;
558 result[i] = constPool.getFloatAt(index);
559 } else {
560 skipMemberValue(tag, buf);
561 typeMismatch = true;
562 }
563 }
564 return typeMismatch ? exceptionProxy(tag) : result;
565 }
566
567 private static Object parseIntArray(int length,
568 ByteBuffer buf, ConstantPool constPool) {
569 int[] result = new int[length];
570 boolean typeMismatch = false;
571 int tag = 0;
572
573 for (int i = 0; i < length; i++) {
574 tag = buf.get();
575 if (tag == 'I') {
576 int index = buf.getShort() & 0xFFFF;
577 result[i] = constPool.getIntAt(index);
578 } else {
579 skipMemberValue(tag, buf);
580 typeMismatch = true;
581 }
582 }
583 return typeMismatch ? exceptionProxy(tag) : result;
584 }
585
586 private static Object parseLongArray(int length,
587 ByteBuffer buf, ConstantPool constPool) {
588 long[] result = new long[length];
589 boolean typeMismatch = false;
590 int tag = 0;
591
592 for (int i = 0; i < length; i++) {
593 tag = buf.get();
594 if (tag == 'J') {
595 int index = buf.getShort() & 0xFFFF;
596 result[i] = constPool.getLongAt(index);
597 } else {
598 skipMemberValue(tag, buf);
599 typeMismatch = true;
600 }
601 }
602 return typeMismatch ? exceptionProxy(tag) : result;
603 }
604
605 private static Object parseShortArray(int length,
606 ByteBuffer buf, ConstantPool constPool) {
607 short[] result = new short[length];
608 boolean typeMismatch = false;
609 int tag = 0;
610
611 for (int i = 0; i < length; i++) {
612 tag = buf.get();
613 if (tag == 'S') {
614 int index = buf.getShort() & 0xFFFF;
615 result[i] = (short) constPool.getIntAt(index);
616 } else {
617 skipMemberValue(tag, buf);
618 typeMismatch = true;
619 }
620 }
621 return typeMismatch ? exceptionProxy(tag) : result;
622 }
623
624 private static Object parseBooleanArray(int length,
625 ByteBuffer buf, ConstantPool constPool) {
626 boolean[] result = new boolean[length];
627 boolean typeMismatch = false;
628 int tag = 0;
629
630 for (int i = 0; i < length; i++) {
631 tag = buf.get();
632 if (tag == 'Z') {
633 int index = buf.getShort() & 0xFFFF;
634 result[i] = (constPool.getIntAt(index) != 0);
635 } else {
636 skipMemberValue(tag, buf);
637 typeMismatch = true;
638 }
639 }
640 return typeMismatch ? exceptionProxy(tag) : result;
641 }
642
643 private static Object parseStringArray(int length,
644 ByteBuffer buf, ConstantPool constPool) {
645 String[] result = new String[length];
646 boolean typeMismatch = false;
647 int tag = 0;
648
649 for (int i = 0; i < length; i++) {
650 tag = buf.get();
651 if (tag == 's') {
652 int index = buf.getShort() & 0xFFFF;
653 result[i] = constPool.getUTF8At(index);
654 } else {
655 skipMemberValue(tag, buf);
656 typeMismatch = true;
657 }
658 }
659 return typeMismatch ? exceptionProxy(tag) : result;
660 }
661
662 private static Object parseClassArray(int length,
663 ByteBuffer buf,
664 ConstantPool constPool,
665 Class<?> container) {
666 Object[] result = new Class<?>[length];
667 boolean typeMismatch = false;
668 int tag = 0;
669
670 for (int i = 0; i < length; i++) {
671 tag = buf.get();
672 if (tag == 'c') {
673 result[i] = parseClassValue(buf, constPool, container);
674 } else {
675 skipMemberValue(tag, buf);
676 typeMismatch = true;
677 }
678 }
679 return typeMismatch ? exceptionProxy(tag) : result;
680 }
681
682 private static Object parseEnumArray(int length, Class<? extends Enum> enumType,
683 ByteBuffer buf,
684 ConstantPool constPool,
685 Class<?> container) {
686 Object[] result = (Object[]) Array.newInstance(enumType, length);
687 boolean typeMismatch = false;
688 int tag = 0;
689
690 for (int i = 0; i < length; i++) {
691 tag = buf.get();
692 if (tag == 'e') {
693 result[i] = parseEnumValue(enumType, buf, constPool, container);
694 } else {
695 skipMemberValue(tag, buf);
696 typeMismatch = true;
697 }
698 }
699 return typeMismatch ? exceptionProxy(tag) : result;
700 }
701
702 private static Object parseAnnotationArray(int length,
703 Class<? extends Annotation> annotationType,
704 ByteBuffer buf,
705 ConstantPool constPool,
706 Class<?> container) {
707 Object[] result = (Object[]) Array.newInstance(annotationType, length);
708 boolean typeMismatch = false;
709 int tag = 0;
710
711 for (int i = 0; i < length; i++) {
712 tag = buf.get();
713 if (tag == '@') {
714 result[i] = parseAnnotation(buf, constPool, container, true);
715 } else {
716 skipMemberValue(tag, buf);
717 typeMismatch = true;
718 }
719 }
720 return typeMismatch ? exceptionProxy(tag) : result;
721 }
722
723 /**
724 * Return an appropriate exception proxy for a mismatching array
725 * annotation where the erroneous array has the specified tag.
726 */
727 private static ExceptionProxy exceptionProxy(int tag) {
728 return new AnnotationTypeMismatchExceptionProxy(
729 "Array with component tag: " + tag);
730 }
731
732 /**
733 * Skips the annotation at the current position in the specified
734 * byte buffer. The cursor of the byte buffer must point to
735 * an "annotation structure" OR two bytes into an annotation
736 * structure (i.e., after the type index).
737 *
738 * @parameter complete true if the byte buffer points to the beginning
739 * of an annotation structure (rather than two bytes in).
740 */
741 private static void skipAnnotation(ByteBuffer buf, boolean complete) {
742 if (complete)
743 buf.getShort(); // Skip type index
744 int numMembers = buf.getShort() & 0xFFFF;
745 for (int i = 0; i < numMembers; i++) {
746 buf.getShort(); // Skip memberNameIndex
747 skipMemberValue(buf);
748 }
749 }
750
751 /**
752 * Skips the annotation member value at the current position in the
753 * specified byte buffer. The cursor of the byte buffer must point to a
754 * "member_value structure."
755 */
756 private static void skipMemberValue(ByteBuffer buf) {
757 int tag = buf.get();
758 skipMemberValue(tag, buf);
759 }
760
761 /**
762 * Skips the annotation member value at the current position in the
763 * specified byte buffer. The cursor of the byte buffer must point
764 * immediately after the tag in a "member_value structure."
765 */
766 private static void skipMemberValue(int tag, ByteBuffer buf) {
767 switch(tag) {
768 case 'e': // Enum value
769 buf.getInt(); // (Two shorts, actually.)
770 break;
771 case '@':
772 skipAnnotation(buf, true);
773 break;
774 case '[':
775 skipArray(buf);
776 break;
777 default:
778 // Class, primitive, or String
779 buf.getShort();
780 }
781 }
782
783 /**
784 * Skips the array value at the current position in the specified byte
785 * buffer. The cursor of the byte buffer must point to an array value
786 * struct.
787 */
788 private static void skipArray(ByteBuffer buf) {
789 int length = buf.getShort() & 0xFFFF;
790 for (int i = 0; i < length; i++)
791 skipMemberValue(buf);
792 }
793
794 /*
795 * This method converts the annotation map returned by the parseAnnotations()
796 * method to an array. It is called by Field.getDeclaredAnnotations(),
797 * Method.getDeclaredAnnotations(), and Constructor.getDeclaredAnnotations().
798 * This avoids the reflection classes to load the Annotation class until
799 * it is needed.
800 */
801 private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
802 public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
803 return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
804 }
805}