All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.tools.util.ReflectionHelper Maven / Gradle / Ivy

/*
 * File: ReflectionHelper.java
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * The contents of this file are subject to the terms and conditions of 
 * the Common Development and Distribution License 1.0 (the "License").
 *
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the License by consulting the LICENSE.txt file
 * distributed with this file, or by consulting https://oss.oracle.com/licenses/CDDL
 *
 * 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 LICENSE.txt.
 *
 * 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]"
 */

package com.oracle.tools.util;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * A collection of utilities to assist in using Reflection to create objects.
 * 

* Copyright (c) 2010. All Rights Reserved. Oracle Corporation.
* Oracle is a registered trademark of Oracle Corporation and/or its affiliates. * * @author Christer Fahlgren * @author Brian Oliver */ public class ReflectionHelper { /** * Get a compatible constructor to the supplied parameter types. * * @param clazz the class which we want to construct * @param parameterTypes the types required of the constructor * * @return a compatible constructor or null if none exists */ public static Constructor getCompatibleConstructor(Class clazz, Class[] parameterTypes) { Constructor[] constructors = clazz.getConstructors(); for (int i = 0; i < constructors.length; i++) { if (constructors[i].getParameterTypes().length == (parameterTypes != null ? parameterTypes.length : 0)) { // If we have the same number of parameters there is a shot that we have a compatible // constructor Class[] constructorTypes = constructors[i].getParameterTypes(); boolean isCompatible = true; for (int j = 0; j < (parameterTypes != null ? parameterTypes.length : 0); j++) { if (!constructorTypes[j].isAssignableFrom(parameterTypes[j])) { // The type is not assignment compatible, however // we might be able to coerce from a basic type to a boxed type if (constructorTypes[j].isPrimitive()) { if (!isAssignablePrimitive(constructorTypes[j], parameterTypes[j])) { isCompatible = false; break; } } } } if (isCompatible) { return constructors[i]; } } } return null; } /** * Determines if a primitive type is assignable to a wrapper type. * * @param clzPrimitive a primitive class type * @param clzWrapper a wrapper class type * * @return true if primitive and wrapper are assignment compatible */ public static boolean isAssignablePrimitive(Class clzPrimitive, Class clzWrapper) { return (clzPrimitive.equals(java.lang.Boolean.TYPE) && clzWrapper.equals(java.lang.Boolean.class)) || (clzPrimitive.equals(java.lang.Byte.TYPE) && clzWrapper.equals(java.lang.Byte.class)) || (clzPrimitive.equals(java.lang.Character.TYPE) && clzWrapper.equals(java.lang.Character.class)) || (clzPrimitive.equals(java.lang.Double.TYPE) && clzWrapper.equals(java.lang.Double.class)) || (clzPrimitive.equals(java.lang.Float.TYPE) && clzWrapper.equals(java.lang.Float.class)) || (clzPrimitive.equals(java.lang.Integer.TYPE) && clzWrapper.equals(java.lang.Integer.class)) || (clzPrimitive.equals(java.lang.Long.TYPE) && clzWrapper.equals(java.lang.Long.class)) || (clzPrimitive.equals(java.lang.Short.TYPE) && clzWrapper.equals(java.lang.Short.class)); } /** * Obtains the {@link Method} that is compatible to the supplied parameter types. * * @param clazz the {@link Class} on which to find the {@link Method} * @param arguments the arguments for the {@link Method} * * @return a compatible {@link Method} or null if one can't be found */ public static Method getCompatibleMethod(Class clazz, String methodName, Object... arguments) { // determine the types of the arguments Class[] argumentTypes = new Class[arguments.length]; for (int i = 0; i < arguments.length; i++) { argumentTypes[i] = arguments[i] == null ? null : arguments[i].getClass(); } try { // attempt to find the method on the specified class // (this may fail, in which case we should try super classes) return clazz.getDeclaredMethod(methodName, argumentTypes); } catch (SecurityException e) { return null; } catch (NoSuchMethodException e) { return clazz.getSuperclass() == null ? null : getCompatibleMethod(clazz.getSuperclass(), methodName, arguments); } } /** * Create an Object via reflection (using the specified {@link ClassLoader}). * * @param className The name of the class to instantiate. * @param classLoader The {@link ClassLoader} to use to load the class. * * @return A new instance of the class specified by the className * * @throws ClassNotFoundException if the class is not found * @throws NoSuchMethodException if there is no such constructor * @throws InstantiationException if it failed to instantiate * @throws IllegalAccessException if security doesn't allow the call * @throws InvocationTargetException if the constructor failed */ public static Object createObject(String className, ClassLoader classLoader) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName(className, true, classLoader); Constructor con = clazz.getDeclaredConstructor((Class[]) null); return con.newInstance((Object[]) null); } /** * Create an Object via reflection (using the specified {@link ClassLoader}). * * @param className The name of the class to instantiate. * @param classLoader The {@link ClassLoader} to use to load the class. * @param constructorParameterList The set of parameters to pass to the constructor * * @return A new instance of the class specified by the className * * @throws ClassNotFoundException if the class is not found * @throws NoSuchMethodException if there is no such constructor * @throws InstantiationException if it failed to instantiate * @throws IllegalAccessException if security doesn't allow the call * @throws InvocationTargetException if the constructor failed */ public static Object createObject(String className, ClassLoader classLoader, Object... constructorParameterList) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName(className, true, classLoader); Class[] parameterTypes = getClassArrayFromObjectArray(constructorParameterList); Constructor con = ReflectionHelper.getCompatibleConstructor(clazz, parameterTypes); return con.newInstance(constructorParameterList); } /** * Returns an array of Class objects representing the class of the objects in the parameter. * * @param objectArray the array of Objects * * @return an array of Classes representing the class of the Objects */ protected static Class[] getClassArrayFromObjectArray(Object[] objectArray) { Class[] parameterTypes = null; if (objectArray != null) { parameterTypes = new Class[objectArray.length]; for (int i = 0; i < objectArray.length; i++) { parameterTypes[i] = objectArray[i].getClass(); } } return parameterTypes; } /** * Creates a dynamic proxy of the specified {@link Object} routing all * method calls to the specified {@link MethodInterceptor}. * * @param object the {@link Object} to proxy * @param interceptor the {@link MethodInterceptor} * * @return a dynamic proxy of the specified {@link Object} */ @SuppressWarnings("unchecked") public static T createProxyOf(T object, MethodInterceptor interceptor) { return (T) createProxyOf(object.getClass(), interceptor); } /** * Creates a dynamic proxy of the specified {@link Class} routing all * method calls to the specified {@link MethodInterceptor}. * * @param clazz the {@link Class} to proxy * @param interceptor the {@link MethodInterceptor} * * @return a dynamic proxy of the specified {@link Class} */ @SuppressWarnings("unchecked") public static T createProxyOf(Class clazz, MethodInterceptor interceptor) { // use a cglib enhancer to create the proxy Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallbackType(interceptor.getClass()); Class proxiedClass = (Class) enhancer.createClass(); Enhancer.registerCallbacks(proxiedClass, new Callback[] {interceptor}); Objenesis objenesis = new ObjenesisStd(); T proxy = (T) objenesis.newInstance(proxiedClass); return proxy; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy