1 /* 2 * Copyright (c) 2013, 2015, 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 final class AnnotatedTypeFactory { 38 /** 39 * Create an AnnotatedType. 40 * 41 * @param type the type this AnnotatedType corresponds to 42 * @param currentLoc the location this AnnotatedType corresponds to 43 * @param actualTypeAnnos the type annotations this AnnotatedType has 44 * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget 45 * as the AnnotatedType being built 46 * @param decl the declaration having the type use this AnnotatedType 47 * corresponds to 48 */ 49 public static AnnotatedType buildAnnotatedType(Type type, 50 LocationInfo currentLoc, 51 TypeAnnotation[] actualTypeAnnos, 52 TypeAnnotation[] allOnSameTarget, 53 AnnotatedElement decl) { 54 if (type == null) { 55 return EMPTY_ANNOTATED_TYPE; 56 } 57 if (isArray(type)) 58 return new AnnotatedArrayTypeImpl(type, 59 currentLoc, 60 actualTypeAnnos, 61 allOnSameTarget, 62 decl); 63 if (type instanceof Class) { 64 return new AnnotatedTypeBaseImpl(type, 65 addNesting(type, currentLoc), 66 actualTypeAnnos, 67 allOnSameTarget, 68 decl); 69 } else if (type instanceof TypeVariable) { 70 return new AnnotatedTypeVariableImpl((TypeVariable)type, 71 currentLoc, 72 actualTypeAnnos, 73 allOnSameTarget, 74 decl); 75 } else if (type instanceof ParameterizedType) { 76 return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, 77 addNesting(type, currentLoc), 78 actualTypeAnnos, 79 allOnSameTarget, 80 decl); 81 } else if (type instanceof WildcardType) { 82 return new AnnotatedWildcardTypeImpl((WildcardType) type, 83 currentLoc, 84 actualTypeAnnos, 85 allOnSameTarget, 86 decl); 87 } 88 throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen."); 89 } 90 91 private static LocationInfo addNesting(Type type, LocationInfo addTo) { 92 if (isArray(type)) 93 return addTo; 94 if (type instanceof Class) { 95 Class<?> clz = (Class)type; 96 if (clz.getEnclosingClass() == null) 97 return addTo; 98 if (Modifier.isStatic(clz.getModifiers())) 99 return addNesting(clz.getEnclosingClass(), addTo); 100 return addNesting(clz.getEnclosingClass(), addTo.pushInner()); 101 } else if (type instanceof ParameterizedType) { 102 ParameterizedType t = (ParameterizedType)type; 103 if (t.getOwnerType() == null) 104 return addTo; 105 return addNesting(t.getOwnerType(), addTo.pushInner()); 106 } 107 return addTo; 108 } 109 110 private static boolean isArray(Type t) { 111 if (t instanceof Class) { 112 Class<?> c = (Class)t; 113 if (c.isArray()) 114 return true; 115 } else if (t instanceof GenericArrayType) { 116 return true; 117 } 118 return false; 119 } 120 121 static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, 122 new TypeAnnotation[0], new TypeAnnotation[0], null); 123 static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0]; 124 125 private static class AnnotatedTypeBaseImpl implements AnnotatedType { 126 private final Type type; 127 private final AnnotatedElement decl; 128 private final LocationInfo location; 129 private final TypeAnnotation[] allOnSameTargetTypeAnnotations; 130 private final Map<Class <? extends Annotation>, Annotation> annotations; 131 132 AnnotatedTypeBaseImpl(Type type, LocationInfo location, 133 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 134 AnnotatedElement decl) { 135 this.type = type; 136 this.decl = decl; 137 this.location = location; 138 this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; 139 this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations)); 140 } 141 142 // AnnotatedElement 143 @Override 144 public final Annotation[] getAnnotations() { 145 return getDeclaredAnnotations(); 146 } 147 148 @Override 149 public final <T extends Annotation> T getAnnotation(Class<T> annotation) { 150 return getDeclaredAnnotation(annotation); 151 } 152 153 @Override 154 public final <T extends Annotation> T[] getAnnotationsByType(Class<T> annotation) { 155 return getDeclaredAnnotationsByType(annotation); 156 } 157 158 @Override 159 public final Annotation[] getDeclaredAnnotations() { 160 return annotations.values().toArray(new Annotation[0]); 161 } 162 163 @Override 164 @SuppressWarnings("unchecked") 165 public final <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) { 166 return (T)annotations.get(annotation); 167 } 168 169 @Override 170 public final <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotation) { 171 return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation); 172 } 173 174 // AnnotatedType 175 @Override 176 public final Type getType() { 177 return type; 178 } 179 180 // Implementation details 181 final LocationInfo getLocation() { 182 return location; 183 } 184 final TypeAnnotation[] getTypeAnnotations() { 185 return allOnSameTargetTypeAnnotations; 186 } 187 final AnnotatedElement getDecl() { 188 return decl; 189 } 190 } 191 192 private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { 193 AnnotatedArrayTypeImpl(Type type, LocationInfo location, 194 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 195 AnnotatedElement decl) { 196 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 197 } 198 199 @Override 200 public AnnotatedType getAnnotatedGenericComponentType() { 201 return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), 202 getLocation().pushArray(), 203 getTypeAnnotations(), 204 getTypeAnnotations(), 205 getDecl()); 206 } 207 208 private Type getComponentType() { 209 Type t = getType(); 210 if (t instanceof Class) { 211 Class<?> c = (Class)t; 212 return c.getComponentType(); 213 } 214 return ((GenericArrayType)t).getGenericComponentType(); 215 } 216 } 217 218 private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { 219 AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location, 220 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 221 AnnotatedElement decl) { 222 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 223 } 224 225 @Override 226 public AnnotatedType[] getAnnotatedBounds() { 227 return getTypeVariable().getAnnotatedBounds(); 228 } 229 230 private TypeVariable<?> getTypeVariable() { 231 return (TypeVariable)getType(); 232 } 233 } 234 235 private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl 236 implements AnnotatedParameterizedType { 237 AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, 238 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 239 AnnotatedElement decl) { 240 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 241 } 242 243 @Override 244 public AnnotatedType[] getAnnotatedActualTypeArguments() { 245 Type[] arguments = getParameterizedType().getActualTypeArguments(); 246 AnnotatedType[] res = new AnnotatedType[arguments.length]; 247 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 248 int initialCapacity = getTypeAnnotations().length; 249 for (int i = 0; i < res.length; i++) { 250 List<TypeAnnotation> l = new ArrayList<>(initialCapacity); 251 LocationInfo newLoc = getLocation().pushTypeArg((byte)i); 252 for (TypeAnnotation t : getTypeAnnotations()) 253 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 254 l.add(t); 255 res[i] = buildAnnotatedType(arguments[i], 256 newLoc, 257 l.toArray(new TypeAnnotation[0]), 258 getTypeAnnotations(), 259 getDecl()); 260 } 261 return res; 262 } 263 264 private ParameterizedType getParameterizedType() { 265 return (ParameterizedType)getType(); 266 } 267 } 268 269 private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { 270 private final boolean hasUpperBounds; 271 AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, 272 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, 273 AnnotatedElement decl) { 274 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); 275 hasUpperBounds = (type.getLowerBounds().length == 0); 276 } 277 278 @Override 279 public AnnotatedType[] getAnnotatedUpperBounds() { 280 if (!hasUpperBounds()) { 281 return new AnnotatedType[] { buildAnnotatedType(Object.class, 282 LocationInfo.BASE_LOCATION, 283 new TypeAnnotation[0], 284 new TypeAnnotation[0], 285 null) 286 }; 287 } 288 return getAnnotatedBounds(getWildcardType().getUpperBounds()); 289 } 290 291 @Override 292 public AnnotatedType[] getAnnotatedLowerBounds() { 293 if (hasUpperBounds) 294 return new AnnotatedType[0]; 295 return getAnnotatedBounds(getWildcardType().getLowerBounds()); 296 } 297 298 private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { 299 AnnotatedType[] res = new AnnotatedType[bounds.length]; 300 Arrays.fill(res, EMPTY_ANNOTATED_TYPE); 301 LocationInfo newLoc = getLocation().pushWildcard(); 302 int initialCapacity = getTypeAnnotations().length; 303 for (int i = 0; i < res.length; i++) { 304 List<TypeAnnotation> l = new ArrayList<>(initialCapacity); 305 for (TypeAnnotation t : getTypeAnnotations()) 306 if (t.getLocationInfo().isSameLocationInfo(newLoc)) 307 l.add(t); 308 res[i] = buildAnnotatedType(bounds[i], 309 newLoc, 310 l.toArray(new TypeAnnotation[0]), 311 getTypeAnnotations(), 312 getDecl()); 313 } 314 return res; 315 } 316 317 private WildcardType getWildcardType() { 318 return (WildcardType)getType(); 319 } 320 321 private boolean hasUpperBounds() { 322 return hasUpperBounds; 323 } 324 } 325 }