/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.generictype.impl; import static com.alibaba.citrus.generictype.TypeInfo.*; import static com.alibaba.citrus.util.ArrayUtil.*; import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.CollectionUtil.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.HashMap; import java.util.Map; import com.alibaba.citrus.generictype.ArrayTypeInfo; import com.alibaba.citrus.generictype.BoundedTypeInfo; import com.alibaba.citrus.generictype.ClassTypeInfo; import com.alibaba.citrus.generictype.FieldInfo; import com.alibaba.citrus.generictype.FieldNotFoundException; import com.alibaba.citrus.generictype.GenericDeclarationInfo; import com.alibaba.citrus.generictype.MethodInfo; import com.alibaba.citrus.generictype.MethodNotFoundException; import com.alibaba.citrus.generictype.ParameterizedTypeInfo; import com.alibaba.citrus.generictype.RawTypeInfo; import com.alibaba.citrus.generictype.TypeInfo; import com.alibaba.citrus.generictype.TypeVariableInfo; import com.alibaba.citrus.generictype.WildcardTypeInfo; import com.alibaba.citrus.util.ClassUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 用来创建{@link TypeInfo}的工厂。 * * @author Michael Zhou */ public class TypeInfoFactory extends TypeInfo.Factory { private final Map<Class<?>, TypeInfo> classCache = createConcurrentHashMap(); // XXX! use weak ref instead private static Logger log = LoggerFactory.getLogger(TypeInfo.class); /** 取得指定{@link Type}对应的{@link TypeInfo}对象。 */ @Override public final TypeInfo getType(Type type) { return buildType(type, null); } /** 取得一组{@link TypeInfo}对象。 */ @Override public final TypeInfo[] getTypes(Type[] types) { return buildTypes(types, null); } /** 取得指定{@link GenericDeclaration}对应的{@link GenericDeclarationInfo}对象。 */ @Override public final GenericDeclarationInfo getGenericDeclaration(GenericDeclaration declaration) { return buildGenericDeclaration(declaration, null); } /** 取得指定{@link Field}对应的{@link FieldInfo}对象。 */ @Override public final FieldInfo getField(Field field) { ClassTypeInfo declaringType = getClassType(field.getDeclaringClass()); TypeInfo type = getType(field.getGenericType()); return new FieldImpl(field, declaringType, type); } /** 创建一个参数化类型。 */ @Override public final ParameterizedTypeInfo getParameterizedType(TypeInfo type, TypeInfo... args) { assertTrue(type instanceof RawTypeInfo, "type should be RawTypeInfo"); ParameterizedTypeImpl parameterizedType = new ParameterizedTypeImpl((RawTypeInfo) type); parameterizedType.init(args); return parameterizedType; } /** 创建一个数组类型。 */ @Override public final ArrayTypeInfo getArrayType(TypeInfo componentType, int dimension) { assertTrue(componentType instanceof RawTypeInfo || componentType instanceof ParameterizedTypeInfo || componentType instanceof TypeVariableInfo, "unsupported componentType: %s", componentType); assertTrue(dimension > 0, "dimension"); ArrayTypeInfo arrayType; TypeInfo directComponentType = dimension == 1 ? componentType : getArrayType(componentType, dimension - 1); if (componentType instanceof RawTypeInfo) { Class<?> type = ClassUtil.getArrayClass(componentType.getRawType(), dimension); arrayType = (ArrayTypeInfo) getFromClassCache(type); if (arrayType == null) { arrayType = new ArrayTypeImpl(componentType, directComponentType, dimension, type); saveToClassCache(type, arrayType); } } else { arrayType = new ArrayTypeImpl(componentType, directComponentType, dimension, null); } return arrayType; } /** 从<code>java.lang.reflect.Type</code>创建<code>TypeInfo</code>。 */ private TypeInfo buildType(Type type, BuildingCache buildingCache) { assertNotNull(type, "type"); if (type instanceof Class<?>) { Class<?> clazz = (Class<?>) type; if (clazz.isArray()) { return buildArrayType(clazz, buildingCache); } else { return buildRawType((Class<?>) type, buildingCache); } } else if (type instanceof GenericArrayType) { return buildArrayType((GenericArrayType) type, buildingCache); } else if (type instanceof ParameterizedType) { return buildParameterizedType((ParameterizedType) type, buildingCache); } else if (type instanceof TypeVariable<?>) { return buildTypeVariable((TypeVariable<?>) type, buildingCache); } else if (type instanceof WildcardType) { return buildWildcardType((WildcardType) type, buildingCache); } unreachableCode("Unknown type: %s", type); return null; } /** 创建一组<code>TypeInfo</code>。 */ private TypeInfo[] buildTypes(Type[] types, BuildingCache buildingCache) { if (isEmptyArray(types)) { return new TypeInfo[0]; } if (buildingCache == null) { buildingCache = new BuildingCache(); } TypeInfo[] typeInfos = new TypeInfo[types.length]; for (int i = 0; i < types.length; i++) { typeInfos[i] = buildType(types[i], buildingCache); } return typeInfos; } /** * 从<code>java.lang.reflect.GenericDeclaration</code>创建 * <code>GenericDeclarationInfo</code>。 */ private GenericDeclarationInfo buildGenericDeclaration(GenericDeclaration declaration, BuildingCache buildingCache) { assertNotNull(declaration, "declaration"); if (declaration instanceof Class<?>) { Class<?> clazz = (Class<?>) declaration; assertTrue(!clazz.isArray(), "declaration should not be array class: %s", clazz.getName()); return buildRawType(clazz, buildingCache); } else if (declaration instanceof Method) { return buildMethod((Method) declaration, buildingCache); } else if (declaration instanceof Constructor<?>) { return buildConstructor((Constructor<?>) declaration, buildingCache); } else { unreachableCode("Unknown generic declaration: %s", declaration); return null; } } /** 从非数组<code>Class<?></code>中创建<code>RawTypeInfo</code>。 */ private RawTypeInfo buildRawType(Class<?> type, BuildingCache buildingCache) { RawTypeImpl rawType; // 先查找building cache,假如当前类型已经在build了,则直接返回之。 if (buildingCache != null) { rawType = buildingCache.getRawType(type); if (rawType != null) { return rawType; } } // 否则,查看永久cache,防止重复创建。 rawType = (RawTypeImpl) getFromClassCache(type); if (rawType == null) { log.debug("Buiding type info: {}", type); rawType = new RawTypeImpl(type); rawType.init(buildTypeVariables(type, rawType, buildingCache)); saveToClassCache(type, rawType); } return rawType; } /** 创建type parameters,如果有的话 */ private TypeVariableInfo[] buildTypeVariables(GenericDeclaration declaration, GenericDeclarationInfo declInfo, BuildingCache buildingCache) { TypeVariable<?>[] params = declaration.getTypeParameters(); TypeVariableInfo[] vars = new TypeVariableInfo[params.length]; if (buildingCache == null && params.length > 0) { buildingCache = new BuildingCache(); } if (buildingCache != null) { buildingCache.setGenericDeclaration(declaration, declInfo); } for (int i = 0; i < params.length; i++) { vars[i] = buildTypeVariable(params[i], buildingCache); } return vars; } /** 从数组<code>Class<?></code>中创建<code>ArrayTypeInfo</code>。 */ private ArrayTypeInfo buildArrayType(Class<?> type, BuildingCache buildingCache) { ArrayTypeImpl arrayType = (ArrayTypeImpl) getFromClassCache(type); if (arrayType == null) { int dimension = 0; Class<?> componentClass = type; Class<?> directComponentClass = null; while (componentClass.isArray()) { componentClass = componentClass.getComponentType(); dimension++; if (directComponentClass == null) { directComponentClass = componentClass; } } TypeInfo componentType = buildRawType(componentClass, buildingCache); TypeInfo directComponentType = componentClass.equals(directComponentClass) ? componentType : buildType( directComponentClass, buildingCache); arrayType = new ArrayTypeImpl(componentType, directComponentType, dimension, type); saveToClassCache(type, arrayType); } return arrayType; } /** 从数组<code>GenericArrayType</code>中创建<code>ArrayTypeInfo</code>。 */ private ArrayTypeInfo buildArrayType(GenericArrayType type, BuildingCache buildingCache) { int dimension = 0; Type component = type; Type directComponent = null; // GenericArrayType的成员类型,只可能是三种:Class,TypeVariable和GenericArrayType for (; ; ) { if (component instanceof Class<?>) { if (((Class<?>) component).isArray()) { component = ((Class<?>) component).getComponentType(); } else { break; } } else if (component instanceof GenericArrayType) { component = ((GenericArrayType) component).getGenericComponentType(); } else { break; } dimension++; if (directComponent == null) { directComponent = component; } } TypeInfo componentType = buildType(component, buildingCache); TypeInfo directComponentType = component.equals(directComponent) ? componentType : buildType(directComponent, buildingCache); return new ArrayTypeImpl(componentType, directComponentType, dimension, null); } /** 从<code>ParameterizedType</code>中创建<code>ParameterizedTypeInfo</code>。 */ private ParameterizedTypeInfo buildParameterizedType(ParameterizedType type, BuildingCache buildingCache) { if (buildingCache == null) { buildingCache = new BuildingCache(); } ParameterizedTypeImpl parameterizedTypeInfo = buildingCache.getParameterizedType(type); if (parameterizedTypeInfo == null) { RawTypeInfo rawType = buildRawType((Class<?>) type.getRawType(), buildingCache); parameterizedTypeInfo = new ParameterizedTypeImpl(rawType); buildingCache.setParameterizedType(type, parameterizedTypeInfo); // 取得actual type arguments TypeInfo[] args = buildTypes(type.getActualTypeArguments(), buildingCache); // 修正wildcard的upper bounds为对应var的upper bounds // 例如,var为<T extends Number>,而wildcard未指定upper bounds,那么修正wildcard的upper bounds为Number for (int i = 0; i < args.length; i++) { TypeInfo arg = args[i]; if (arg instanceof WildcardTypeInfo && ((WildcardTypeInfo) arg).isUnknown()) { TypeVariable<?> var = rawType.getRawType().getTypeParameters()[i]; TypeInfo[] upperBounds = buildTypes(var.getBounds(), buildingCache); args[i] = new UnknownWildcardTypeImpl((WildcardTypeInfo) arg, upperBounds); } } parameterizedTypeInfo.init(args); } return parameterizedTypeInfo; } /** 从<code>TypeVariable</code>中创建<code>TypeVariableInfo</code>。 */ private TypeVariableInfo buildTypeVariable(TypeVariable<?> type, BuildingCache buildingCache) { if (buildingCache == null) { buildingCache = new BuildingCache(); } String name = type.getName(); GenericDeclarationInfo declaration = buildGenericDeclaration(type.getGenericDeclaration(), buildingCache); TypeInfo[] upperBounds = buildTypes(type.getBounds(), buildingCache); return new TypeVariableImpl(name, declaration, upperBounds); } /** 从<code>WildcardType</code>中创建<code>WildcardTypeInfo</code>。 */ private WildcardTypeInfo buildWildcardType(WildcardType type, BuildingCache buildingCache) { if (buildingCache == null) { buildingCache = new BuildingCache(); } TypeInfo[] upperBounds = buildTypes(type.getUpperBounds(), buildingCache); TypeInfo[] lowerBounds = buildTypes(type.getLowerBounds(), buildingCache); return new WildcardTypeImpl(upperBounds, lowerBounds); } private MethodInfo buildMethod(Method method, BuildingCache buildingCache) { if (buildingCache == null) { buildingCache = new BuildingCache(); } MethodImpl methodInfo = buildingCache.getMethod(method); if (methodInfo == null) { methodInfo = new MethodImpl(method); buildingCache.setGenericDeclaration(method, methodInfo); buildMethodOrConstructor(methodInfo, method.getGenericReturnType(), method.getGenericParameterTypes(), method.getGenericExceptionTypes(), method.getDeclaringClass(), buildingCache); } return methodInfo; } private MethodInfo buildConstructor(Constructor<?> constructor, BuildingCache buildingCache) { if (buildingCache == null) { buildingCache = new BuildingCache(); } MethodImpl methodInfo = buildingCache.getConstructor(constructor); if (methodInfo == null) { methodInfo = new MethodImpl(constructor); buildingCache.setGenericDeclaration(constructor, methodInfo); buildMethodOrConstructor(methodInfo, null, constructor.getGenericParameterTypes(), constructor.getGenericExceptionTypes(), constructor.getDeclaringClass(), buildingCache); } return methodInfo; } private void buildMethodOrConstructor(MethodImpl method, Type returnType, Type[] parameterTypes, Type[] exceptionTypes, Class<?> declaringClass, BuildingCache buildingCache) { TypeVariableInfo[] vars = buildTypeVariables(method.declaration, method, buildingCache); TypeInfo returnTypeInfo = returnType == null ? TypeInfo.PRIMITIVE_VOID : buildType(returnType, buildingCache); TypeInfo[] parameterTypeInfos = buildTypes(parameterTypes, buildingCache); TypeInfo[] exceptionTypeInfos = buildTypes(exceptionTypes, buildingCache); ClassTypeInfo declaringType = buildRawType(declaringClass, buildingCache); method.init(vars, returnTypeInfo, parameterTypeInfos, exceptionTypeInfos, declaringType); } private TypeInfo getFromClassCache(Class<?> type) { return classCache.get(type); } private void saveToClassCache(Class<?> type, TypeInfo typeInfo) { classCache.put(type, typeInfo); } /** 缓存{@link ParameterizedTypeInfo}、{@link Method}和{@link Constructor}。 */ private static class BuildingCache extends HashMap<Object, GenericDeclarationInfo> { private static final long serialVersionUID = -2169655543193524884L; public RawTypeImpl getRawType(Class<?> type) { return (RawTypeImpl) super.get(type); } public MethodImpl getMethod(Method method) { return (MethodImpl) super.get(method); } public MethodImpl getConstructor(Constructor<?> constructor) { return (MethodImpl) super.get(constructor); } public ParameterizedTypeImpl getParameterizedType(ParameterizedType type) { return (ParameterizedTypeImpl) super.get(type); } public void setGenericDeclaration(GenericDeclaration decl, GenericDeclarationInfo declInfo) { super.put(decl, declInfo); } public void setParameterizedType(ParameterizedType type, ParameterizedTypeImpl typeInfo) { super.put(type, typeInfo); } } /** 在super类型中查找等同于指定类的类型。 */ static TypeInfo findSupertype(TypeInfo type, Class<?> equivalentClass) { for (TypeInfo supertype : type.getSupertypes()) { if (supertype.getRawType().equals(equivalentClass)) { return supertype; } } return null; } /** 在context中查找类型变量对应的实际类型。 */ static TypeInfo resolveTypeVariable(TypeVariableInfo var, GenericDeclarationInfo context, boolean includeBaseType) { GenericDeclarationInfo declaration = assertNotNull(var, "var").getGenericDeclaration(); TypeInfo result = null; // 当前var的declaration可能是: Class,带类型参数的method,带类型参数的constructor。 // // 情形1. delcaration是Class,context也是Class,则在context. // supertypes中查找和declaration匹配的type if (declaration instanceof ClassTypeInfo && context instanceof ClassTypeInfo) { TypeInfo declarationEquivalent = findSupertype((ClassTypeInfo) context, ((ClassTypeInfo) declaration).getRawType()); if (declarationEquivalent != null) { if (!includeBaseType && declarationEquivalent instanceof RawTypeInfo) { result = var; } else { TypeInfo declarationResolved = declarationEquivalent.resolve(context, includeBaseType); assertTrue(declarationResolved instanceof GenericDeclarationInfo, "Unexpected declarationResolved: %s", declarationResolved); result = ((GenericDeclarationInfo) declarationResolved).getActualTypeArgument(var.getName()); } } } // 情形2. declaration是Method,context也是method // 但目前MethodInfo没有实现ParameterizedMethod,故跳过。 // 最后,如果找不到,则返回baseType。 if (result == null) { if (includeBaseType) { result = var.getUpperBounds().get(0).resolve(context, includeBaseType); // baseType.resolve() } else { result = var; } } return result; } /** * 查找非{@link BoundedTypeInfo}。 * <p> * 例如:{@link TypeVariableInfo}:<code><A extends B></code>, * <code><B extends Number></code>,那么,查找<code>A</code>的结果为 * <code>Number</code>。 * </p> * <p> * 再如:{@link WildcardTypeInfo}:<code><? extends B></code>, * <code><B extends Number></code>,那么,查找<code>?</code>的结果为 * <code>Number</code>。 * </p> */ static TypeInfo findNonBoundedType(TypeInfo type) { while (type instanceof BoundedTypeInfo) { type = ((BoundedTypeInfo) type).getBaseType(); } return type; } /** 取得类型中的方法。 */ static MethodInfo getMethod(ClassTypeInfo type, String methodName, Class<?>... paramTypes) { Class<?> rawType = assertNotNull(type, "type").getRawType(); Method method = null; Exception notFound = null; // 先找public方法 try { method = rawType.getMethod(methodName, paramTypes); } catch (java.lang.NoSuchMethodException e) { notFound = e; } // 再找protected/package/private方法 if (method == null) { try { method = rawType.getDeclaredMethod(methodName, paramTypes); } catch (java.lang.NoSuchMethodException e) { notFound = e; } } if (method == null) { throw new MethodNotFoundException(notFound); } return factory.getMethod(method, type); } /** 取得类型中的构造函数。 */ static MethodInfo getConstructor(ClassTypeInfo type, Class<?>... paramTypes) { Class<?> rawType = assertNotNull(type, "type").getRawType(); Constructor<?> constructor = null; Exception notFound = null; try { constructor = rawType.getDeclaredConstructor(paramTypes); } catch (java.lang.NoSuchMethodException e) { notFound = e; } if (constructor == null) { throw new MethodNotFoundException(notFound); } return factory.getConstructor(constructor, type); } /** 取得类型中的字段。 */ static FieldInfo getField(ClassTypeInfo type, ClassTypeInfo declaringType, String name) { Field field = null; try { field = declaringType.getRawType().getDeclaredField(name); } catch (Exception e) { throw new FieldNotFoundException(e); } return factory.getField(field, type); } }