com.sun.jersey.core.reflection.ReflectionHelper Maven / Gradle / Ivy
Show all versions of jersey-bundle Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.jersey.core.reflection;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
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.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import com.sun.jersey.core.osgi.OsgiRegistry;
import com.sun.jersey.impl.ImplMessages;
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Utility methods for Java reflection.
*
* @author [email protected]
*/
public class ReflectionHelper {
private static final Logger LOGGER = Logger.getLogger(ReflectionHelper.class.getName());
private static final PrivilegedAction NoOpPrivilegedACTION = new PrivilegedAction() {
@Override
public Object run() {
return null;
}
};
/**
*
*/
public static Class getDeclaringClass(AccessibleObject ao) {
if (ao instanceof Method) {
return ((Method)ao).getDeclaringClass();
} else if (ao instanceof Field) {
return ((Field)ao).getDeclaringClass();
} else if (ao instanceof Constructor) {
return ((Constructor)ao).getDeclaringClass();
} else {
throw new RuntimeException();
}
}
/**
* 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())
*
*
* @param o the object.
* @return the string representation of the object.
*/
public static String objectToString(Object o) {
if (o == null)
return "null";
StringBuffer sb = new StringBuffer();
sb.append(o.getClass().getName()).
append('@').append(Integer.toHexString(o.hashCode()));
return sb.toString();
}
/**
* 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, thos method returns a
* string equal to the value of:
*
*
* o.getClass().getName() + '@' + Integer.toHexString(o.hashCode()) +
* '.' + m.getName() + '(' + <parameters> + ')'.
*
*
* @param o the object whose class implements m
.
* @param m the method.
* @return the string representation of the method and instance.
*/
public static String methodInstanceToString(Object o, Method m) {
StringBuffer sb = new StringBuffer();
sb.append(o.getClass().getName()).
append('@').append(Integer.toHexString(o.hashCode())).
append('.').append(m.getName()).append('(');
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();
}
/**
*
* @param type
* @return
*/
private static String getTypeName(Class type) {
if (type.isArray()) {
try {
Class cl = type;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuffer sb = new StringBuffer();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
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.
*
* @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 PrivilegedAction> 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.
*
* @param name class name.
* @param cl class loader to use, if 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)
*/
public static PrivilegedAction> classForNamePA(final String name, final ClassLoader cl) {
return new PrivilegedAction>() {
@Override
public Class> run() {
if (cl != null) {
try {
return Class.forName(name, false, cl);
} catch (ClassNotFoundException ex) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE,
"Unable to load class " + name + " using the supplied class loader "
+ cl.getClass().getName() + ".", ex);
}
}
}
try {
return Class.forName(name);
} catch (ClassNotFoundException ex) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to load class " + name + " using the current class loader.", ex);
}
}
return null;
}
};
}
/**
* 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.
*
* @param 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.
*
* @see AccessController#doPrivileged(java.security.PrivilegedExceptionAction)
*/
public static PrivilegedExceptionAction> 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.
*
* @param 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.
* The action throws {@link ClassNotFoundException}
* or returns {@code null} if the class cannot be found.
*
* @see AccessController#doPrivileged(java.security.PrivilegedExceptionAction)
*/
@SuppressWarnings("unchecked")
public static PrivilegedExceptionAction> classForNameWithExceptionPEA(final String name, final ClassLoader cl) throws ClassNotFoundException {
return new PrivilegedExceptionAction>() {
@Override
public Class run() throws ClassNotFoundException {
if (cl != null) {
try {
return (Class) Class.forName(name, false, cl);
} catch (ClassNotFoundException ex) {
// ignored on purpose
}
}
return (Class) 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.
*
* @return privileged action to obtain the actual context class loader.
* The action could return {@code null} if context class loader has not been set.
*
* @see AccessController#doPrivileged(java.security.PrivilegedAction)
*/
public static PrivilegedAction getContextClassLoaderPA() {
return new PrivilegedAction() {
@Override
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
};
}
/**
* 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 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