/* * #%L * Apache Geronimo JAX-RS Spec 2.0 * %% * Copyright (C) 2003 - 2014 The Apache Software Foundation * %% * 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. * #L% */ package javax.ws.rs.core; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Arrays; import java.util.Stack; public class GenericType<T> { private final Type type; private final Class<?> rawType; protected GenericType() { type = getTypeArgument(getClass(), GenericType.class); rawType = getClass(type); } public GenericType(Type genericType) { if (genericType == null) { throw new IllegalArgumentException("Type must not be null"); } type = genericType; rawType = getClass(type); } public final Type getType() { return type; } public final Class<?> getRawType() { return rawType; } private static Class getClass(Type type) { if (type instanceof Class) { return (Class) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; if (parameterizedType.getRawType() instanceof Class) { return (Class) parameterizedType.getRawType(); } } else if (type instanceof GenericArrayType) { GenericArrayType array = (GenericArrayType) type; final Class<?> componentRawType = getClass(array.getGenericComponentType()); return getArrayClass(componentRawType); } throw new IllegalArgumentException("Type parameter " + type.toString() + " not a class or " + "parameterized type whose raw type is a class"); } private static Class getArrayClass(Class c) { try { Object o = Array.newInstance(c, 0); return o.getClass(); } catch (Exception e) { throw new IllegalArgumentException(e); } } static Type getTypeArgument(Class<?> clazz, Class<?> baseClass) { Stack<Type> superclasses = new Stack<Type>(); Type currentType; Class<?> currentClass = clazz; do { currentType = currentClass.getGenericSuperclass(); superclasses.push(currentType); if (currentType instanceof Class) { currentClass = (Class) currentType; } else if (currentType instanceof ParameterizedType) { currentClass = (Class) ((ParameterizedType) currentType).getRawType(); } } while (!currentClass.equals(baseClass)); TypeVariable tv = baseClass.getTypeParameters()[0]; while (!superclasses.isEmpty()) { currentType = superclasses.pop(); if (currentType instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) currentType; Class<?> rawType = (Class) pt.getRawType(); int argIndex = Arrays.asList(rawType.getTypeParameters()).indexOf(tv); if (argIndex > -1) { Type typeArg = pt.getActualTypeArguments()[argIndex]; if (typeArg instanceof TypeVariable) { tv = (TypeVariable) typeArg; continue; } else { return typeArg; } } } break; } throw new IllegalArgumentException(currentType + " does not specify the type parameter T of GenericType<T>"); } @Override public boolean equals(Object obj) { boolean result = this == obj; if (!result && obj instanceof GenericType) { GenericType<?> that = (GenericType<?>) obj; return this.type.equals(that.type); } return result; } @Override public int hashCode() { return type.hashCode(); } @Override public String toString() { return "GenericType{" + type.toString() + "}"; } }