1 /* 2 * Copyright (c) 2013, 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 sun.reflect.annotation; 27 28 import java.lang.annotation.*; 29 import java.lang.reflect.*; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.List; 33 import java.util.Map; 34 35 import static sun.reflect.annotation.TypeAnnotation.*; 36 37 public class AnnotatedTypeFactory { 38 public static AnnotatedType buildAnnotatedType(Type type, 39 LocationInfo currentLoc, 40 TypeAnnotation[] actualTypeAnnos, 41 TypeAnnotation[] allOnSameTarget, 42 AnnotatedElement decl) { 43 if (type == null) { 44 return EMPTY_ANNOTATED_TYPE; 45 } 46 if (isArray(type)) 47 return new AnnotatedArrayTypeImpl(type, 48 currentLoc, 49 actualTypeAnnos, 50 allOnSameTarget, 51 decl); 52 if (type instanceof Class) { 53 return new AnnotatedTypeBaseImpl(type, 54 addNesting(type, currentLoc), 55 actualTypeAnnos, 56 allOnSameTarget, 57 decl); 58 } else if (type instanceof TypeVariable) { 59 return new AnnotatedTypeVariableImpl((TypeVariable)type, 60 currentLoc, 61 actualTypeAnnos, 62 allOnSameTarget, 63 decl); 64 } else if (type instanceof ParameterizedType) { 65 return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, 66 addNesting(type, currentLoc), 67 actualTypeAnnos, 68 allOnSameTarget, 69 decl); 70 } else if (type instanceof WildcardType) { 71 return new AnnotatedWildcardTypeImpl((WildcardType) type, 72 currentLoc, 73 actualTypeAnnos, 74 allOnSameTarget, 75 decl); 76 } 77 // Assert here? because this should not be happening 78 return EMPTY_ANNOTATED_TYPE; 79 } 80 81 private static LocationInfo addNesting(Type type, LocationInfo addTo) { 82 if (isArray(type)) 83 return addTo; 84 if (type instanceof Class) { 85 Class<?> clz = (Class)type; 86 if (clz.getEnclosingClass() == null) 87 return addTo; 88 return addNesting(clz.getEnclosingClass(), addTo.pushInner()); 89 } else if (type instanceof ParameterizedType) { 90 ParameterizedType t = (ParameterizedType)type; 91 if (t.getOwnerType() == null) 92 return addTo; 93 return addNesting(t.getOwnerType(), addTo.pushInner()); 94 } 95 return addTo; 96 } 97 98 private static boolean isArray(Type t) { 99 if (t instanceof Class) { 100 Class<?> c = (Class)t; 101 if (c.isArray()) 102 return true; 103 } else if (t instanceof GenericArrayType) { 104 return true; 105 } 106 return false; 107 } 108 109 static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, 110 new TypeAnnotation[0], new TypeAnnotation[0], null); 111 112 private static class AnnotatedTypeBaseImpl implements AnnotatedType { 113 private Type type; 114 private AnnotatedElement decl; 115 private LocationInfo location; 116 private TypeAnnotation[] allOnSameTargetTypeAnnotations; 117 private Map<Class <? extends Annotation>, Annotation> annotations; 118 119 AnnotatedTypeBaseImpl(Type type, LocationInfo location, 120 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 121 AnnotatedElement decl) { 122 this.type = type; 123 this.decl = decl; 124 this.location = location; 125 this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; 126 this.annotations = TypeAnnotationParser.mapAnnotations(location.filter(actualTypeAnnotations)); 127 } 128 public final boolean isAnnotationPresent(Class<? extends Annotation> annotation) { 129 return annotations.get(annotation) != null; 130 } 131 public final Annotation[] getAnnotations() { 132 return getDeclaredAnnotations(); 133 } 134 public final <T extends Annotation> T getAnnotation(Class<T> annotation) { 135 return getDeclaredAnnotation(annotation); 136 } 137 public final <T extends Annotation> T[] getAnnotations(Class<T> annotation) { 138 return getDeclaredAnnotations(annotation); 139 } 140 public Annotation[] getDeclaredAnnotations() { 141 return annotations.values().toArray(new Annotation[0]); 142 } 143 @SuppressWarnings("unchecked") 144 public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) { 145 return (T)annotations.get(annotation); 146 } 147 public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotation) { 148 return AnnotationSupport.getMultipleAnnotations(annotations, annotation); 149 } 150 151 Type getType() { 152 return type; 153 } 154 LocationInfo getLocation() { 155 return location; 156 } 157 TypeAnnotation[] getTypeAnnotations() { 158 return allOnSameTargetTypeAnnotations; 159 } 160 AnnotatedElement getDecl() { 161 return decl; 162 } 163 } 164 165 private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { 166 AnnotatedArrayTypeImpl(Type type, LocationInfo location, 167 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 168 AnnotatedElement decl) { 169 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 170 } 171 public AnnotatedType getAnnotatedGenericComponentType() { 172 return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), 173 getLocation().pushArray(), 174 getTypeAnnotations(), 175 getTypeAnnotations(), 176 getDecl()); 177 } 178 private Type getComponentType() { 179 Type t = getType(); 180 if (t instanceof Class) { 181 Class<?> c = (Class)t; 182 return c.getComponentType(); 183 } 184 return ((GenericArrayType)t).getGenericComponentType(); 185 } 186 } 187 188 private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { 189 AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location, 190 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 191 AnnotatedElement decl) { 192 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 193 } 194 195 private TypeVariable<?> getTypeVariable() { 196 return (TypeVariable)getType(); 197 } 198 public AnnotatedType[] getAnnotatedBounds() { 199 return getTypeVariable().getAnnotatedBounds(); 200 } 201 } 202 203 private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType { 204 AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, 205 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 206 AnnotatedElement decl) { 207 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 208 } 209 public AnnotatedType[] getAnnotatedActualTypeArguments() { 210 Type[] arguments = getParameterizedType().getActualTypeArguments(); 211 AnnotatedType[] res = new AnnotatedType[arguments.length]; 212 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 213 for (int i = 0; i < res.length; i++) { 214 List<TypeAnnotation> l = new ArrayList<>(); 215 LocationInfo newLoc = getLocation().pushTypeArg((byte)i); 216 for (TypeAnnotation t : getTypeAnnotations()) 217 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 218 l.add(t); 219 res[i] = buildAnnotatedType(arguments[i], 220 newLoc, 221 l.toArray(new TypeAnnotation[0]), 222 getTypeAnnotations(), 223 getDecl()); 224 } 225 return res; 226 } 227 228 private ParameterizedType getParameterizedType() { 229 return (ParameterizedType)getType(); 230 } 231 } 232 233 private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { 234 private boolean hasUpperBounds; 235 AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, 236 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 237 AnnotatedElement decl) { 238 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 239 hasUpperBounds = (type.getLowerBounds().length == 0); 240 } 241 242 public AnnotatedType[] getAnnotatedUpperBounds() { 243 if (!hasUpperBounds()) 244 return new AnnotatedType[0]; 245 return getAnnotatedBounds(getWildcardType().getUpperBounds()); 246 } 247 248 public AnnotatedType[] getAnnotatedLowerBounds() { 249 if (hasUpperBounds) 250 return new AnnotatedType[0]; 251 return getAnnotatedBounds(getWildcardType().getLowerBounds()); 252 } 253 254 private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { 255 AnnotatedType[] res = new AnnotatedType[bounds.length]; 256 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 257 LocationInfo newLoc = getLocation().pushWildcard(); 258 for (int i = 0; i < res.length; i++) { 259 List<TypeAnnotation> l = new ArrayList<>(); 260 for (TypeAnnotation t : getTypeAnnotations()) 261 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 262 l.add(t); 263 res[i] = buildAnnotatedType(bounds[i], 264 newLoc, 265 l.toArray(new TypeAnnotation[0]), 266 getTypeAnnotations(), 267 getDecl()); 268 } 269 return res; 270 } 271 272 private WildcardType getWildcardType() { 273 return (WildcardType)getType(); 274 } 275 276 private boolean hasUpperBounds() { 277 return hasUpperBounds; 278 } 279 } 280 }