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

Tue, 25 May 2010 15:54:51 -0700

author
ohair
date
Tue, 25 May 2010 15:54:51 -0700
changeset 554
9d9f26857129
parent 484
732510cc3538
child 581
f2fdd52e4e87
permissions
-rw-r--r--

6943119: Rebrand source copyright notices
Reviewed-by: darcy

     1 /*
     2  * Copyright (c) 2009, 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  */
    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             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         }
   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     }
   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         }
   250         if (pos.type.hasLocation()) {
   251             n += 2; // length
   252             n += 1 * pos.location.size(); // actual array size
   253         }
   255         return n;
   256     }
   258     // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position
   259     public static class Position {
   261         public TargetType type = TargetType.UNKNOWN;
   263         // For generic/array types.
   264         public List<Integer> location = new ArrayList<Integer>();
   266         // For typecasts, type tests, new (and locals, as start_pc).
   267         public int offset = -1;
   269         // For locals.
   270         public int[] lvarOffset = null;
   271         public int[] lvarLength = null;
   272         public int[] lvarIndex = null;
   274         // For type parameter bound
   275         public int bound_index = Integer.MIN_VALUE;
   277         // For type parameter and method parameter
   278         public int parameter_index = Integer.MIN_VALUE;
   280         // For class extends, implements, and throws classes
   281         public int type_index = Integer.MIN_VALUE;
   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             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             }
   387             // Append location data for generics/arrays.
   388             if (type.hasLocation()) {
   389                 sb.append(", location = (");
   390                 sb.append(location);
   391                 sb.append(")");
   392             }
   394             sb.append(']');
   395             return sb.toString();
   396         }
   397     }
   399     // Code duplicated from com.sun.tools.javac.comp.TargetType
   400     public enum TargetType {
   402         /** For annotations on typecasts. */
   403         TYPECAST(0x00),
   405         /** For annotations on a type argument or nested array of a typecast. */
   406         TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation),
   408         /** For annotations on type tests. */
   409         INSTANCEOF(0x02),
   411         /** For annotations on a type argument or nested array of a type test. */
   412         INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation),
   414         /** For annotations on object creation expressions. */
   415         NEW(0x04),
   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),
   424         /** For annotations on the method receiver. */
   425         METHOD_RECEIVER(0x06),
   427         // invalid location
   428         // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
   430         /** For annotations on local variables. */
   431         LOCAL_VARIABLE(0x08),
   433         /** For annotations on a type argument or nested array of a local. */
   434         LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation),
   436         // already handled by regular annotations
   437         // METHOD_RETURN(0x0A),
   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),
   445         // already handled by regular annotations
   446         // METHOD_PARAMETER(0x0C),
   448         /** For annotations on a type argument or nested array of a method parameter. */
   449         METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
   451         // already handled by regular annotations
   452         // FIELD(0x0E),
   454         /** For annotations on a type argument or nested array of a field. */
   455         FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
   457         /** For annotations on a bound of a type parameter of a class. */
   458         CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
   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),
   466         /** For annotations on a bound of a type parameter of a method. */
   467         METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
   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),
   475         /** For annotations on the type of an "extends" or "implements" clause. */
   476         CLASS_EXTENDS(0x14),
   478         /** For annotations on the inner type of an "extends" or "implements" clause. */
   479         CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
   481         /** For annotations on a throws clause in a method declaration. */
   482         THROWS(0x16),
   484         // invalid location
   485         // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
   487         /** For annotations in type arguments of object creation expressions. */
   488         NEW_TYPE_ARGUMENT(0x18),
   489         NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation),
   491         METHOD_TYPE_ARGUMENT(0x1A),
   492         METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation),
   494         WILDCARD_BOUND(0x1C, HasBound),
   495         WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
   497         CLASS_LITERAL(0x1E),
   498         CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation),
   500         METHOD_TYPE_PARAMETER(0x20, HasParameter),
   502         // invalid location
   503         // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
   505         CLASS_TYPE_PARAMETER(0x22, HasParameter),
   507         // invalid location
   508         // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
   510         /** For annotations with an unknown target. */
   511         UNKNOWN(-1);
   513         static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
   515         private final int targetTypeValue;
   516         private Set<TargetAttribute> flags;
   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         }
   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         }
   539         public TargetType getGenericComplement() {
   540             if (hasLocation())
   541                 return this;
   542             else
   543                 return fromTargetTypeValue(targetTypeValue() + 1);
   544         }
   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         }
   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         }
   568         public int targetTypeValue() {
   569             return this.targetTypeValue;
   570         }
   572         private static TargetType[] targets = null;
   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         }
   586         public static boolean isValidTargetTypeValue(int tag) {
   587             if (targets == null)
   588                 targets = buildTargets();
   590             if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
   591                 return true;
   593             return (tag >= 0 && tag < targets.length);
   594         }
   596         public static TargetType fromTargetTypeValue(int tag) {
   597             if (targets == null)
   598                 targets = buildTargets();
   600             if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
   601                 return UNKNOWN;
   603             if (tag < 0 || tag >= targets.length)
   604                 throw new IllegalArgumentException("Unknown TargetType: " + tag);
   605             return targets[tag];
   606         }
   607     }
   609     static enum TargetAttribute {
   610         HasLocation, HasParameter, HasBound;
   611     }
   612 }

mercurial