/* * 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(); } }