/*
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.internal.util;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.GenericType;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.OsgiRegistry;
import org.glassfish.jersey.internal.util.collection.ClassTypePair;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
Utility methods for Java reflection.
Author: Paul Sandoz, Jakub Podlesak
/**
* Utility methods for Java reflection.
*
* @author Paul Sandoz
* @author Jakub Podlesak
*/
public final class ReflectionHelper {
private static final Logger LOGGER = Logger.getLogger(ReflectionHelper.class.getName());
private static final PrivilegedAction<?> NoOpPrivilegedACTION = new PrivilegedAction<Object>() {
@Override
public Object run() {
return null;
}
};
Prevents instantiation.
/**
* Prevents instantiation.
*/
private ReflectionHelper() {
throw new AssertionError("No instances allowed.");
}
Get the declaring class of an accessible object.
Supported are Method
, Field
and Constructor
accessible object types.
Params: - ao – an accessible object.
Throws: - IllegalArgumentException – in case the type of the accessible object
is not supported.
Returns: the declaring class of an accessible object.
/**
* Get the declaring class of an accessible object.
* <p>
* Supported are {@link Method}, {@link Field} and {@link Constructor} accessible object types.
* </p>
*
* @param ao an accessible object.
* @return the declaring class of an accessible object.
* @throws IllegalArgumentException in case the type of the accessible object
* is not supported.
*/
public static Class<?> getDeclaringClass(final AccessibleObject ao) {
if (ao instanceof Member && (ao instanceof Field || ao instanceof Method || ao instanceof Constructor)) {
return ((Member) ao).getDeclaringClass();
} else {
throw new IllegalArgumentException("Unsupported accessible object type: " + ao.getClass().getName());
}
}
Create a string representation of an object.
Returns a string consisting of the name of the class of which the object is an instance, the at-sign character '@'
, and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
o.getClass().getName() + '@' + Integer.toHexString(o.hashCode())
Params: - o – the object.
Returns: the string representation of the object.
/**
* Create a string representation of an object.
* <p>
* Returns a string consisting of the name of the class of which the
* object is an instance, the at-sign character {@code '@'}, and
* the unsigned hexadecimal representation of the hash code of the
* object. In other words, this method returns a string equal to the
* value of:
* </p>
* <pre>
* o.getClass().getName() + '@' + Integer.toHexString(o.hashCode())
* </pre>
*
* @param o the object.
* @return the string representation of the object.
*/
public static String objectToString(final Object o) {
if (o == null) {
return "null";
}
return o.getClass().getName() + '@' + Integer.toHexString(o.hashCode());
}
Create a string representation of a method and an instance whose
class implements the method.
Returns a string consisting of the name of the class of which the object is an instance, the at-sign character '@'
, the unsigned hexadecimal representation of the hash code of the object, the character '.'
, the name of the method, the character '('
, the list of method parameters, and the character ')'
. In other words, those method returns a string equal to the value of:
o.getClass().getName() + '@' + Integer.toHexString(o.hashCode()) +
'.' + m.getName() + '(' + <parameters> + ')'.
Params: - o – the object whose class implements
m
. - m – the method.
Returns: the string representation of the method and instance.
/**
* Create a string representation of a method and an instance whose
* class implements the method.
* <p>
* Returns a string consisting of the name of the class of which the object
* is an instance, the at-sign character {@code '@'},
* the unsigned hexadecimal representation of the hash code of the
* object, the character {@code '.'}, the name of the method,
* the character {@code '('}, the list of method parameters, and
* the character {@code ')'}. In other words, those method returns a
* string equal to the value of:
* </p>
* <pre>
* o.getClass().getName() + '@' + Integer.toHexString(o.hashCode()) +
* '.' + m.getName() + '(' + <parameters> + ')'.</pre>
*
* @param o the object whose class implements {@code m}.
* @param m the method.
* @return the string representation of the method and instance.
*/
public static String methodInstanceToString(final Object o, final Method m) {
final StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName())
.append('@').append(Integer.toHexString(o.hashCode()))
.append('.').append(m.getName()).append('(');
final Class[] params = m.getParameterTypes();
for (int i = 0; i < params.length; i++) {
sb.append(getTypeName(params[i]));
if (i < (params.length - 1)) {
sb.append(",");
}
}
sb.append(')');
return sb.toString();
}
Get the Java type or array name.
If the class is representing an array, the "[]"
suffix will be added to the name of the type for each dimension of an array.
Params: - type – Java type (can represent an array).
Returns: Java type or array name.
/**
* Get the Java type or array name.
* <p>
* If the class is representing an array, the {@code "[]"} suffix will be added
* to the name of the type for each dimension of an array.
* </p>
*
* @param type Java type (can represent an array).
* @return Java type or array name.
*/
private static String getTypeName(final Class<?> type) {
if (type.isArray()) {
Class<?> cl = type;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
final StringBuilder sb = new StringBuilder();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
}
return type.getName();
}
Get privileged action to obtain Class from given class name.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
The context class loader will be utilized if accessible and non-null.
Otherwise the defining class loader of this class will
be utilized.
Params: - name – class name.
Type parameters: - <T> – class type.
See Also: Returns: privileged action to obtain desired Class. The action could return null
if the class cannot be found.
/**
* Get privileged action to obtain Class from given class name.
* <p>
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
* The context class loader will be utilized if accessible and non-null.
* Otherwise the defining class loader of this class will
* be utilized.
* </p>
*
* @param <T> class type.
* @param name class name.
* @return privileged action to obtain desired Class.
* The action could return {@code null} if the class cannot be found.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static <T> PrivilegedAction<Class<T>> classForNamePA(final String name) {
return classForNamePA(name, getContextClassLoader());
}
Get privileged action to obtain Class from given class name.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - name – class name.
- cl – class loader to use, if
null
then the defining class loader of this class will be utilized.
Type parameters: - <T> – class type.
See Also: Returns: privileged action to obtain desired Class. The action could return null
if the class cannot be found.
/**
* Get privileged action to obtain Class from given class name.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param <T> class type.
* @param name class name.
* @param cl class loader to use, if {@code null} then the defining class loader
* of this class will be utilized.
* @return privileged action to obtain desired Class. The action could return {@code null} if the class cannot be found.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
@SuppressWarnings("unchecked")
public static <T> PrivilegedAction<Class<T>> classForNamePA(final String name, final ClassLoader cl) {
return new PrivilegedAction<Class<T>>() {
@Override
public Class<T> run() {
if (cl != null) {
try {
return (Class<T>) Class.forName(name, false, cl);
} catch (final ClassNotFoundException ex) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER,
"Unable to load class " + name + " using the supplied class loader "
+ cl.getClass().getName() + ".", ex);
}
}
}
try {
return (Class<T>) Class.forName(name);
} catch (final ClassNotFoundException ex) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, "Unable to load class " + name + " using the current class loader.", ex);
}
}
return null;
}
};
}
Get privileged action to obtain class loader for given class.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get class loader.
See Also: Returns: privileged action to obtain class loader for the clazz
class.
/**
* Get privileged action to obtain class loader for given class.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get class loader.
* @return privileged action to obtain class loader for the {@code clazz} class.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<ClassLoader> getClassLoaderPA(final Class<?> clazz) {
return new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return clazz.getClassLoader();
}
};
}
Get privileged action to obtain fields declared on given class.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get the declared fields.
See Also: Returns: privileged action to obtain fields declared on the clazz
class.
/**
* Get privileged action to obtain fields declared on given class.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get the declared fields.
* @return privileged action to obtain fields declared on the {@code clazz} class.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Field[]> getDeclaredFieldsPA(final Class<?> clazz) {
return new PrivilegedAction<Field[]>() {
@Override
public Field[] run() {
return clazz.getDeclaredFields();
}
};
}
Get privileged action to obtain fields on given class, recursively through inheritance hierarchy.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get fields.
See Also: Returns: privileged action to obtain fields declared on the clazz
class.
/**
* Get privileged action to obtain fields on given class, recursively through inheritance hierarchy.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get fields.
* @return privileged action to obtain fields declared on the {@code clazz} class.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Field[]> getAllFieldsPA(final Class<?> clazz) {
return new PrivilegedAction<Field[]>() {
@Override
public Field[] run() {
final List<Field> fields = new ArrayList<Field>();
recurse(clazz, fields);
return fields.toArray(new Field[fields.size()]);
}
private void recurse(final Class<?> clazz, final List<Field> fields) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (clazz.getSuperclass() != null) {
recurse(clazz.getSuperclass(), fields);
}
}
};
}
Get privileged action to obtain methods declared on given class.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get the declared methods.
See Also: Returns: privileged action to obtain methods declared on the clazz
class.
/**
* Get privileged action to obtain methods declared on given class.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get the declared methods.
* @return privileged action to obtain methods declared on the {@code clazz} class.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Collection<? extends Method>> getDeclaredMethodsPA(final Class<?> clazz) {
return new PrivilegedAction<Collection<? extends Method>>() {
@Override
public Collection<? extends Method> run() {
return Arrays.asList(clazz.getDeclaredMethods());
}
};
}
Get privileged exception action to obtain Class from given class name.
If run using security manager, the returned privileged exception action
must be invoked within a doPrivileged block.
The actual context class loader will be utilized if accessible and non-null.
Otherwise the defining class loader of the calling class will be utilized.
Params: - name – class name.
Type parameters: - <T> – class type.
Throws: - ClassNotFoundException – in case the class cannot be loaded with the context class loader.
See Also: Returns: privileged exception action to obtain the Class. The action could throw ClassNotFoundException
or return null
if the class cannot be found.
/**
* Get privileged exception action to obtain Class from given class name.
* If run using security manager, the returned privileged exception action
* must be invoked within a doPrivileged block.
* <p/>
* The actual context class loader will be utilized if accessible and non-null.
* Otherwise the defining class loader of the calling class will be utilized.
*
* @param <T> class type.
* @param name class name.
* @return privileged exception action to obtain the Class.
* The action could throw {@link ClassNotFoundException} or return {@code null} if the class cannot be found.
* @throws ClassNotFoundException in case the class cannot be loaded with the context class loader.
* @see AccessController#doPrivileged(java.security.PrivilegedExceptionAction)
*/
public static <T> PrivilegedExceptionAction<Class<T>> classForNameWithExceptionPEA(final String name)
throws ClassNotFoundException {
return classForNameWithExceptionPEA(name, getContextClassLoader());
}
Get privileged exception action to obtain Class from given class name.
If run using security manager, the returned privileged exception action
must be invoked within a doPrivileged block.
Params: - name – class name.
- cl – class loader to use, if
null
then the defining class loader of the calling class will be utilized.
Type parameters: - <T> – class type.
Throws: - ClassNotFoundException – in case the class cannot be loaded with the specified class loader.
See Also: Returns: privileged exception action to obtain the Class. If the class cannot be found, the action returns null
, or throws ClassNotFoundException
in case the class loader has been specified.
/**
* Get privileged exception action to obtain Class from given class name.
* If run using security manager, the returned privileged exception action
* must be invoked within a doPrivileged block.
*
* @param <T> class type.
* @param name class name.
* @param cl class loader to use, if {@code null} then the defining class loader
* of the calling class will be utilized.
* @return privileged exception action to obtain the Class. If the class cannot be found, the action returns {@code null},
* or throws {@link ClassNotFoundException} in case the class loader has been specified.
* @throws ClassNotFoundException in case the class cannot be loaded with the specified class loader.
* @see AccessController#doPrivileged(java.security.PrivilegedExceptionAction)
*/
@SuppressWarnings("unchecked")
public static <T> PrivilegedExceptionAction<Class<T>> classForNameWithExceptionPEA(final String name, final ClassLoader cl)
throws ClassNotFoundException {
return new PrivilegedExceptionAction<Class<T>>() {
@Override
public Class<T> run() throws ClassNotFoundException {
if (cl != null) {
try {
return (Class<T>) Class.forName(name, false, cl);
} catch (final ClassNotFoundException ex) {
// ignored on purpose
}
}
return (Class<T>) Class.forName(name);
}
};
}
Get privileged action to obtain context class loader.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
See Also: Returns: privileged action to obtain the actual context class loader. The action could return null
if the context class loader has not been set.
/**
* Get privileged action to obtain context class loader.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @return privileged action to obtain the actual context class loader. The action could return {@code null}
* if the context class loader has not been set.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<ClassLoader> getContextClassLoaderPA() {
return new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
};
}
Get the context class loader.
Returns: the context class loader, otherwise null
if not set.
/**
* Get the context class loader.
*
* @return the context class loader, otherwise {@code null} if not set.
*/
private static ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(getContextClassLoaderPA());
}
Get privileged action to set the actual context class loader.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - classLoader – context class loader to be set.
See Also: Returns: privileged action to set context class loader.
/**
* Get privileged action to set the actual context class loader.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param classLoader context class loader to be set.
* @return privileged action to set context class loader.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction setContextClassLoaderPA(final ClassLoader classLoader) {
return new PrivilegedAction() {
@Override
public Object run() {
Thread.currentThread().setContextClassLoader(classLoader);
return null;
}
};
}
Get privileged action to set a method to be accessible.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - m – method to be set as accessible.
See Also: Returns: privileged action to set the method to be accessible.
/**
* Get privileged action to set a method to be accessible.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param m method to be set as accessible.
* @return privileged action to set the method to be accessible.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction setAccessibleMethodPA(final Method m) {
if (Modifier.isPublic(m.getModifiers())) {
return NoOpPrivilegedACTION;
}
return new PrivilegedAction<Object>() {
@Override
public Object run() {
if (!m.isAccessible()) {
m.setAccessible(true);
}
return m;
}
};
}
Get the list of classes that represent the type arguments of a parameterized
input type.
For any given argument in the returned list, following rules apply:
- If a type argument is a class then the class is returned.
- If the type argument is a generic array type and the generic component
type is a class then class of the array is returned.
- If the type argument is a parameterized type and it's raw type is a
class then that class is returned.
If the type
is not an instance of ParameterizedType an empty list is returned. Params: - type – parameterized type.
Throws: - IllegalArgumentException – if any of the generic type arguments is
not a class, or a generic array type, or the generic component type
of the generic array type is not class, or not a parameterized type
with a raw type that is not a class.
Returns: the list of classed representing the actual type arguments. May be empty, but may never be null
.
/**
* Get the list of classes that represent the type arguments of a
* {@link ParameterizedType parameterized} input type.
* <p/>
* For any given argument in the returned list, following rules apply:
* <ul>
* <li>If a type argument is a class then the class is returned.</li>
* <li>If the type argument is a generic array type and the generic component
* type is a class then class of the array is returned.</li>
* <li>If the type argument is a parameterized type and it's raw type is a
* class then that class is returned.</li>
* </ul>
* If the {@code type} is not an instance of ParameterizedType an empty
* list is returned.
*
* @param type parameterized type.
* @return the list of classed representing the actual type arguments. May be empty,
* but may never be {@code null}.
* @throws IllegalArgumentException if any of the generic type arguments is
* not a class, or a generic array type, or the generic component type
* of the generic array type is not class, or not a parameterized type
* with a raw type that is not a class.
*/
public static List<Class<?>> getGenericTypeArgumentClasses(final Type type) throws IllegalArgumentException {
final Type[] types = getTypeArguments(type);
if (types == null) {
return Collections.emptyList();
}
return Arrays.stream(types)
.map((Function<Type, Class<?>>) ReflectionHelper::erasure)
.collect(Collectors.toList());
}
Get the list of class-type pairs that represent the type arguments of a parameterized
input type. For any given class
part of each pair in the returned list, following rules apply:
- If a type argument is a class then the class is returned as raw class.
- If the type argument is a generic array type and the generic component
type is a class then class of the array is returned as raw class.
- If the type argument is a parameterized type and it's raw type is a
class then that class is returned as raw class.
If the type
is not an instance of ParameterizedType an empty list is returned. Params: - type – parameterized type.
Throws: - IllegalArgumentException – if any of the generic type arguments is
not a class, or a generic array type, or the generic component type
of the generic array type is not class, or not a parameterized type
with a raw type that is not a class.
Returns: the list of class-type pairs representing the actual type arguments. May be empty, but may never be null
.
/**
* Get the list of class-type pairs that represent the type arguments of a
* {@link ParameterizedType parameterized} input type.
* <p/>
* For any given {@link ClassTypePair#rawClass() class} part of each pair
* in the returned list, following rules apply:
* <ul>
* <li>If a type argument is a class then the class is returned as raw class.</li>
* <li>If the type argument is a generic array type and the generic component
* type is a class then class of the array is returned as raw class.</li>
* <li>If the type argument is a parameterized type and it's raw type is a
* class then that class is returned as raw class.</li>
* </ul>
* If the {@code type} is not an instance of ParameterizedType an empty
* list is returned.
*
* @param type parameterized type.
* @return the list of class-type pairs representing the actual type arguments. May be empty, but may never be {@code null}.
* @throws IllegalArgumentException if any of the generic type arguments is
* not a class, or a generic array type, or the generic component type
* of the generic array type is not class, or not a parameterized type
* with a raw type that is not a class.
*/
public static List<ClassTypePair> getTypeArgumentAndClass(final Type type) throws IllegalArgumentException {
final Type[] types = getTypeArguments(type);
if (types == null) {
return Collections.emptyList();
}
return Arrays.stream(types)
.map(type1 -> ClassTypePair.of(erasure(type1), type1))
.collect(Collectors.toList());
}
Check if the given type is a primitive type.
Params: - type – type to be checked.
Returns: true
in case the type represents a primitive type, otherwise returns false
.
/**
* Check if the given type is a primitive type.
*
* @param type type to be checked.
* @return {@code true} in case the type represents a primitive type, otherwise returns {@code false}.
*/
public static boolean isPrimitive(final Type type) {
if (type instanceof Class) {
final Class c = (Class) type;
return c.isPrimitive();
}
return false;
}
Get the type arguments for a parameterized type.
In case the type is not a parameterized type
, the method returns null
. Params: - type – parameterized type.
Returns: type arguments for a parameterized type, or null
in case the input type is not a parameterized type.
/**
* Get the type arguments for a parameterized type.
* <p/>
* In case the type is not a {@link ParameterizedType parameterized type},
* the method returns {@code null}.
*
* @param type parameterized type.
* @return type arguments for a parameterized type, or {@code null} in case the input type is not a parameterized type.
*/
public static Type[] getTypeArguments(final Type type) {
if (!(type instanceof ParameterizedType)) {
return null;
}
return ((ParameterizedType) type).getActualTypeArguments();
}
Get a type argument at particular index for a parameterized type.
In case the type is not a parameterized type
, the method returns null
. Params: - type – parameterized type.
- index – type parameter index.
Returns: type argument for a parameterized type at a given index, or null
in case the input type is not a parameterized type.
/**
* Get a type argument at particular index for a parameterized type.
* <p/>
* In case the type is not a {@link ParameterizedType parameterized type},
* the method returns {@code null}.
*
* @param type parameterized type.
* @param index type parameter index.
* @return type argument for a parameterized type at a given index, or {@code null} in case the input type is not
* a parameterized type.
*/
public static Type getTypeArgument(final Type type, final int index) {
if (type instanceof ParameterizedType) {
final ParameterizedType p = (ParameterizedType) type;
return fix(p.getActualTypeArguments()[index]);
}
return null;
}
JDK 5.0 has a bug of creating GenericArrayType
where it shouldn't. fix that manually to work around the problem.
See bug 6202725.
/**
* JDK 5.0 has a bug of creating {@link GenericArrayType} where it shouldn't.
* fix that manually to work around the problem.
* <p/>
* See bug 6202725.
*/
private static Type fix(final Type t) {
if (!(t instanceof GenericArrayType)) {
return t;
}
final GenericArrayType gat = (GenericArrayType) t;
if (gat.getGenericComponentType() instanceof Class) {
final Class c = (Class) gat.getGenericComponentType();
return Array.newInstance(c, 0).getClass();
}
return t;
}
Implements the logic for erasure(Type)
. /**
* Implements the logic for {@link #erasure(Type)}.
*/
private static final TypeVisitor<Class> eraser = new TypeVisitor<Class>() {
@Override
protected Class onClass(final Class clazz) {
return clazz;
}
@Override
protected Class onParameterizedType(final ParameterizedType type) {
return visit(type.getRawType());
}
@Override
protected Class onGenericArray(final GenericArrayType type) {
return Array.newInstance(visit(type.getGenericComponentType()), 0).getClass();
}
@Override
protected Class onVariable(final TypeVariable type) {
return visit(type.getBounds()[0]);
}
@Override
protected Class onWildcard(final WildcardType type) {
return visit(type.getUpperBounds()[0]);
}
@Override
protected RuntimeException createError(final Type type) {
return new IllegalArgumentException(LocalizationMessages.TYPE_TO_CLASS_CONVERSION_NOT_SUPPORTED(type));
}
};
Get the Class
representation of the given type.
This corresponds to the notion of the erasure in JSR-14.
Params: - type – type to provide the erasure for.
Returns: the given type's erasure.
/**
* Get the {@link Class} representation of the given type.
* <p/>
* This corresponds to the notion of the erasure in JSR-14.
*
* @param type type to provide the erasure for.
* @return the given type's erasure.
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> erasure(final Type type) {
return eraser.visit(type);
}
Check if subType
is a sub-type of superType
. Params: - subType – sub-type type.
- superType – super-type type.
Returns: true
in case the subType
is a sub-type of superType
, false
otherwise.
/**
* Check if {@code subType} is a sub-type of {@code superType}.
*
* @param subType sub-type type.
* @param superType super-type type.
* @return {@code true} in case the {@code subType} is a sub-type of {@code superType},
* {@code false} otherwise.
*/
public static boolean isSubClassOf(final Type subType, final Type superType) {
return erasure(superType).isAssignableFrom(erasure(subType));
}
Checks if the type is an array type.
Params: - type – type to check.
Returns: true
in case the type is an array type, false
otherwise.
/**
* Checks if the type is an array type.
*
* @param type type to check.
* @return {@code true} in case the type is an array type, {@code false} otherwise.
*/
public static boolean isArray(final Type type) {
if (type instanceof Class) {
final Class c = (Class) type;
return c.isArray();
}
return type instanceof GenericArrayType;
}
Checks if the type is an array of a given component type.
Params: - type – type to check.
- componentType – array component type.
Returns: true
in case the type is an array type of a given component type, false
otherwise.
/**
* Checks if the type is an array of a given component type.
*
* @param type type to check.
* @param componentType array component type.
* @return {@code true} in case the type is an array type of a given component type,
* {@code false} otherwise.
*/
public static boolean isArrayOfType(final Type type, final Class<?> componentType) {
if (type instanceof Class) {
final Class c = (Class) type;
return c.isArray() && c != byte[].class;
}
if (type instanceof GenericArrayType) {
final Type arrayComponentType = ((GenericArrayType) type).getGenericComponentType();
return arrayComponentType == componentType;
}
return false;
}
Gets the component type of the array.
Params: - type – must be an array.
Throws: - IllegalArgumentException – in case the type is not an array type.
Returns: array component type.
/**
* Gets the component type of the array.
*
* @param type must be an array.
* @return array component type.
* @throws IllegalArgumentException in case the type is not an array type.
*/
public static Type getArrayComponentType(final Type type) {
if (type instanceof Class) {
final Class c = (Class) type;
return c.getComponentType();
}
if (type instanceof GenericArrayType) {
return ((GenericArrayType) type).getGenericComponentType();
}
throw new IllegalArgumentException();
}
Get Array class of component type.
Params: - c – the component class of the array
Returns: the array class.
/**
* Get Array class of component type.
*
* @param c the component class of the array
* @return the array class.
*/
public static Class<?> getArrayForComponentType(final Class<?> c) {
try {
final Object o = Array.newInstance(c, 0);
return o.getClass();
} catch (final Exception e) {
throw new IllegalArgumentException(e);
}
}
Get privileged action to obtain the static valueOf(String ) method.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class to obtain the method.
See Also: Returns: privileged action to get the method. The action could return null
if the method is not present.
/**
* Get privileged action to obtain the static valueOf(String ) method.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class to obtain the method.
* @return privileged action to get the method.
* The action could return {@code null} if the method is not present.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
@SuppressWarnings("unchecked")
public static PrivilegedAction<Method> getValueOfStringMethodPA(final Class<?> clazz) {
return getStringToObjectMethodPA(clazz, "valueOf");
}
Get privileged action to get the static fromString(String ) method.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get the method.
See Also: Returns: privileged action to obtain the method. The action could return null
if the method is not present.
/**
* Get privileged action to get the static fromString(String ) method.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get the method.
* @return privileged action to obtain the method.
* The action could return {@code null} if the method is not present.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
@SuppressWarnings("unchecked")
public static PrivilegedAction<Method> getFromStringStringMethodPA(final Class<?> clazz) {
return getStringToObjectMethodPA(clazz, "fromString");
}
Get privileged action to get the static method of given name. If run using security manager, the returned privileged
action
must be invoked within a doPrivileged block.
Params: - clazz – class for which to get the method.
- methodName – name of the method to be obtained.
See Also: Returns: privileged action to obtain the method. The action could return null
if the method is not present.
/**
* Get privileged action to get the static method of given name. If run using security manager, the returned privileged
* action
* must be invoked within a doPrivileged block.
*
* @param clazz class for which to get the method.
* @param methodName name of the method to be obtained.
* @return privileged action to obtain the method.
* The action could return {@code null} if the method is not present.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
private static PrivilegedAction<Method> getStringToObjectMethodPA(final Class<?> clazz, final String methodName) {
return new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
final Method method = clazz.getDeclaredMethod(methodName, String.class);
if (Modifier.isStatic(method.getModifiers()) && method.getReturnType() == clazz) {
return method;
}
return null;
} catch (final NoSuchMethodException nsme) {
return null;
}
}
};
}
Get privileged action to obtain constructor that has a single parameter of String.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – The class for which to obtain the constructor.
See Also: Returns: privileged action to obtain the constructor. The action could return null
if the constructor is not present.
/**
* Get privileged action to obtain constructor that has a single parameter of String.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz The class for which to obtain the constructor.
* @return privileged action to obtain the constructor.
* The action could return {@code null} if the constructor is not present.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Constructor> getStringConstructorPA(final Class<?> clazz) {
return new PrivilegedAction<Constructor>() {
@Override
public Constructor run() {
try {
return clazz.getConstructor(String.class);
} catch (final SecurityException e) {
throw e;
} catch (final Exception e) {
return null;
}
}
};
}
Get privileged action to obtain declared constructors of given class.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
Params: - clazz – The class for which to obtain the constructors.
See Also: Returns: privileged action to obtain the array of constructors.
/**
* Get privileged action to obtain declared constructors of given class.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
*
* @param clazz The class for which to obtain the constructors.
* @return privileged action to obtain the array of constructors.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Constructor<?>[]> getDeclaredConstructorsPA(final Class<?> clazz) {
return new PrivilegedAction<Constructor<?>[]>() {
@Override
public Constructor<?>[] run() {
return clazz.getDeclaredConstructors();
}
};
}
Get privileged action to obtain declared constructor of given class with given parameters.
If run using security manager, the returned privileged action must be invoked within a doPrivileged block.
Params: - clazz – The class for which to obtain the constructor.
- params – constructor parameters.
See Also: Returns: privileged action to obtain the constructor or null
, when constructor with given parameters is not found.
/**
* Get privileged action to obtain declared constructor of given class with given parameters.
* If run using security manager, the returned privileged action must be invoked within a doPrivileged block.
*
* @param clazz The class for which to obtain the constructor.
* @param params constructor parameters.
* @return privileged action to obtain the constructor or {@code null}, when constructor with given parameters
* is not found.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Constructor<?>> getDeclaredConstructorPA(final Class<?> clazz, final Class<?>... params) {
return new PrivilegedAction<Constructor<?>>() {
@Override
public Constructor<?> run() {
try {
return clazz.getDeclaredConstructor(params);
} catch (NoSuchMethodException e) {
return null;
}
}
};
}
Returns collection of all annotation types attached to a given annotated element that have the provided meta
annotation attached.
Params: - annotatedElement – annotated element.
- metaAnnotation – meta annotation attached to the annotation types we are looking for (if null, annotation
types of all attached annotations will be returned).
Returns: list of annotation types with a given meta annotation
/**
* Returns collection of all annotation types attached to a given annotated element that have the provided meta
* annotation attached.
*
* @param annotatedElement annotated element.
* @param metaAnnotation meta annotation attached to the annotation types we are looking for (if null, annotation
* types of all attached annotations will be returned).
* @return list of annotation types with a given meta annotation
*/
public static Collection<Class<? extends Annotation>> getAnnotationTypes(final AnnotatedElement annotatedElement,
final Class<? extends Annotation> metaAnnotation) {
final Set<Class<? extends Annotation>> result = Collections.newSetFromMap(new IdentityHashMap<>());
for (final Annotation a : annotatedElement.getAnnotations()) {
final Class<? extends Annotation> aType = a.annotationType();
if (metaAnnotation == null || aType.getAnnotation(metaAnnotation) != null) {
result.add(aType);
}
}
return result;
}
Determine whether a given method is getter
. Params: - method – method to be examined.
Returns: true
if the method is getter
, false
otherwise.
/**
* Determine whether a given method is {@code getter}.
*
* @param method method to be examined.
* @return {@code true} if the method is {@code getter}, {@code false} otherwise.
*/
public static boolean isGetter(final Method method) {
if (method.getParameterTypes().length == 0
&& Modifier.isPublic(method.getModifiers())) {
final String methodName = method.getName();
if (methodName.startsWith("get") && methodName.length() > 3) {
return !void.class.equals(method.getReturnType());
} else if (methodName.startsWith("is") && methodName.length() > 2) {
return boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType());
}
}
return false;
}
Create a generic type
information for a given Java instance
. If the supplied instance is an instance of GenericEntity
, the generic type information will be computed using the GenericEntity.getType()
information. Otherwise the instance.getClass()
will be used.
Params: - instance – Java instance for which the
GenericType
description should be created.
Returns: GenericType
describing the Java instance
.
/**
* Create a {@link javax.ws.rs.core.GenericType generic type} information for a given
* Java {@code instance}.
* <p>
* If the supplied instance is an instance of {@link javax.ws.rs.core.GenericEntity}, the generic type
* information will be computed using the {@link javax.ws.rs.core.GenericEntity#getType()}
* information. Otherwise the {@code instance.getClass()} will be used.
* </p>
*
* @param instance Java instance for which the {@code GenericType} description should be created.
* @return {@code GenericType} describing the Java {@code instance}.
*/
public static GenericType genericTypeFor(final Object instance) {
final GenericType genericType;
if (instance instanceof GenericEntity) {
genericType = new GenericType(((GenericEntity) instance).getType());
} else {
genericType = (instance == null) ? null : new GenericType(instance.getClass());
}
return genericType;
}
Determine whether a given method is setter
. Params: - method – method to be examined.
Returns: true
if the method is setter
, false
otherwise.
/**
* Determine whether a given method is {@code setter}.
*
* @param method method to be examined.
* @return {@code true} if the method is {@code setter}, {@code false} otherwise.
*/
public static boolean isSetter(final Method method) {
return Modifier.isPublic(method.getModifiers())
&& void.class.equals(method.getReturnType())
&& method.getParameterTypes().length == 1
&& method.getName().startsWith("set");
}
Determine property (field) name from given getter/setter method.
Params: - method – method to be examined.
Returns: property (field) name.
/**
* Determine property (field) name from given getter/setter method.
*
* @param method method to be examined.
* @return property (field) name.
*/
public static String getPropertyName(final Method method) {
if (!isGetter(method) && !isSetter(method)) {
throw new IllegalArgumentException(LocalizationMessages.METHOD_NOT_GETTER_NOR_SETTER());
}
final String methodName = method.getName();
final int offset = methodName.startsWith("is") ? 2 : 3;
final char[] chars = methodName.toCharArray();
chars[offset] = Character.toLowerCase(chars[offset]);
return new String(chars, offset, chars.length - offset);
}
Determine the most specific type from given set.
Params: - contractTypes – to be taken into account.
Returns: the most specific type.
/**
* Determine the most specific type from given set.
*
* @param contractTypes to be taken into account.
* @return the most specific type.
*/
public static Class<?> theMostSpecificTypeOf(final Set<Type> contractTypes) {
Class<?> result = null;
for (final Type t : contractTypes) {
final Class<?> next = (Class<?>) t;
if (result == null) {
result = next;
} else {
if (result.isAssignableFrom(next)) {
result = next;
}
}
}
return result;
}
A tuple consisting of a concrete class and a declaring class that declares a
generic interface type.
/**
* A tuple consisting of a concrete class and a declaring class that declares a
* generic interface type.
*/
public static class DeclaringClassInterfacePair {
Concrete class.
/**
* Concrete class.
*/
public final Class<?> concreteClass;
Declaring class.
/**
* Declaring class.
*/
public final Class<?> declaringClass;
Generic interface type.
/**
* Generic interface type.
*/
public final Type genericInterface;
private DeclaringClassInterfacePair(final Class<?> concreteClass,
final Class<?> declaringClass,
final Type genericInterface) {
this.concreteClass = concreteClass;
this.declaringClass = declaringClass;
this.genericInterface = genericInterface;
}
}
Get the parameterized class arguments for a declaring class that
declares a generic interface type.
Params: - p – the declaring class
Returns: the parameterized class arguments, or null if the generic
interface type is not a parameterized type.
/**
* Get the parameterized class arguments for a declaring class that
* declares a generic interface type.
*
* @param p the declaring class
* @return the parameterized class arguments, or null if the generic
* interface type is not a parameterized type.
*/
public static Class[] getParameterizedClassArguments(final DeclaringClassInterfacePair p) {
if (p.genericInterface instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) p.genericInterface;
final Type[] as = pt.getActualTypeArguments();
final Class[] cas = new Class[as.length];
for (int i = 0; i < as.length; i++) {
final Type a = as[i];
if (a instanceof Class) {
cas[i] = (Class) a;
} else if (a instanceof ParameterizedType) {
pt = (ParameterizedType) a;
cas[i] = (Class) pt.getRawType();
} else if (a instanceof TypeVariable) {
final TypeVariable tv = (TypeVariable) a;
final ClassTypePair ctp = resolveTypeVariable(p.concreteClass, p.declaringClass, tv);
cas[i] = (ctp != null) ? ctp.rawClass() : (Class<?>) (tv.getBounds()[0]);
} else if (a instanceof GenericArrayType) {
final GenericArrayType gat = (GenericArrayType) a;
final Type t = gat.getGenericComponentType();
if (t instanceof Class) {
cas[i] = getArrayForComponentType((Class<?>) t);
}
}
}
return cas;
} else {
return null;
}
}
Get the parameterized type arguments for a declaring class that
declares a generic interface type.
Params: - p – the declaring class
Returns: the parameterized type arguments, or null if the generic
interface type is not a parameterized type.
/**
* Get the parameterized type arguments for a declaring class that
* declares a generic interface type.
*
* @param p the declaring class
* @return the parameterized type arguments, or null if the generic
* interface type is not a parameterized type.
*/
public static Type[] getParameterizedTypeArguments(final DeclaringClassInterfacePair p) {
if (p.genericInterface instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) p.genericInterface;
final Type[] as = pt.getActualTypeArguments();
final Type[] ras = new Type[as.length];
for (int i = 0; i < as.length; i++) {
final Type a = as[i];
if (a instanceof Class) {
ras[i] = a;
} else if (a instanceof ParameterizedType) {
ras[i] = a;
} else if (a instanceof TypeVariable) {
final ClassTypePair ctp = resolveTypeVariable(p.concreteClass, p.declaringClass, (TypeVariable) a);
if (ctp == null) {
throw new IllegalArgumentException(
LocalizationMessages.ERROR_RESOLVING_GENERIC_TYPE_VALUE(p.genericInterface, p.concreteClass));
}
ras[i] = ctp.type();
}
}
return ras;
} else {
return null;
}
}
Find the declaring class that implements or extends an interface.
Params: - concrete – the concrete class than directly or indirectly
implements or extends an interface class.
- iface – the interface class.
Returns: the tuple of the declaring class and the generic interface
type.
/**
* Find the declaring class that implements or extends an interface.
*
* @param concrete the concrete class than directly or indirectly
* implements or extends an interface class.
* @param iface the interface class.
* @return the tuple of the declaring class and the generic interface
* type.
*/
public static DeclaringClassInterfacePair getClass(final Class<?> concrete, final Class<?> iface) {
return getClass(concrete, iface, concrete);
}
private static DeclaringClassInterfacePair getClass(final Class<?> concrete, final Class<?> iface, Class<?> c) {
final Type[] gis = c.getGenericInterfaces();
final DeclaringClassInterfacePair p = getType(concrete, iface, c, gis);
if (p != null) {
return p;
}
c = c.getSuperclass();
if (c == null || c == Object.class) {
return null;
}
return getClass(concrete, iface, c);
}
private static DeclaringClassInterfacePair getType(final Class<?> concrete,
final Class<?> iface,
final Class<?> c,
final Type[] ts) {
for (final Type t : ts) {
final DeclaringClassInterfacePair p = getType(concrete, iface, c, t);
if (p != null) {
return p;
}
}
return null;
}
private static DeclaringClassInterfacePair getType(final Class<?> concrete,
final Class<?> iface,
final Class<?> c,
final Type t) {
if (t instanceof Class) {
if (t == iface) {
return new DeclaringClassInterfacePair(concrete, c, t);
} else {
return getClass(concrete, iface, (Class<?>) t);
}
} else if (t instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) t;
if (pt.getRawType() == iface) {
return new DeclaringClassInterfacePair(concrete, c, t);
} else {
return getClass(concrete, iface, (Class<?>) pt.getRawType());
}
}
return null;
}
Resolve generic type parameter(s) of a raw class and it's generic type
based on the class that declares the generic type parameter(s) to be resolved
and a concrete implementation of the declaring class.
Params: - concreteClass – concrete implementation of the declaring class.
- declaringClass – class declaring the generic type parameter(s) to be
resolved.
- rawResolvedType – raw class of the generic type to be resolved.
- genericResolvedType – generic type information of th type to be resolved.
Returns: a pair of class and the generic type values with the the resolved
generic parameter types.
/**
* Resolve generic type parameter(s) of a raw class and it's generic type
* based on the class that declares the generic type parameter(s) to be resolved
* and a concrete implementation of the declaring class.
*
* @param concreteClass concrete implementation of the declaring class.
* @param declaringClass class declaring the generic type parameter(s) to be
* resolved.
* @param rawResolvedType raw class of the generic type to be resolved.
* @param genericResolvedType generic type information of th type to be resolved.
* @return a pair of class and the generic type values with the the resolved
* generic parameter types.
*/
public static ClassTypePair resolveGenericType(final Class concreteClass, final Class declaringClass,
final Class rawResolvedType, final Type genericResolvedType) {
if (genericResolvedType instanceof TypeVariable) {
final ClassTypePair ct = resolveTypeVariable(
concreteClass,
declaringClass,
(TypeVariable) genericResolvedType);
if (ct != null) {
return ct;
}
} else if (genericResolvedType instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) genericResolvedType;
final Type[] ptts = pt.getActualTypeArguments();
boolean modified = false;
for (int i = 0; i < ptts.length; i++) {
final ClassTypePair ct =
resolveGenericType(concreteClass, declaringClass, (Class) pt.getRawType(), ptts[i]);
if (ct.type() != ptts[i]) {
ptts[i] = ct.type();
modified = true;
}
}
if (modified) {
final ParameterizedType rpt = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return ptts.clone();
}
@Override
public Type getRawType() {
return pt.getRawType();
}
@Override
public Type getOwnerType() {
return pt.getOwnerType();
}
};
return ClassTypePair.of((Class<?>) pt.getRawType(), rpt);
}
} else if (genericResolvedType instanceof GenericArrayType) {
final GenericArrayType gat = (GenericArrayType) genericResolvedType;
final ClassTypePair ct =
resolveGenericType(concreteClass, declaringClass, null, gat.getGenericComponentType());
if (gat.getGenericComponentType() != ct.type()) {
try {
final Class ac = ReflectionHelper.getArrayForComponentType(ct.rawClass());
return ClassTypePair.of(ac);
} catch (final Exception e) {
LOGGER.log(Level.FINEST, "", e);
}
}
}
return ClassTypePair.of(rawResolvedType, genericResolvedType);
}
Given a type variable resolve the Java class of that variable.
Params: - c – the concrete class from which all type variables are resolved.
- dc – the declaring class where the type variable was defined.
- tv – the type variable.
Returns: the resolved Java class and type, otherwise null if the type variable
could not be resolved.
/**
* Given a type variable resolve the Java class of that variable.
*
* @param c the concrete class from which all type variables are resolved.
* @param dc the declaring class where the type variable was defined.
* @param tv the type variable.
* @return the resolved Java class and type, otherwise null if the type variable
* could not be resolved.
*/
public static ClassTypePair resolveTypeVariable(final Class<?> c, final Class<?> dc, final TypeVariable tv) {
return resolveTypeVariable(c, dc, tv, new HashMap<TypeVariable, Type>());
}
private static ClassTypePair resolveTypeVariable(final Class<?> c, final Class<?> dc, final TypeVariable tv,
final Map<TypeVariable, Type> map) {
final Type[] gis = c.getGenericInterfaces();
for (final Type gi : gis) {
if (gi instanceof ParameterizedType) {
// process pt of interface
final ParameterizedType pt = (ParameterizedType) gi;
final ClassTypePair ctp = resolveTypeVariable(pt, (Class<?>) pt.getRawType(), dc, tv, map);
if (ctp != null) {
return ctp;
}
}
}
final Type gsc = c.getGenericSuperclass();
if (gsc instanceof ParameterizedType) {
// process pt of class
final ParameterizedType pt = (ParameterizedType) gsc;
return resolveTypeVariable(pt, c.getSuperclass(), dc, tv, map);
} else if (gsc instanceof Class) {
return resolveTypeVariable(c.getSuperclass(), dc, tv, map);
}
return null;
}
private static ClassTypePair resolveTypeVariable(ParameterizedType pt, Class<?> c, final Class<?> dc, final TypeVariable tv,
final Map<TypeVariable, Type> map) {
final Type[] typeArguments = pt.getActualTypeArguments();
final TypeVariable[] typeParameters = c.getTypeParameters();
final Map<TypeVariable, Type> subMap = new HashMap<TypeVariable, Type>();
for (int i = 0; i < typeArguments.length; i++) {
// Substitute a type variable with the Java class
final Type typeArgument = typeArguments[i];
if (typeArgument instanceof TypeVariable) {
final Type t = map.get(typeArgument);
subMap.put(typeParameters[i], t);
} else {
subMap.put(typeParameters[i], typeArgument);
}
}
if (c == dc) {
Type t = subMap.get(tv);
if (t instanceof Class) {
return ClassTypePair.of((Class) t);
} else if (t instanceof GenericArrayType) {
final GenericArrayType gat = (GenericArrayType) t;
t = gat.getGenericComponentType();
if (t instanceof Class) {
c = (Class<?>) t;
try {
return ClassTypePair.of(getArrayForComponentType(c));
} catch (final Exception ignored) {
// ignored
}
return null;
} else if (t instanceof ParameterizedType) {
final Type rt = ((ParameterizedType) t).getRawType();
if (rt instanceof Class) {
c = (Class<?>) rt;
} else {
return null;
}
try {
return ClassTypePair.of(getArrayForComponentType(c), gat);
} catch (final Exception e) {
return null;
}
} else {
return null;
}
} else if (t instanceof ParameterizedType) {
pt = (ParameterizedType) t;
if (pt.getRawType() instanceof Class) {
return ClassTypePair.of((Class<?>) pt.getRawType(), pt);
} else {
return null;
}
} else {
return null;
}
} else {
return resolveTypeVariable(c, dc, tv, subMap);
}
}
Get privileged action to find a method on a class given an existing method.
If run using security manager, the returned privileged action
must be invoked within a doPrivileged block.
If there exists a public method on the class that has the same name
and parameters as the existing method then that public method is
returned from the action.
Otherwise, if there exists a public method on the class that has the same name and the same number of parameters as the existing method, and each generic parameter type, in order, of the public method is equal to the generic parameter type, in the same order, of the existing method or is an instance of TypeVariable
then that public method is returned from the action. Params: - c – the class to search for a public method
- m – the method to find
See Also: Returns: privileged action to return public method found.
/**
* Get privileged action to find a method on a class given an existing method.
* If run using security manager, the returned privileged action
* must be invoked within a doPrivileged block.
* <p/>
* If there exists a public method on the class that has the same name
* and parameters as the existing method then that public method is
* returned from the action.
* <p/>
* Otherwise, if there exists a public method on the class that has
* the same name and the same number of parameters as the existing method,
* and each generic parameter type, in order, of the public method is equal
* to the generic parameter type, in the same order, of the existing method
* or is an instance of {@link TypeVariable} then that public method is
* returned from the action.
*
* @param c the class to search for a public method
* @param m the method to find
* @return privileged action to return public method found.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Method> findMethodOnClassPA(final Class<?> c, final Method m) {
return new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
return c.getMethod(m.getName(), m.getParameterTypes());
} catch (final NoSuchMethodException nsme) {
for (final Method _m : c.getMethods()) {
if (_m.getName().equals(m.getName())
&& _m.getParameterTypes().length == m.getParameterTypes().length) {
if (compareParameterTypes(m.getGenericParameterTypes(),
_m.getGenericParameterTypes())) {
return _m;
}
}
}
return null;
}
}
};
}
Get privileged action to return an array containing Method
objects reflecting all the public member methods of the supplied class or interface
object, including those declared by the class or interface and those
inherited from superclasses and superinterfaces.
Array classes return all the (public) member methods inherited from the Object
class. The elements in the array returned are not sorted and are not in any particular order. This method returns action providing an array of length 0 if this Class
object represents a class or interface that has no public member methods, or if this Class
object represents a primitive type or void.
The class initialization method <clinit>
is not included in the returned array. If the class declares multiple public member methods with the same parameter types, they are all included in the returned array.
See The Java Language Specification, sections 8.2 and 8.4.
Params: - c – class for which the methods should be returned.
See Also: Returns: privileged action to obtain an array of Method
objects representing the public methods of the class.
/**
* Get privileged action to return an array containing {@link Method} objects reflecting all
* the public <em>member</em> methods of the supplied class or interface
* object, including those declared by the class or interface and those
* inherited from superclasses and superinterfaces.
* <p/>
* Array classes return all the (public) member methods
* inherited from the {@code Object} class. The elements in the array
* returned are not sorted and are not in any particular order. This
* method returns action providing an array of length 0 if this {@code Class} object
* represents a class or interface that has no public member methods, or if
* this {@code Class} object represents a primitive type or void.
* <p/>
* <p>
* The class initialization method {@code <clinit>} is not
* included in the returned array. If the class declares multiple public
* member methods with the same parameter types, they are all included in
* the returned array.
* </p>
* <p>
* See <em>The Java Language Specification</em>, sections 8.2 and 8.4.
* </p>
*
* @param c class for which the methods should be returned.
* @return privileged action to obtain an array of {@code Method} objects representing the
* public methods of the class.
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction<Method[]> getMethodsPA(final Class<?> c) {
return new PrivilegedAction<Method[]>() {
@Override
public Method[] run() {
return c.getMethods();
}
};
}
private static Method[] _getMethods(final Class<?> clazz) {
return AccessController.doPrivileged(getMethodsPA(clazz));
}
Params: - clazz – class to find overriding method on.
- method – an abstract method to find implementing method for.
Returns: method that overrides the given method or the given method itself if a better alternative cannot be found.
/**
* Find a {@link Method method} that overrides the given {@code method} on the given {@link Class class}.
*
* @param clazz class to find overriding method on.
* @param method an abstract method to find implementing method for.
* @return method that overrides the given method or the given method itself if a better alternative cannot be found.
*/
public static Method findOverridingMethodOnClass(final Class<?> clazz, final Method method) {
for (final Method _method : _getMethods(clazz)) {
if (!_method.isBridge()
&& !Modifier.isAbstract(_method.getModifiers())
&& _method.getName().equals(method.getName())
&& _method.getParameterTypes().length == method.getParameterTypes().length) {
if (compareParameterTypes(_method.getGenericParameterTypes(), method.getGenericParameterTypes())) {
return _method;
}
}
}
if (method.isBridge() || Modifier.isAbstract(method.getModifiers())) {
LOGGER.log(Level.INFO, LocalizationMessages.OVERRIDING_METHOD_CANNOT_BE_FOUND(method, clazz));
}
return method;
}
Compare generic parameter types of two methods.
Params: - ts – generic parameter types of the first method.
- _ts – generic parameter types of the second method.
See Also: Returns: true
if the given types are understood to be equal, false
otherwise.
/**
* Compare generic parameter types of two methods.
*
* @param ts generic parameter types of the first method.
* @param _ts generic parameter types of the second method.
* @return {@code true} if the given types are understood to be equal, {@code false} otherwise.
* @see #compareParameterTypes(java.lang.reflect.Type, java.lang.reflect.Type)
*/
private static boolean compareParameterTypes(final Type[] ts, final Type[] _ts) {
for (int i = 0; i < ts.length; i++) {
if (!ts[i].equals(_ts[i])) {
if (!compareParameterTypes(ts[i], _ts[i])) {
return false;
}
}
}
return true;
}
Compare respective generic parameter types of two methods.
Params: - ts – generic parameter type of the first method.
- _ts – generic parameter type of the second method.
Returns: true
if the given types are understood to be equal, false
otherwise.
/**
* Compare respective generic parameter types of two methods.
*
* @param ts generic parameter type of the first method.
* @param _ts generic parameter type of the second method.
* @return {@code true} if the given types are understood to be equal, {@code false} otherwise.
*/
@SuppressWarnings("unchecked")
private static boolean compareParameterTypes(final Type ts, final Type _ts) {
if (ts instanceof Class) {
final Class<?> clazz = (Class<?>) ts;
if (_ts instanceof Class) {
return ((Class) _ts).isAssignableFrom(clazz);
} else if (_ts instanceof TypeVariable) {
return checkTypeBounds(clazz, ((TypeVariable) _ts).getBounds());
}
}
return _ts instanceof TypeVariable;
}
@SuppressWarnings("unchecked")
private static boolean checkTypeBounds(final Class type, final Type[] bounds) {
for (final Type bound : bounds) {
if (bound instanceof Class) {
if (!((Class) bound).isAssignableFrom(type)) {
return false;
}
}
}
return true;
}
private static final Class<?> bundleReferenceClass = AccessController.doPrivileged(
classForNamePA("org.osgi.framework.BundleReference", null));
Returns an OsgiRegistry
instance. Returns: an OsgiRegistry
instance or null
if the class cannot be instantiated (not in OSGi environment).
/**
* Returns an {@link OsgiRegistry} instance.
*
* @return an {@link OsgiRegistry} instance or {@code null} if the class cannot be instantiated (not in OSGi environment).
*/
public static OsgiRegistry getOsgiRegistryInstance() {
try {
if (bundleReferenceClass != null) {
return OsgiRegistry.getInstance();
}
} catch (final Exception e) {
// Do nothing - instance is null.
}
return null;
}
Lookup resource by given name. If OSGi runtime is detected and the originClass parameter is not null,
an attempt will be made to get the resource input stream via OSGi API from the bundle where originClass is included.
Otherwise (non OSGi environment) or if OSGi fails to provide the input stream, the return value
will be taken from the provided loader getResourceAsStream method.
Params: - loader – class loader where to lookup the resource in non-OSGi environment or if OSGi means fail.
- originClass – if not null, and OSGi environment is detected, the resource will be taken from the bundle including
the originClass type.
- name – filename of the desired resource.
Returns: an input stream corresponding to the required resource or null if the resource could not be found.
/**
* Lookup resource by given name. If OSGi runtime is detected and the originClass parameter is not null,
* an attempt will be made to get the resource input stream via OSGi API from the bundle where originClass is included.
* Otherwise (non OSGi environment) or if OSGi fails to provide the input stream, the return value
* will be taken from the provided loader getResourceAsStream method.
*
* @param loader class loader where to lookup the resource in non-OSGi environment or if OSGi means fail.
* @param originClass if not null, and OSGi environment is detected, the resource will be taken from the bundle including
* the originClass type.
* @param name filename of the desired resource.
* @return an input stream corresponding to the required resource or null if the resource could not be found.
*/
public static InputStream getResourceAsStream(final ClassLoader loader, final Class<?> originClass, final String name) {
try {
if (bundleReferenceClass != null
&& originClass != null
&& bundleReferenceClass.isInstance(ReflectionHelper.class.getClassLoader())) {
final Bundle bundle = FrameworkUtil.getBundle(originClass);
final URL resourceUrl = (bundle != null) ? bundle.getEntry(name) : null;
if (resourceUrl != null) {
return resourceUrl.openStream();
}
}
} catch (final IOException ex) {
// ignore
}
return loader.getResourceAsStream(name);
}
Given the type parameter gets the raw type represented by the type, or null if this has no associated raw class.
Params: - type – the type to find the raw class on.
Returns: the raw class associated with this type.
/**
* Given the type parameter gets the raw type represented by the type, or null if this has no associated raw class.
*
* @param type the type to find the raw class on.
* @return the raw class associated with this type.
*/
public static Class<?> getRawClass(Type type) {
if (type == null) return null;
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
if (!(componentType instanceof ParameterizedType) && !(componentType instanceof Class)) {
// type variable is not supported
return null;
}
Class<?> rawComponentClass = getRawClass(componentType);
String forNameName = "[L" + rawComponentClass.getName() + ";";
try {
return Class.forName(forNameName);
} catch (Throwable th) {
// ignore, but return null
return null;
}
}
if (type instanceof Class) {
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
if (rawType instanceof Class) {
return (Class<?>) rawType;
}
}
return null;
}
}