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

org.apache.commons.lang.reflect.ConstructorUtils Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
package org.apache.commons.lang.reflect;

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

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.ClassUtils;

/**
 * 

Utility reflection methods focussed on constructors, modelled after * {@link MethodUtils}.

* *

Known Limitations

Accessing Public Constructors In A Default * Access Superclass

There is an issue when invoking public constructors * contained in a default access superclass. Reflection locates these * constructors fine and correctly assigns them as public. However, an * IllegalAccessException is thrown if the constructors is * invoked.

* *

ConstructorUtils contains a workaround for this situation. It * will attempt to call setAccessible on this constructor. If this * call succeeds, then the method can be invoked as normal. This call will only * succeed when the application has sufficient security privilages. If this call * fails then a warning will be logged and the method may fail.

* * @author Apache Software Foundation * @author Craig R. McClanahan * @author Ralph Schaer * @author Chris Audley * @author Rey Francois * @author Gregor Rayman * @author Jan Sorensen * @author Robert Burrell Donkin * @author Rodney Waldhoff * @since 2.5 * @version $Id: ConstructorUtils.java 1056863 2011-01-09 02:00:25Z niallp $ */ public class ConstructorUtils { /** *

ConstructorUtils instances should NOT be constructed in standard * programming. Instead, the class should be used as * ConstructorUtils.invokeConstructor(cls, args).

* *

This constructor is public to permit tools that require a JavaBean * instance to operate.

*/ public ConstructorUtils() { super(); } /** *

Returns new instance of klazz created using the actual * arguments args. The formal parameter types are inferred from * the actual values of args. See * {@link #invokeExactConstructor(Class, Object[], Class[])} for more * details.

* *

The signatures should be assignment compatible.

* * @param cls the class to be constructed. * @param arg the actual argument * @return new instance of klazz * * @throws NoSuchMethodException If the constructor cannot be found * @throws IllegalAccessException If an error occurs accessing the constructor * @throws InvocationTargetException If an error occurs invoking the constructor * @throws InstantiationException If an error occurs instantiating the class * * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[]) */ public static Object invokeConstructor(Class cls, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { return invokeConstructor(cls, new Object[] { arg }); } /** *

Returns new instance of klazz created using the actual * arguments args. The formal parameter types are inferred from * the actual values of args. See * {@link #invokeExactConstructor(Class, Object[], Class[])} for more * details.

*

The signatures should be assignment compatible.

* * @param cls the class to be constructed. * @param args actual argument array * @return new instance of klazz * * @throws NoSuchMethodException If the constructor cannot be found * @throws IllegalAccessException If an error occurs accessing the * constructor * @throws InvocationTargetException If an error occurs invoking the * constructor * @throws InstantiationException If an error occurs instantiating the class * * @see #invokeConstructor(java.lang.Class, java.lang.Object[], * java.lang.Class[]) */ public static Object invokeConstructor(Class cls, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (null == args) { args = ArrayUtils.EMPTY_OBJECT_ARRAY; } Class parameterTypes[] = new Class[args.length]; for (int i = 0; i < args.length; i++) { parameterTypes[i] = args[i].getClass(); } return invokeConstructor(cls, args, parameterTypes); } /** *

Returns new instance of klazz created using constructor * with signature parameterTypes and actual arguments * args.

* *

The signatures should be assignment compatible.

* * @param cls the class to be constructed. * @param args actual argument array * @param parameterTypes parameter types array * @return new instance of klazz * * @throws NoSuchMethodException if matching constructor cannot be found * @throws IllegalAccessException thrown on the constructor's invocation * @throws InvocationTargetException thrown on the constructor's invocation * @throws InstantiationException thrown on the constructor's invocation * @see Constructor#newInstance */ public static Object invokeConstructor(Class cls, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (parameterTypes == null) { parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; } if (args == null) { args = ArrayUtils.EMPTY_OBJECT_ARRAY; } Constructor ctor = getMatchingAccessibleConstructor(cls, parameterTypes); if (null == ctor) { throw new NoSuchMethodException("No such accessible constructor on object: " + cls.getName()); } return ctor.newInstance(args); } /** *

Returns new instance of klazz created using the actual * arguments args. The formal parameter types are inferred from * the actual values of args. See * {@link #invokeExactConstructor(Class, Object[], Class[])} for more * details.

* *

The signatures should match exactly.

* * @param cls the class to be constructed. * @param arg the actual argument * @return new instance of klazz * * @throws NoSuchMethodException If the constructor cannot be found * @throws IllegalAccessException If an error occurs accessing the constructor * @throws InvocationTargetException If an error occurs invoking the constructor * @throws InstantiationException If an error occurs instantiating the class * * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[]) */ public static Object invokeExactConstructor(Class cls, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { return invokeExactConstructor(cls, new Object[] { arg }); } /** *

Returns new instance of klazz created using the actual * arguments args. The formal parameter types are inferred from * the actual values of args. See * {@link #invokeExactConstructor(Class, Object[], Class[])} for more * details.

* *

The signatures should match exactly.

* * @param cls the class to be constructed. * @param args actual argument array * @return new instance of klazz * * @throws NoSuchMethodException If the constructor cannot be found * @throws IllegalAccessException If an error occurs accessing the * constructor * @throws InvocationTargetException If an error occurs invoking the * constructor * @throws InstantiationException If an error occurs instantiating the class * * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], * java.lang.Class[]) */ public static Object invokeExactConstructor(Class cls, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (null == args) { args = ArrayUtils.EMPTY_OBJECT_ARRAY; } int arguments = args.length; Class parameterTypes[] = new Class[arguments]; for (int i = 0; i < arguments; i++) { parameterTypes[i] = args[i].getClass(); } return invokeExactConstructor(cls, args, parameterTypes); } /** *

Returns new instance of klazz created using constructor * with signature parameterTypes and actual arguments * args.

* *

The signatures should match exactly.

* * @param cls the class to be constructed. * @param args actual argument array * @param parameterTypes parameter types array * @return new instance of klazz * * @throws NoSuchMethodException if matching constructor cannot be found * @throws IllegalAccessException thrown on the constructor's invocation * @throws InvocationTargetException thrown on the constructor's invocation * @throws InstantiationException thrown on the constructor's invocation * @see Constructor#newInstance */ public static Object invokeExactConstructor(Class cls, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { if (args == null) { args = ArrayUtils.EMPTY_OBJECT_ARRAY; } if (parameterTypes == null) { parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; } Constructor ctor = getAccessibleConstructor(cls, parameterTypes); if (null == ctor) { throw new NoSuchMethodException("No such accessible constructor on object: " + cls.getName()); } return ctor.newInstance(args); } /** * Returns a constructor with single argument. * @param cls the class to be constructed * @param parameterType The constructor parameter type * @return null if matching accessible constructor can not be found. * @see Class#getConstructor * @see #getAccessibleConstructor(java.lang.reflect.Constructor) */ public static Constructor getAccessibleConstructor(Class cls, Class parameterType) { return getAccessibleConstructor(cls, new Class[] { parameterType }); } /** * Returns a constructor given a class and signature. * @param cls the class to be constructed * @param parameterTypes the parameter array * @return null if matching accessible constructor can not be found * @see Class#getConstructor * @see #getAccessibleConstructor(java.lang.reflect.Constructor) */ public static Constructor getAccessibleConstructor(Class cls, Class[] parameterTypes) { try { return getAccessibleConstructor(cls.getConstructor(parameterTypes)); } catch (NoSuchMethodException e) { return (null); } } /** * Returns accessible version of the given constructor. * @param ctor prototype constructor object. * @return null if accessible constructor can not be found. * @see java.lang.SecurityManager */ public static Constructor getAccessibleConstructor(Constructor ctor) { return MemberUtils.isAccessible(ctor) && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null; } /** *

Find an accessible constructor with compatible parameters. Compatible * parameters mean that every method parameter is assignable from the given * parameters. In other words, it finds constructor that will take the * parameters given.

* *

First it checks if there is constructor matching the exact signature. * If no such, all the constructors of the class are tested if their * signatures are assignment compatible with the parameter types. The first * matching constructor is returned.

* * @param cls find constructor for this class * @param parameterTypes find method with compatible parameters * @return a valid Constructor object. If there's no matching constructor, * returns null. */ public static Constructor getMatchingAccessibleConstructor(Class cls, Class[] parameterTypes) { // see if we can find the constructor directly // most of the time this works and it's much faster try { Constructor ctor = cls.getConstructor(parameterTypes); MemberUtils.setAccessibleWorkaround(ctor); return ctor; } catch (NoSuchMethodException e) { /* SWALLOW */ } Constructor result = null; // search through all constructors Constructor[] ctors = cls.getConstructors(); // return best match: for (int i = 0; i < ctors.length; i++) { // compare parameters if (ClassUtils.isAssignable(parameterTypes, ctors[i].getParameterTypes(), true)) { // get accessible version of constructor Constructor ctor = getAccessibleConstructor(ctors[i]); if (ctor != null) { MemberUtils.setAccessibleWorkaround(ctor); if (result == null || MemberUtils.compareParameterTypes(ctor.getParameterTypes(), result .getParameterTypes(), parameterTypes) < 0) { result = ctor; } } } } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy