Example #1
0
  /**
   * Method to resolve a TypeVariable to its most <a
   * href="http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#112582">reifiable</a>
   * form.
   *
   * <p>How to resolve a TypeVariable:<br>
   * All of the TypeVariables defined by a generic class will be given a Type by any class that
   * extends it. The Type given may or may not be reifiable; it may be another TypeVariable for
   * instance.
   *
   * <p>Consider <br>
   * <i>class Pair&gt;A,B> { A getA(){...}; ...}</i><br>
   * <i>class StringLongPair extends Pair&gt;String, Long> { }</i><br>
   * To resolve the actual return type of Pair.getA() you must first resolve the TypeVariable "A".
   * We can do that by first finding the index of "A" in the Pair.class.getTypeParameters() array of
   * TypeVariables.
   *
   * <p>To get to the Type provided by StringLongPair you access the generics information by calling
   * StringLongPair.class.getGenericSuperclass; this will be a ParameterizedType. ParameterizedType
   * gives you access to the actual type arguments provided to Pair by StringLongPair. The array is
   * in the same order as the array in Pair.class.getTypeParameters so you can use the index we
   * discovered earlier to extract the Type; String.class.
   *
   * <p>When extracting Types we only have to consider the superclass hierarchy and not the
   * interfaces implemented by the class. When a class implements a generic interface it must
   * provide types for the interface and any generic methods implemented from the interface will be
   * re-defined by the class with its generic type variables.
   *
   * @param typeVariable - the type variable to resolve.
   * @param containingType - the shallowest class in the class hierarchy (furthest from Object)
   *     where typeVariable is defined.
   * @return a Type that has had all possible TypeVariables resolved that have been defined between
   *     the type variable declaration and the containingType.
   */
  private static Type resolve(TypeVariable typeVariable, Type containingType) {
    // The generic declaration is either a Class, Method or Constructor
    final GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();

    if (!(genericDeclaration instanceof Class)) {
      // It's a method or constructor. The best we can do here is try to resolve the bounds
      // e.g. <T extends E> T getT(T param){} where E is defined by the class.
      final Type bounds0 = typeVariable.getBounds()[0];
      return resolve(bounds0, containingType);
    }

    final Class typeVariableOwner = (Class) genericDeclaration;

    // find the typeOwner in the containingType's hierarchy
    final LinkedList<Type> stack = new LinkedList<Type>();

    // If you pass a List<Long> as the containingType then the TypeVariable is going to be resolved
    // by the
    // containingType and not the super class.
    if (containingType instanceof ParameterizedType) {
      stack.add(containingType);
    }

    Class theClass = asClass(containingType);
    Type genericSuperclass = theClass.getGenericSuperclass();
    while (genericSuperclass != null
        && // true for interfaces with no superclass
        !theClass.equals(Object.class)
        && !theClass.equals(typeVariableOwner)) {
      stack.addFirst(genericSuperclass);
      theClass = asClass(genericSuperclass);
      genericSuperclass = theClass.getGenericSuperclass();
    }

    int i = getTypeVariableIndex(typeVariable);
    Type resolved = typeVariable;
    for (Type t : stack) {
      if (t instanceof ParameterizedType) {
        resolved = ((ParameterizedType) t).getActualTypeArguments()[i];
        if (resolved instanceof Class) return resolved;
        if (resolved instanceof TypeVariable) {
          // Need to look at the next class in the hierarchy
          i = getTypeVariableIndex((TypeVariable) resolved);
          continue;
        }
        return resolve(resolved, containingType);
      }
    }

    // the only way we get here is if resolved is still a TypeVariable, otherwise an
    // exception is thrown or a value is returned.
    return ((TypeVariable) resolved).getBounds()[0];
  }
 private void readActualTypeParametersOnDeclaringClass() {
   registerTypeParametersOn(clazz.getTypeParameters());
   registerTypeVariablesOn(clazz.getGenericSuperclass());
   for (Type genericInterface : clazz.getGenericInterfaces()) {
     registerTypeVariablesOn(genericInterface);
   }
 }
Example #3
0
  /**
   * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
   *
   * <p>如public UserDao extends HibernateDao<User,Long>
   *
   * @param clazz clazz The class to introspect
   * @param index the Index of the generic ddeclaration,start from 0.
   * @return the index generic declaration, or Object.class if cannot be determined
   */
  public static Class getSuperClassGenricType(final Class clazz, final int index) {

    Type genType = clazz.getGenericSuperclass();

    if (!(genType instanceof ParameterizedType)) {
      logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
      return Object.class;
    }

    Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

    if (index >= params.length || index < 0) {
      logger.warn(
          "Index: "
              + index
              + ", Size of "
              + clazz.getSimpleName()
              + "'s Parameterized Type: "
              + params.length);
      return Object.class;
    }
    if (!(params[index] instanceof Class)) {
      logger.warn(
          clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
      return Object.class;
    }

    return (Class) params[index];
  }
  @Nullable
  public static Type resolveVariable(
      TypeVariable variable, final Class classType, boolean resolveInInterfacesOnly) {
    final Class aClass = getRawType(classType);
    int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), variable);
    if (index >= 0) {
      return variable;
    }

    final Class[] classes = ReflectionCache.getInterfaces(aClass);
    final Type[] genericInterfaces = ReflectionCache.getGenericInterfaces(aClass);
    for (int i = 0; i <= classes.length; i++) {
      Class anInterface;
      if (i < classes.length) {
        anInterface = classes[i];
      } else {
        anInterface = ReflectionCache.getSuperClass(aClass);
        if (resolveInInterfacesOnly || anInterface == null) {
          continue;
        }
      }
      final Type resolved = resolveVariable(variable, anInterface);
      if (resolved instanceof Class || resolved instanceof ParameterizedType) {
        return resolved;
      }
      if (resolved instanceof TypeVariable) {
        final TypeVariable typeVariable = (TypeVariable) resolved;
        index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(anInterface), typeVariable);
        if (index < 0) {
          LOG.error(
              "Cannot resolve type variable:\n"
                  + "typeVariable = "
                  + typeVariable
                  + "\n"
                  + "genericDeclaration = "
                  + declarationToString(typeVariable.getGenericDeclaration())
                  + "\n"
                  + "searching in "
                  + declarationToString(anInterface));
        }
        final Type type =
            i < genericInterfaces.length ? genericInterfaces[i] : aClass.getGenericSuperclass();
        if (type instanceof Class) {
          return Object.class;
        }
        if (type instanceof ParameterizedType) {
          return getActualTypeArguments((ParameterizedType) type)[index];
        }
        throw new AssertionError("Invalid type: " + type);
      }
    }
    return null;
  }
  protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
    String name = aClass.getName();
    if (myVisited.add(aClass)) {
      try {
        for (Method method : aClass.getDeclaredMethods()) {
          loadTypeDependencies(method.getGenericReturnType());
          for (Type type : method.getGenericExceptionTypes()) {
            loadTypeDependencies(type);
          }
          for (Type type : method.getGenericParameterTypes()) {
            loadTypeDependencies(type);
          }
        }
        for (Constructor method : aClass.getDeclaredConstructors()) {
          for (Type type : method.getGenericExceptionTypes()) {
            loadTypeDependencies(type);
          }
          for (Type type : method.getGenericParameterTypes()) {
            loadTypeDependencies(type);
          }
        }

        for (Field field : aClass.getDeclaredFields()) {
          loadTypeDependencies(field.getGenericType());
        }

        Type superclass = aClass.getGenericSuperclass();
        if (superclass != null) {
          loadClassDependencies(aClass);
        }

        for (Type intf : aClass.getGenericInterfaces()) {
          loadTypeDependencies(intf);
        }

        aClass.getAnnotations();
        Package aPackage = aClass.getPackage();
        if (aPackage != null) {
          aPackage.getAnnotations();
        }
      } catch (LinkageError e) {
        throw new ClassNotFoundException(name);
      } catch (TypeNotPresentException e) {
        throw new ClassNotFoundException(name);
      }
    }
  }
 @Override
 public List<ReferenceTypeUsage> getAllAncestors(Resolver resolver) {
   List<ReferenceTypeUsage> ancestors = new ArrayList<>();
   if (clazz.getSuperclass() != null) {
     ReferenceTypeUsage superTypeDefinition =
         toReferenceTypeUsage(clazz.getSuperclass(), clazz.getGenericSuperclass());
     ancestors.add(superTypeDefinition);
     ancestors.addAll(superTypeDefinition.getAllAncestors(resolver));
   }
   int i = 0;
   for (Class<?> interfaze : clazz.getInterfaces()) {
     Type genericInterfaze = clazz.getGenericInterfaces()[i];
     ReferenceTypeUsage superTypeDefinition = toReferenceTypeUsage(interfaze, genericInterfaze);
     ancestors.add(superTypeDefinition);
     ancestors.addAll(superTypeDefinition.getAllAncestors(resolver));
     i++;
   }
   return ancestors;
 }
Example #7
0
  public void configureClassNode(CompileUnit compileUnit, ClassNode classNode) {
    Class clazz = classNode.getTypeClass();
    Field[] fields = clazz.getDeclaredFields();
    for (Field f : fields) {
      ClassNode ret = makeClassNode(compileUnit, f.getGenericType(), f.getType());
      classNode.addField(f.getName(), f.getModifiers(), ret, null);
    }
    Method[] methods = clazz.getDeclaredMethods();
    for (Method m : methods) {
      ClassNode ret = makeClassNode(compileUnit, m.getGenericReturnType(), m.getReturnType());
      Parameter[] params =
          makeParameters(compileUnit, m.getGenericParameterTypes(), m.getParameterTypes());
      ClassNode[] exceptions =
          makeClassNodes(compileUnit, m.getGenericExceptionTypes(), m.getExceptionTypes());
      MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ret, params, exceptions, null);
      setMethodDefaultValue(mn, m);
      setAnnotationMetaData(m.getAnnotations(), mn);
      mn.setGenericsTypes(configureTypeVariable(m.getTypeParameters()));
      classNode.addMethod(mn);
    }
    Constructor[] constructors = clazz.getDeclaredConstructors();
    for (Constructor ctor : constructors) {
      Parameter[] params =
          makeParameters(compileUnit, ctor.getGenericParameterTypes(), ctor.getParameterTypes());
      ClassNode[] exceptions =
          makeClassNodes(compileUnit, ctor.getGenericExceptionTypes(), ctor.getExceptionTypes());
      classNode.addConstructor(ctor.getModifiers(), params, exceptions, null);
    }

    Class sc = clazz.getSuperclass();
    if (sc != null)
      classNode.setUnresolvedSuperClass(
          makeClassNode(compileUnit, clazz.getGenericSuperclass(), sc));
    makeInterfaceTypes(compileUnit, classNode, clazz);
    setAnnotationMetaData(classNode.getTypeClass().getAnnotations(), classNode);

    PackageNode packageNode = classNode.getPackage();
    if (packageNode != null) {
      setAnnotationMetaData(classNode.getTypeClass().getPackage().getAnnotations(), packageNode);
    }
  }
Example #8
0
  protected void _resolveBindings(Type t) {
    if (t == null) return;

    Class<?> raw;
    if (t instanceof ParameterizedType) {
      ParameterizedType pt = (ParameterizedType) t;
      Type[] args = pt.getActualTypeArguments();
      if (args != null && args.length > 0) {
        Class<?> rawType = (Class<?>) pt.getRawType();
        TypeVariable<?>[] vars = rawType.getTypeParameters();
        if (vars.length != args.length) {
          throw new IllegalArgumentException(
              "Strange parametrized type (in class "
                  + rawType.getName()
                  + "): number of type arguments != number of type parameters ("
                  + args.length
                  + " vs "
                  + vars.length
                  + ")");
        }
        for (int i = 0, len = args.length; i < len; ++i) {
          TypeVariable<?> var = vars[i];
          String name = var.getName();
          if (_bindings == null) {
            _bindings = new LinkedHashMap<String, JavaType>();
          } else {
            /* 24-Mar-2010, tatu: Better ensure that we do not overwrite something
             *  collected earlier (since we descend towards super-classes):
             */
            if (_bindings.containsKey(name)) continue;
          }
          // first: add a placeholder to prevent infinite loops
          _addPlaceholder(name);
          // then resolve type
          _bindings.put(name, _typeFactory._constructType(args[i], this));
        }
      }
      raw = (Class<?>) pt.getRawType();
    } else if (t instanceof Class<?>) {
      raw = (Class<?>) t;
      /* [JACKSON-677]: If this is an inner class then the generics are defined on the
       * enclosing class so we have to check there as well.  We don't
       * need to call getEnclosingClass since anonymous classes declare
       * generics
       */
      _resolveBindings(raw.getDeclaringClass());
      /* 24-Mar-2010, tatu: Can not have true generics definitions, but can
       *   have lower bounds ("<T extends BeanBase>") in declaration itself
       */
      TypeVariable<?>[] vars = raw.getTypeParameters();
      if (vars != null && vars.length > 0) {
        JavaType[] typeParams = null;

        if (_contextType != null && raw.isAssignableFrom(_contextType.getRawClass())) {
          typeParams = _typeFactory.findTypeParameters(_contextType, raw);
        }

        for (int i = 0; i < vars.length; i++) {
          TypeVariable<?> var = vars[i];

          String name = var.getName();
          Type varType = var.getBounds()[0];
          if (varType != null) {
            if (_bindings == null) {
              _bindings = new LinkedHashMap<String, JavaType>();
            } else { // and no overwriting...
              if (_bindings.containsKey(name)) continue;
            }
            _addPlaceholder(name); // to prevent infinite loops

            if (typeParams != null) {
              _bindings.put(name, typeParams[i]);
            } else {
              _bindings.put(name, _typeFactory._constructType(varType, this));
            }
          }
        }
      }
    } else { // probably can't be any of these... so let's skip for now
      // if (type instanceof GenericArrayType) {
      // if (type instanceof TypeVariable<?>) {
      // if (type instanceof WildcardType) {
      return;
    }
    // but even if it's not a parameterized type, its super types may be:
    _resolveBindings(raw.getGenericSuperclass());
    for (Type intType : raw.getGenericInterfaces()) {
      _resolveBindings(intType);
    }
  }
Example #9
0
  /**
   * Determines if the suspected super type is assignable from the suspected sub type.
   *
   * @param suspectedSuperType e.g. {@code GenericDAO<Pet, String>}
   * @param suspectedSubType e.g. {@code PetDAO extends GenericDAO<Pet,String>}
   * @return true if (sourceType)targetClass is a valid cast
   */
  public static boolean isAssignableFrom(Type suspectedSuperType, Type suspectedSubType) {
    final Class suspectedSuperClass = asClass(suspectedSuperType);
    final Class suspectedSubClass = asClass(suspectedSubType);

    // The raw types need to be compatible.
    if (!suspectedSuperClass.isAssignableFrom(suspectedSubClass)) {
      return false;
    }

    // From this point we know that the raw types are assignable.
    // We need to figure out what the generic parameters in the targetClass are
    // as they pertain to the sourceType.

    if (suspectedSuperType instanceof WildcardType) {
      // ? extends Number
      // needs to match all the bounds (there will only be upper bounds or lower bounds
      for (Type t : ((WildcardType) suspectedSuperType).getUpperBounds()) {
        if (!isAssignableFrom(t, suspectedSubType)) return false;
      }
      for (Type t : ((WildcardType) suspectedSuperType).getLowerBounds()) {
        if (!isAssignableFrom(suspectedSubType, t)) return false;
      }
      return true;
    }

    Type curType = suspectedSubType;
    Class curClass;

    while (curType != null && !curType.equals(Object.class)) {
      curClass = asClass(curType);

      if (curClass.equals(suspectedSuperClass)) {
        final Type resolved = resolve(curType, suspectedSubType);

        if (suspectedSuperType instanceof Class) {
          if (resolved instanceof Class) return suspectedSuperType.equals(resolved);

          // They may represent the same class, but the suspectedSuperType is not parameterized. The
          // parameter
          // types default to Object so they must be a match.
          // e.g. Pair p = new StringLongPair();
          //      Pair p = new Pair<? extends Number, String>

          return true;
        }

        if (suspectedSuperType instanceof ParameterizedType) {
          if (resolved instanceof ParameterizedType) {
            final Type[] type1Arguments =
                ((ParameterizedType) suspectedSuperType).getActualTypeArguments();
            final Type[] type2Arguments = ((ParameterizedType) resolved).getActualTypeArguments();
            if (type1Arguments.length != type2Arguments.length) return false;

            for (int i = 0; i < type1Arguments.length; ++i) {
              if (!isAssignableFrom(type1Arguments[i], type2Arguments[i])) return false;
            }
            return true;
          }
        } else if (suspectedSuperType instanceof GenericArrayType) {
          if (resolved instanceof GenericArrayType) {
            return isAssignableFrom(
                ((GenericArrayType) suspectedSuperType).getGenericComponentType(),
                ((GenericArrayType) resolved).getGenericComponentType());
          }
        }

        return false;
      }

      final Type[] types = curClass.getGenericInterfaces();
      for (Type t : types) {
        final Type resolved = resolve(t, suspectedSubType);
        if (isAssignableFrom(suspectedSuperType, resolved)) return true;
      }

      curType = curClass.getGenericSuperclass();
    }
    return false;
  }
Example #10
0
  /**
   * Gets the actual type arguments that are used in a given implementation of a given generic base
   * class or interface. (Based on code copyright 2007 by Ian Robertson).
   *
   * @param base the generic base class or interface
   * @param implementation the type (potentially) implementing the given base class or interface
   * @return a list of the raw classes for the actual type arguments.
   */
  @NotNull
  public static List<Class<?>> getTypeArguments(
      @NotNull Class<?> base, @NotNull Class<?> implementation) {
    Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();

    // first we need to resolve all supertypes up to the required base class or interface
    // and find the right Type for it
    Type type;

    Queue<Type> toCheck = new LinkedList<Type>();
    toCheck.add(implementation);
    while (true) {
      // if we have checked everything and not found the base class we return an empty list
      if (toCheck.isEmpty()) return ImmutableList.of();

      type = toCheck.remove();
      Class<?> clazz;

      if (type instanceof Class) {
        // there is no useful information for us in raw types, so just keep going up the inheritance
        // chain
        clazz = (Class) type;
        if (base.isInterface()) {
          // if we are actually looking for the type parameters to an interface we also need to
          // look at all the ones implemented by the given current one
          toCheck.addAll(Arrays.asList(clazz.getGenericInterfaces()));
        }
      } else if (type instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) type;
        clazz = (Class) parameterizedType.getRawType();

        // for instances of ParameterizedType we extract and remember all type arguments
        TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        for (int i = 0; i < actualTypeArguments.length; i++) {
          resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
        }
      } else {
        return ImmutableList.of();
      }

      // we can stop if we have reached the sought for base type
      if (base.equals(getClass(type))) break;

      toCheck.add(clazz.getGenericSuperclass());
    }

    // finally, for each actual type argument provided to baseClass,
    // determine (if possible) the raw class for that type argument.
    Type[] actualTypeArguments;
    if (type instanceof Class) {
      actualTypeArguments = ((Class) type).getTypeParameters();
    } else {
      actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
    }
    List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
    // resolve types by chasing down type variables.
    for (Type baseType : actualTypeArguments) {
      while (resolvedTypes.containsKey(baseType)) {
        baseType = resolvedTypes.get(baseType);
      }
      typeArgumentsAsClasses.add(getClass(baseType));
    }
    return typeArgumentsAsClasses;
  }