src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java

changeset 834
d7225b476a5d
parent 798
4868a36f6fd8
equal deleted inserted replaced
814:d79e283c7d9b 834:d7225b476a5d
1 /*
2 * Copyright (c) 2009, 2010, 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
26 package com.sun.tools.classfile;
27
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.EnumSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import static com.sun.tools.classfile.ExtendedAnnotation.TargetAttribute.*;
35
36 /**
37 * See JSR 308 specification, section 4.1
38 *
39 * <p><b>This is NOT part of any supported API.
40 * If you write code that depends on this, you do so at your own risk.
41 * This code and its internal interfaces are subject to change or
42 * deletion without notice.</b>
43 */
44 public class ExtendedAnnotation {
45 ExtendedAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
46 annotation = new Annotation(cr);
47 position = read_position(cr);
48 }
49
50 public ExtendedAnnotation(ConstantPool constant_pool,
51 Annotation annotation, Position position) {
52 this.annotation = annotation;
53 this.position = position;
54 }
55
56 public int length() {
57 int n = annotation.length();
58 n += position_length(position);
59 return n;
60 }
61
62 public final Annotation annotation;
63 public final Position position;
64
65 private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
66 // Copied from ClassReader
67 int tag = (byte)cr.readUnsignedByte(); // cast to introduce signedness
68 if (!TargetType.isValidTargetTypeValue(tag))
69 throw new Annotation.InvalidAnnotation("invalid type annotation target type value: " + tag);
70
71 TargetType type = TargetType.fromTargetTypeValue(tag);
72
73 Position position = new Position();
74 position.type = type;
75
76 switch (type) {
77 // type case
78 case TYPECAST:
79 case TYPECAST_GENERIC_OR_ARRAY:
80 // object creation
81 case INSTANCEOF:
82 case INSTANCEOF_GENERIC_OR_ARRAY:
83 // new expression
84 case NEW:
85 case NEW_GENERIC_OR_ARRAY:
86 position.offset = cr.readUnsignedShort();
87 break;
88 // local variable
89 case LOCAL_VARIABLE:
90 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
91 int table_length = cr.readUnsignedShort();
92 position.lvarOffset = new int[table_length];
93 position.lvarLength = new int[table_length];
94 position.lvarIndex = new int[table_length];
95 for (int i = 0; i < table_length; ++i) {
96 position.lvarOffset[i] = cr.readUnsignedShort();
97 position.lvarLength[i] = cr.readUnsignedShort();
98 position.lvarIndex[i] = cr.readUnsignedShort();
99 }
100 break;
101 // method receiver
102 case METHOD_RECEIVER:
103 // Do nothing
104 break;
105 // type parameters
106 case CLASS_TYPE_PARAMETER:
107 case METHOD_TYPE_PARAMETER:
108 position.parameter_index = cr.readUnsignedByte();
109 break;
110 // type parameter bounds
111 case CLASS_TYPE_PARAMETER_BOUND:
112 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
113 case METHOD_TYPE_PARAMETER_BOUND:
114 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
115 position.parameter_index = cr.readUnsignedByte();
116 position.bound_index = cr.readUnsignedByte();
117 break;
118 // wildcards
119 case WILDCARD_BOUND:
120 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
121 position.wildcard_position = read_position(cr);
122 break;
123 // Class extends and implements clauses
124 case CLASS_EXTENDS:
125 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
126 int in = cr.readUnsignedShort();
127 if (in == 0xFFFF)
128 in = -1;
129 position.type_index = in;
130 break;
131 // throws
132 case THROWS:
133 position.type_index = cr.readUnsignedShort();
134 break;
135 case CLASS_LITERAL:
136 case CLASS_LITERAL_GENERIC_OR_ARRAY:
137 position.offset = cr.readUnsignedShort();
138 break;
139 // method parameter: not specified
140 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
141 position.parameter_index = cr.readUnsignedByte();
142 break;
143 // method type argument: wasn't specified
144 case NEW_TYPE_ARGUMENT:
145 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
146 case METHOD_TYPE_ARGUMENT:
147 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
148 position.offset = cr.readUnsignedShort();
149 position.type_index = cr.readUnsignedByte();
150 break;
151 // We don't need to worry abut these
152 case METHOD_RETURN_GENERIC_OR_ARRAY:
153 case FIELD_GENERIC_OR_ARRAY:
154 break;
155 case UNKNOWN:
156 break;
157 default:
158 throw new AssertionError("Cannot be here");
159 }
160
161 if (type.hasLocation()) {
162 int len = cr.readUnsignedShort();
163 List<Integer> loc = new ArrayList<Integer>(len);
164 for (int i = 0; i < len; i++)
165 loc.add(cr.readUnsignedByte());
166 position.location = loc;
167 }
168 return position;
169 }
170
171 private static int position_length(Position pos) {
172 int n = 0;
173 n += 1; // target_type
174 switch (pos.type) {
175 // type case
176 case TYPECAST:
177 case TYPECAST_GENERIC_OR_ARRAY:
178 // object creation
179 case INSTANCEOF:
180 case INSTANCEOF_GENERIC_OR_ARRAY:
181 // new expression
182 case NEW:
183 case NEW_GENERIC_OR_ARRAY:
184 n += 2;
185 break;
186 // local variable
187 case LOCAL_VARIABLE:
188 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
189 n += 2; // table_length;
190 int table_length = pos.lvarOffset.length;
191 n += 2 * table_length; // offset
192 n += 2 * table_length; // length;
193 n += 2 * table_length; // index
194 break;
195 // method receiver
196 case METHOD_RECEIVER:
197 // Do nothing
198 break;
199 // type parameters
200 case CLASS_TYPE_PARAMETER:
201 case METHOD_TYPE_PARAMETER:
202 n += 1; // parameter_index;
203 break;
204 // type parameter bounds
205 case CLASS_TYPE_PARAMETER_BOUND:
206 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
207 case METHOD_TYPE_PARAMETER_BOUND:
208 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
209 n += 1; // parameter_index
210 n += 1; // bound_index
211 break;
212 case WILDCARD_BOUND:
213 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
214 n += position_length(pos.wildcard_position);
215 break;
216 // Class extends and implements clauses
217 case CLASS_EXTENDS:
218 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
219 n += 2; // type_index
220 break;
221 // throws
222 case THROWS:
223 n += 2; // type_index
224 break;
225 case CLASS_LITERAL:
226 case CLASS_LITERAL_GENERIC_OR_ARRAY:
227 n += 1; // offset
228 break;
229 // method parameter: not specified
230 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
231 n += 1; // parameter_index
232 break;
233 // method type argument: wasn't specified
234 case NEW_TYPE_ARGUMENT:
235 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
236 case METHOD_TYPE_ARGUMENT:
237 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
238 n += 2; // offset
239 n += 1; // type index
240 break;
241 // We don't need to worry abut these
242 case METHOD_RETURN_GENERIC_OR_ARRAY:
243 case FIELD_GENERIC_OR_ARRAY:
244 break;
245 case UNKNOWN:
246 break;
247 default:
248 }
249
250 if (pos.type.hasLocation()) {
251 n += 2; // length
252 n += 1 * pos.location.size(); // actual array size
253 }
254
255 return n;
256 }
257
258 // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position
259 public static class Position {
260
261 public TargetType type = TargetType.UNKNOWN;
262
263 // For generic/array types.
264 public List<Integer> location = new ArrayList<Integer>();
265
266 // For typecasts, type tests, new (and locals, as start_pc).
267 public int offset = -1;
268
269 // For locals.
270 public int[] lvarOffset = null;
271 public int[] lvarLength = null;
272 public int[] lvarIndex = null;
273
274 // For type parameter bound
275 public int bound_index = Integer.MIN_VALUE;
276
277 // For type parameter and method parameter
278 public int parameter_index = Integer.MIN_VALUE;
279
280 // For class extends, implements, and throws classes
281 public int type_index = Integer.MIN_VALUE;
282
283 // For wildcards
284 public Position wildcard_position = null;
285
286 @Override
287 public String toString() {
288 StringBuilder sb = new StringBuilder();
289 sb.append('[');
290 sb.append(type);
291
292 switch (type) {
293 // type case
294 case TYPECAST:
295 case TYPECAST_GENERIC_OR_ARRAY:
296 // object creation
297 case INSTANCEOF:
298 case INSTANCEOF_GENERIC_OR_ARRAY:
299 // new expression
300 case NEW:
301 case NEW_GENERIC_OR_ARRAY:
302 case NEW_TYPE_ARGUMENT:
303 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
304 sb.append(", offset = ");
305 sb.append(offset);
306 break;
307 // local variable
308 case LOCAL_VARIABLE:
309 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
310 sb.append(", {");
311 for (int i = 0; i < lvarOffset.length; ++i) {
312 if (i != 0) sb.append("; ");
313 sb.append(", start_pc = ");
314 sb.append(lvarOffset[i]);
315 sb.append(", length = ");
316 sb.append(lvarLength[i]);
317 sb.append(", index = ");
318 sb.append(lvarIndex[i]);
319 }
320 sb.append("}");
321 break;
322 // method receiver
323 case METHOD_RECEIVER:
324 // Do nothing
325 break;
326 // type parameters
327 case CLASS_TYPE_PARAMETER:
328 case METHOD_TYPE_PARAMETER:
329 sb.append(", param_index = ");
330 sb.append(parameter_index);
331 break;
332 // type parameters bound
333 case CLASS_TYPE_PARAMETER_BOUND:
334 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
335 case METHOD_TYPE_PARAMETER_BOUND:
336 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
337 sb.append(", param_index = ");
338 sb.append(parameter_index);
339 sb.append(", bound_index = ");
340 sb.append(bound_index);
341 break;
342 // wildcard
343 case WILDCARD_BOUND:
344 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
345 sb.append(", wild_card = ");
346 sb.append(wildcard_position);
347 break;
348 // Class extends and implements clauses
349 case CLASS_EXTENDS:
350 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
351 sb.append(", type_index = ");
352 sb.append(type_index);
353 break;
354 // throws
355 case THROWS:
356 sb.append(", type_index = ");
357 sb.append(type_index);
358 break;
359 case CLASS_LITERAL:
360 case CLASS_LITERAL_GENERIC_OR_ARRAY:
361 sb.append(", offset = ");
362 sb.append(offset);
363 break;
364 // method parameter: not specified
365 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
366 sb.append(", param_index = ");
367 sb.append(parameter_index);
368 break;
369 // method type argument: wasn't specified
370 case METHOD_TYPE_ARGUMENT:
371 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
372 sb.append(", offset = ");
373 sb.append(offset);
374 sb.append(", type_index = ");
375 sb.append(type_index);
376 break;
377 // We don't need to worry abut these
378 case METHOD_RETURN_GENERIC_OR_ARRAY:
379 case FIELD_GENERIC_OR_ARRAY:
380 break;
381 case UNKNOWN:
382 break;
383 default:
384 throw new AssertionError("unknown type: " + type);
385 }
386
387 // Append location data for generics/arrays.
388 if (type.hasLocation()) {
389 sb.append(", location = (");
390 sb.append(location);
391 sb.append(")");
392 }
393
394 sb.append(']');
395 return sb.toString();
396 }
397 }
398
399 // Code duplicated from com.sun.tools.javac.comp.TargetType
400 public enum TargetType {
401
402 /** For annotations on typecasts. */
403 TYPECAST(0x00),
404
405 /** For annotations on a type argument or nested array of a typecast. */
406 TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation),
407
408 /** For annotations on type tests. */
409 INSTANCEOF(0x02),
410
411 /** For annotations on a type argument or nested array of a type test. */
412 INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation),
413
414 /** For annotations on object creation expressions. */
415 NEW(0x04),
416
417 /**
418 * For annotations on a type argument or nested array of an object creation
419 * expression.
420 */
421 NEW_GENERIC_OR_ARRAY(0x05, HasLocation),
422
423
424 /** For annotations on the method receiver. */
425 METHOD_RECEIVER(0x06),
426
427 // invalid location
428 // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
429
430 /** For annotations on local variables. */
431 LOCAL_VARIABLE(0x08),
432
433 /** For annotations on a type argument or nested array of a local. */
434 LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation),
435
436 // already handled by regular annotations
437 // METHOD_RETURN(0x0A),
438
439 /**
440 * For annotations on a type argument or nested array of a method return
441 * type.
442 */
443 METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation),
444
445 // already handled by regular annotations
446 // METHOD_PARAMETER(0x0C),
447
448 /** For annotations on a type argument or nested array of a method parameter. */
449 METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
450
451 // already handled by regular annotations
452 // FIELD(0x0E),
453
454 /** For annotations on a type argument or nested array of a field. */
455 FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
456
457 /** For annotations on a bound of a type parameter of a class. */
458 CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
459
460 /**
461 * For annotations on a type argument or nested array of a bound of a type
462 * parameter of a class.
463 */
464 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter),
465
466 /** For annotations on a bound of a type parameter of a method. */
467 METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
468
469 /**
470 * For annotations on a type argument or nested array of a bound of a type
471 * parameter of a method.
472 */
473 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter),
474
475 /** For annotations on the type of an "extends" or "implements" clause. */
476 CLASS_EXTENDS(0x14),
477
478 /** For annotations on the inner type of an "extends" or "implements" clause. */
479 CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
480
481 /** For annotations on a throws clause in a method declaration. */
482 THROWS(0x16),
483
484 // invalid location
485 // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
486
487 /** For annotations in type arguments of object creation expressions. */
488 NEW_TYPE_ARGUMENT(0x18),
489 NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation),
490
491 METHOD_TYPE_ARGUMENT(0x1A),
492 METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation),
493
494 WILDCARD_BOUND(0x1C, HasBound),
495 WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
496
497 CLASS_LITERAL(0x1E),
498 CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation),
499
500 METHOD_TYPE_PARAMETER(0x20, HasParameter),
501
502 // invalid location
503 // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
504
505 CLASS_TYPE_PARAMETER(0x22, HasParameter),
506
507 // invalid location
508 // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
509
510 /** For annotations with an unknown target. */
511 UNKNOWN(-1);
512
513 static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
514
515 private final int targetTypeValue;
516 private Set<TargetAttribute> flags;
517
518 TargetType(int targetTypeValue, TargetAttribute... attrs) {
519 if (targetTypeValue < Byte.MIN_VALUE
520 || targetTypeValue > Byte.MAX_VALUE)
521 throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue);
522 this.targetTypeValue = (byte)targetTypeValue;
523 this.flags = EnumSet.noneOf(TargetAttribute.class);
524 for (TargetAttribute attr : attrs)
525 this.flags.add(attr);
526 }
527
528 /**
529 * Returns whether or not this TargetType represents an annotation whose
530 * target is an inner type of a generic or array type.
531 *
532 * @return true if this TargetType represents an annotation on an inner
533 * type, false otherwise
534 */
535 public boolean hasLocation() {
536 return flags.contains(HasLocation);
537 }
538
539 public TargetType getGenericComplement() {
540 if (hasLocation())
541 return this;
542 else
543 return fromTargetTypeValue(targetTypeValue() + 1);
544 }
545
546 /**
547 * Returns whether or not this TargetType represents an annotation whose
548 * target has a parameter index.
549 *
550 * @return true if this TargetType has a parameter index,
551 * false otherwise
552 */
553 public boolean hasParameter() {
554 return flags.contains(HasParameter);
555 }
556
557 /**
558 * Returns whether or not this TargetType represents an annotation whose
559 * target is a type parameter bound.
560 *
561 * @return true if this TargetType represents an type parameter bound
562 * annotation, false otherwise
563 */
564 public boolean hasBound() {
565 return flags.contains(HasBound);
566 }
567
568 public int targetTypeValue() {
569 return this.targetTypeValue;
570 }
571
572 private static TargetType[] targets = null;
573
574 private static TargetType[] buildTargets() {
575 TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
576 TargetType[] alltargets = values();
577 for (TargetType target : alltargets)
578 if (target.targetTypeValue >= 0)
579 targets[target.targetTypeValue] = target;
580 for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i)
581 if (targets[i] == null)
582 targets[i] = UNKNOWN;
583 return targets;
584 }
585
586 public static boolean isValidTargetTypeValue(int tag) {
587 if (targets == null)
588 targets = buildTargets();
589
590 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
591 return true;
592
593 return (tag >= 0 && tag < targets.length);
594 }
595
596 public static TargetType fromTargetTypeValue(int tag) {
597 if (targets == null)
598 targets = buildTargets();
599
600 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
601 return UNKNOWN;
602
603 if (tag < 0 || tag >= targets.length)
604 throw new IllegalArgumentException("Unknown TargetType: " + tag);
605 return targets[tag];
606 }
607 }
608
609 static enum TargetAttribute {
610 HasLocation, HasParameter, HasBound;
611 }
612 }

mercurial