/* | |
* #%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() + "}"; | |
} | |
} |