--- /dev/null 2013-01-17 09:11:42.581489353 +0100 +++ new/src/share/classes/sun/reflect/annotation/TypeAnnotation.java 2013-01-17 16:42:44.197550249 +0100 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.reflect.annotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.lang.reflect.AnnotatedElement; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class TypeAnnotation { + private TypeAnnotationTargetInfo targetInfo; + private LocationInfo loc; + private Annotation annotation; + private AnnotatedElement baseDeclaration; + + public TypeAnnotationTargetInfo getTargetInfo() { + return targetInfo; + } + public void setTargetInfo(TypeAnnotationTargetInfo targetInfo) { + this.targetInfo = targetInfo; + } + public Annotation getAnnotation() { + return annotation; + } + public void setAnnotation(Annotation annotation) { + this.annotation = annotation; + } + public AnnotatedElement getBaseDeclaration() { + return baseDeclaration; + } + public void setBaseDeclaration(AnnotatedElement a) { + this.baseDeclaration = a; + } + public LocationInfo getLocationInfo() { + return loc; + } + public void setLocationInfo(LocationInfo a) { + this.loc = a; + } + + public static List filter(TypeAnnotation[] typeAnnotations, + TypeAnnotationTarget predicate) { + List typeAnnos = new ArrayList<>(); + for (TypeAnnotation t : typeAnnotations) + if (t.getTargetInfo().getTarget() == predicate) + typeAnnos.add(t); + return typeAnnos; + } + + public static enum TypeAnnotationTarget { + CLASS_TYPE_PARAMETER, + METHOD_TYPE_PARAMETER, + CLASS_EXTENDS, + CLASS_IMPLEMENTS, + CLASS_PARAMETER_BOUND, + METHOD_PARAMETER_BOUND, + METHOD_RETURN_TYPE, + METHOD_RECEIVER_TYPE, + FIELD_TYPE, + THROWS; + } + public static class TypeAnnotationTargetInfo { + private TypeAnnotationTarget target; + private int count = -2; // -2 is not a valid index + private int secondIndex = -1; + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target) { + this.target = target; + } + + public TypeAnnotationTarget getTarget() { + return target; + } + public void setTarget(TypeAnnotationTarget target) { + this.target = target; + } + public int getCount() { + return count; + } + public void setCount(int count) { + this.count = count; + } + public int getSecondIndex() { + return secondIndex; + } + public void setSecondIndex(int i) { + this.secondIndex = i; + } + + @Override + public String toString() { + return "" + target + ": " + count + ", " + secondIndex; + } + } + + public static class LocationInfo { + private final int depth; + private final Location[] locations; + private LocationInfo() { + this(0, new Location[0]); + } + private LocationInfo(int depth, Location[] locations) { + this.depth = depth; + this.locations = locations; + } + public static final LocationInfo BASE_LOCATION = new LocationInfo(); + + public static LocationInfo parseLocationInfo(ByteBuffer buf) { + int depth = buf.get(); + if (depth == 0) + return BASE_LOCATION; + Location[] locations = new Location[depth]; + for (int i = 0; i < depth; i++) { + byte tag = buf.get(); + byte index = buf.get(); + if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3)) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + if (tag != 3 && index != 0) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + locations[i] = new Location(); + locations[i].tag = tag; + locations[i].index = index; + } + return new LocationInfo(depth, locations); + } + + public LocationInfo pushArray() { + return pushLocation((byte)0, (byte)0); + } + + public LocationInfo pushInner() { + return pushLocation((byte)1, (byte)0); + } + + public LocationInfo pushWildcard() { + return pushLocation((byte) 2, (byte) 0); + } + + public LocationInfo pushTypeArg(byte index) { + return pushLocation((byte) 3, index); + } + + public LocationInfo pushLocation(byte tag, byte index) { + int newDepth = this.depth + 1; + Location[] res = new Location[newDepth]; + System.arraycopy(this.locations, 0, res, 0, depth); + res[newDepth - 1] = new Location(tag, index); + return new LocationInfo(newDepth, res); + } + + public TypeAnnotation[] filter(TypeAnnotation[] ta) { + List l = new ArrayList<>(ta.length); + for (TypeAnnotation t : ta) { + if (isSameLocationInfo(t.getLocationInfo())) + l.add(t); + } + return l.toArray(new TypeAnnotation[0]); + } + + boolean isSameLocationInfo(LocationInfo other) { + if (depth != other.depth) + return false; + for (int i = 0; i < depth; i++) + if (!locations[i].isSameLocation(other.locations[i])) + return false; + return true; + } + + public static class Location { + public byte tag; + public byte index; + + boolean isSameLocation(Location other) { + return tag == other.tag && index == other.index; + } + + public Location(byte tag, byte index) { + this.tag = tag; + this.index = index; + } + public Location() { + this((byte)0,(byte)0); + } + } + } + + public String toString() { + return annotation.toString() + " with Targetnfo: " + + targetInfo.toString() + " on base declaration: " + + baseDeclaration.toString(); + } +}