Fri, 26 Jun 2009 19:12:41 -0700
6855544: add missing files
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.classfile;
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;
34 import static com.sun.tools.classfile.ExtendedAnnotation.TargetAttribute.*;
36 /**
37 * See JSR 308 specification, section 4.1
38 *
39 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
40 * 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 }
50 public ExtendedAnnotation(ConstantPool constant_pool,
51 Annotation annotation, Position position) {
52 this.annotation = annotation;
53 this.position = position;
54 }
56 public int length() {
57 int n = annotation.length();
58 n += position_length(position);
59 return n;
60 }
62 public final Annotation annotation;
63 public final Position position;
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);
71 TargetType type = TargetType.fromTargetTypeValue(tag);
73 Position position = new Position();
74 position.type = type;
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 position.type_index = cr.readUnsignedByte();
127 break;
128 // throws
129 case THROWS:
130 position.type_index = cr.readUnsignedByte();
131 break;
132 case CLASS_LITERAL:
133 case CLASS_LITERAL_GENERIC_OR_ARRAY:
134 position.offset = cr.readUnsignedShort();
135 break;
136 // method parameter: not specified
137 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
138 position.parameter_index = cr.readUnsignedByte();
139 break;
140 // method type argument: wasn't specified
141 case NEW_TYPE_ARGUMENT:
142 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
143 case METHOD_TYPE_ARGUMENT:
144 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
145 position.offset = cr.readUnsignedShort();
146 position.type_index = cr.readUnsignedByte();
147 break;
148 // We don't need to worry abut these
149 case METHOD_RETURN_GENERIC_OR_ARRAY:
150 case FIELD_GENERIC_OR_ARRAY:
151 break;
152 case UNKNOWN:
153 break;
154 default:
155 throw new AssertionError("Cannot be here");
156 }
158 if (type.hasLocation()) {
159 int len = cr.readUnsignedShort();
160 List<Integer> loc = new ArrayList<Integer>(len);
161 for (int i = 0; i < len; i++)
162 loc.add(cr.readUnsignedByte());
163 position.location = loc;
164 }
165 return position;
166 }
168 private static int position_length(Position pos) {
169 int n = 0;
170 n += 1; // target_type
171 switch (pos.type) {
172 // type case
173 case TYPECAST:
174 case TYPECAST_GENERIC_OR_ARRAY:
175 // object creation
176 case INSTANCEOF:
177 case INSTANCEOF_GENERIC_OR_ARRAY:
178 // new expression
179 case NEW:
180 case NEW_GENERIC_OR_ARRAY:
181 n += 2;
182 break;
183 // local variable
184 case LOCAL_VARIABLE:
185 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
186 n += 2; // table_length;
187 int table_length = pos.lvarOffset.length;
188 n += 2 * table_length; // offset
189 n += 2 * table_length; // length;
190 n += 2 * table_length; // index
191 break;
192 // method receiver
193 case METHOD_RECEIVER:
194 // Do nothing
195 break;
196 // type parameters
197 case CLASS_TYPE_PARAMETER:
198 case METHOD_TYPE_PARAMETER:
199 n += 1; // parameter_index;
200 break;
201 // type parameter bounds
202 case CLASS_TYPE_PARAMETER_BOUND:
203 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
204 case METHOD_TYPE_PARAMETER_BOUND:
205 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
206 n += 1; // parameter_index
207 n += 1; // bound_index
208 break;
209 case WILDCARD_BOUND:
210 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
211 n += position_length(pos.wildcard_position);
212 break;
213 // Class extends and implements clauses
214 case CLASS_EXTENDS:
215 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
216 n += 1; // type_index
217 break;
218 // throws
219 case THROWS:
220 n += 1; // type_index
221 break;
222 case CLASS_LITERAL:
223 case CLASS_LITERAL_GENERIC_OR_ARRAY:
224 n += 1; // offset
225 break;
226 // method parameter: not specified
227 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
228 n += 1; // parameter_index
229 break;
230 // method type argument: wasn't specified
231 case NEW_TYPE_ARGUMENT:
232 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
233 case METHOD_TYPE_ARGUMENT:
234 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
235 n += 2; // offset
236 n += 1; // type index
237 break;
238 // We don't need to worry abut these
239 case METHOD_RETURN_GENERIC_OR_ARRAY:
240 case FIELD_GENERIC_OR_ARRAY:
241 break;
242 case UNKNOWN:
243 break;
244 default:
245 }
247 if (pos.type.hasLocation()) {
248 n += 2; // length
249 n += 1 * pos.location.size(); // actual array size
250 }
252 return n;
253 }
255 // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position
256 public static class Position {
258 public TargetType type = TargetType.UNKNOWN;
260 // For generic/array types.
261 public List<Integer> location = new ArrayList<Integer>();
263 // Tree position.
264 public int pos = -1;
266 // For typecasts, type tests, new (and locals, as start_pc).
267 public int offset = -1;
269 // For locals.
270 public int[] lvarOffset = new int[] { -1 };
271 public int[] lvarLength = new int[] { -1 };
272 public int[] lvarIndex = new int[] { -1 };
274 // For type parameter bound
275 public int bound_index = -1;
277 // For type parameter and method parameter
278 public int parameter_index = -1;
280 // For class extends, implements, and throws classes
281 public int type_index = -2;
283 // For wildcards
284 public Position wildcard_position = null;
286 @Override
287 public String toString() {
288 StringBuilder sb = new StringBuilder();
289 sb.append('[');
290 sb.append(type);
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 sb.append(", offset = ");
361 sb.append(offset);
362 break;
363 // method parameter: not specified
364 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
365 sb.append(", param_index = ");
366 sb.append(parameter_index);
367 break;
368 // method type argument: wasn't specified
369 case METHOD_TYPE_ARGUMENT:
370 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
371 sb.append(", offset = ");
372 sb.append(offset);
373 sb.append(", type_index = ");
374 sb.append(type_index);
375 break;
376 // We don't need to worry abut these
377 case METHOD_RETURN_GENERIC_OR_ARRAY:
378 case FIELD_GENERIC_OR_ARRAY:
379 break;
380 case UNKNOWN:
381 break;
382 default:
383 throw new AssertionError("unknown type: " + type);
384 }
386 // Append location data for generics/arrays.
387 if (type.hasLocation()) {
388 sb.append(", location = (");
389 sb.append(location);
390 sb.append(")");
391 }
393 sb.append(", pos = ");
394 sb.append(pos);
396 sb.append(']');
397 return sb.toString();
398 }
399 }
401 // Code duplicated from com.sun.tools.javac.comp.TargetType
402 public enum TargetType {
404 /** For annotations on typecasts. */
405 TYPECAST(0x00),
407 /** For annotations on a type argument or nested array of a typecast. */
408 TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation),
410 /** For annotations on type tests. */
411 INSTANCEOF(0x02),
413 /** For annotations on a type argument or nested array of a type test. */
414 INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation),
416 /** For annotations on object creation expressions. */
417 NEW(0x04),
419 /**
420 * For annotations on a type argument or nested array of an object creation
421 * expression.
422 */
423 NEW_GENERIC_OR_ARRAY(0x05, HasLocation),
426 /** For annotations on the method receiver. */
427 METHOD_RECEIVER(0x06),
429 // invalid location
430 // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
432 /** For annotations on local variables. */
433 LOCAL_VARIABLE(0x08),
435 /** For annotations on a type argument or nested array of a local. */
436 LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation),
438 // already handled by regular annotations
439 // METHOD_RETURN(0x0A),
441 /**
442 * For annotations on a type argument or nested array of a method return
443 * type.
444 */
445 METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation),
447 // already handled by regular annotations
448 // METHOD_PARAMETER(0x0C),
450 /** For annotations on a type argument or nested array of a method parameter. */
451 METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
453 // already handled by regular annotations
454 // FIELD(0x0E),
456 /** For annotations on a type argument or nested array of a field. */
457 FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
459 /** For annotations on a bound of a type parameter of a class. */
460 CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
462 /**
463 * For annotations on a type argument or nested array of a bound of a type
464 * parameter of a class.
465 */
466 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter),
468 /** For annotations on a bound of a type parameter of a method. */
469 METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
471 /**
472 * For annotations on a type argument or nested array of a bound of a type
473 * parameter of a method.
474 */
475 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter),
477 /** For annotations on the type of an "extends" or "implements" clause. */
478 CLASS_EXTENDS(0x14),
480 /** For annotations on the inner type of an "extends" or "implements" clause. */
481 CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
483 /** For annotations on a throws clause in a method declaration. */
484 THROWS(0x16),
486 // invalid location
487 // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
489 /** For annotations in type arguments of object creation expressions. */
490 NEW_TYPE_ARGUMENT(0x18),
491 NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation),
493 METHOD_TYPE_ARGUMENT(0x1A),
494 METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation),
496 WILDCARD_BOUND(0x1C, HasBound),
497 WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
499 CLASS_LITERAL(0x1E),
500 CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation),
502 METHOD_TYPE_PARAMETER(0x20, HasParameter),
504 // invalid location
505 // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
507 CLASS_TYPE_PARAMETER(0x22, HasParameter),
509 // invalid location
510 // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
512 /** For annotations with an unknown target. */
513 UNKNOWN(-1);
515 static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
517 private final int targetTypeValue;
518 private Set<TargetAttribute> flags;
520 TargetType(int targetTypeValue, TargetAttribute... attrs) {
521 if (targetTypeValue < Byte.MIN_VALUE
522 || targetTypeValue > Byte.MAX_VALUE)
523 throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue);
524 this.targetTypeValue = (byte)targetTypeValue;
525 this.flags = EnumSet.noneOf(TargetAttribute.class);
526 for (TargetAttribute attr : attrs)
527 this.flags.add(attr);
528 }
530 /**
531 * Returns whether or not this TargetType represents an annotation whose
532 * target is an inner type of a generic or array type.
533 *
534 * @return true if this TargetType represents an annotation on an inner
535 * type, false otherwise
536 */
537 public boolean hasLocation() {
538 return flags.contains(HasLocation);
539 }
541 public TargetType getGenericComplement() {
542 if (hasLocation())
543 return this;
544 else
545 return fromTargetTypeValue(targetTypeValue() + 1);
546 }
548 /**
549 * Returns whether or not this TargetType represents an annotation whose
550 * target has a parameter index.
551 *
552 * @return true if this TargetType has a parameter index,
553 * false otherwise
554 */
555 public boolean hasParameter() {
556 return flags.contains(HasParameter);
557 }
559 /**
560 * Returns whether or not this TargetType represents an annotation whose
561 * target is a type parameter bound.
562 *
563 * @return true if this TargetType represents an type parameter bound
564 * annotation, false otherwise
565 */
566 public boolean hasBound() {
567 return flags.contains(HasBound);
568 }
570 public int targetTypeValue() {
571 return this.targetTypeValue;
572 }
574 private static TargetType[] targets = null;
576 private static TargetType[] buildTargets() {
577 TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
578 TargetType[] alltargets = values();
579 for (TargetType target : alltargets)
580 if (target.targetTypeValue >= 0)
581 targets[target.targetTypeValue] = target;
582 for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i)
583 if (targets[i] == null)
584 targets[i] = UNKNOWN;
585 return targets;
586 }
588 public static boolean isValidTargetTypeValue(int tag) {
589 if (targets == null)
590 targets = buildTargets();
592 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
593 return true;
595 return (tag >= 0 && tag < targets.length);
596 }
598 public static TargetType fromTargetTypeValue(int tag) {
599 if (targets == null)
600 targets = buildTargets();
602 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
603 return UNKNOWN;
605 if (tag < 0 || tag >= targets.length)
606 throw new IllegalArgumentException("Unknown TargetType: " + tag);
607 return targets[tag];
608 }
609 }
611 static enum TargetAttribute {
612 HasLocation, HasParameter, HasBound;
613 }
614 }