From 3bc6ace6e402e478ab9f4d7685412258337cb610 Mon Sep 17 00:00:00 2001 From: ribeaudc <ribeaudc> Date: Fri, 7 Dec 2007 09:29:34 +0000 Subject: [PATCH] change: - 'ClassUtils.create' might accept not only 'Properties' as parameter. - throws an 'IllegalArgumentException' instead of 'ConfigurationFailureException'. SVN: 2980 --- .../cisd/common/utilities/ClassUtils.java | 70 +++++++++++---- .../cisd/common/utilities/ClassUtilsTest.java | 85 ++++++++++++------- 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java index f539f121acf..69ce8b93938 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ClassUtils.java @@ -21,13 +21,13 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import ch.systemsx.cisd.common.annotation.Mandatory; import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel; -import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; /** * Operations on classes using reflection. @@ -149,11 +149,12 @@ public final class ClassUtils * * @param superClazz Super class <code>className</code> has to be implemented or extended. * @param className Fully-qualified class name. - * @param initargs Optional constructor argument. If not <code>null</code> an constructor with one single - * <code>Properties</code> argument is expected. Otherwise the default constructor will used. + * @param argumentsOrNull Optional constructor arguments. If <code>(Object[]) null</code> then the empty + * constructor will be used. Note that <code>(Object) null</code> is not interpreted as + * <code>null</code> arguments but rather as <code>new Object[]{null}</code>. * @return an instance of type <code>interface</code>. */ - public static <T> T create(final Class<T> superClazz, final String className, final Object... initargs) + public static <T> T create(final Class<T> superClazz, final String className, final Object... argumentsOrNull) { assert superClazz != null : "Missing super class"; assert className != null : "Missing class name"; @@ -165,18 +166,31 @@ public final class ClassUtils + "' can not be instanciated as it is an interface."; assert superClazz.isAssignableFrom(clazz) : "Class '" + clazz.getName() + "' does not implements/extends '" + superClazz.getName() + "'."; - // (Object[]) null ||Ê(Object) null - if (initargs == null || (initargs.length == 1 && initargs[0] == null)) + if (argumentsOrNull == null) { return createInstance(clazz); } - final Class<?>[] classes = getClasses(initargs); - final Constructor<?> constructor = clazz.getConstructor(classes); - return createInstance(constructor, initargs); - } catch (Exception ex) + final Class<?>[] classes = getClasses(argumentsOrNull); + final Constructor<T> constructor = getConstructor(clazz, classes); + if (constructor == null) + { + throw new IllegalArgumentException(String.format("No constructor could be found for classes '%s'.", + Arrays.asList(classes))); + } + return constructor.newInstance(argumentsOrNull); + } catch (ClassNotFoundException e) + { + } catch (InstantiationException ex) + { + } catch (IllegalAccessException ex) + { + } catch (InvocationTargetException ex) + { + } catch (NoSuchMethodException ex) { - throw new ConfigurationFailureException("Cannot instantiate class '" + className + "'.", ex); } + throw new IllegalArgumentException(String.format("Cannot instantiate class '%s' with given arguments '%s'.", + className, Arrays.asList(argumentsOrNull))); } private final static Class<?>[] getClasses(final Object... initargs) @@ -191,17 +205,39 @@ public final class ClassUtils } @SuppressWarnings("unchecked") - private final static <T> T createInstance(final Class<?> clazz) throws InstantiationException, - IllegalAccessException + private final static <T> Constructor<T> getConstructor(final Class<?> clazz, final Class<?>[] classes) + throws NoSuchMethodException { - return (T) clazz.newInstance(); + final Constructor<T>[] constructors = clazz.getConstructors(); + Constructor<T> returned = null; + for (final Constructor<T> constructor : constructors) + { + final Class<?>[] parameterTypes = constructor.getParameterTypes(); + final int len = parameterTypes.length; + if (len != classes.length) + { + continue; + } + boolean match = true; + for (int i = 0; i < len; i++) + { + final Class<?> parameterType = parameterTypes[i]; + final Class<?> c = classes[i]; + match &= parameterType.equals(c) || parameterType.isAssignableFrom(c); + } + if (match) + { + returned = constructor; + } + } + return returned; } @SuppressWarnings("unchecked") - private final static <T> T createInstance(final Constructor<?> constructor, final Object... initargs) - throws InstantiationException, IllegalAccessException, InvocationTargetException + private final static <T> T createInstance(final Class<?> clazz) throws InstantiationException, + IllegalAccessException { - return (T) constructor.newInstance(initargs); + return (T) clazz.newInstance(); } } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java index 9fc609a1e25..b313078776b 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ClassUtilsTest.java @@ -23,6 +23,8 @@ import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import org.testng.annotations.Test; @@ -93,38 +95,7 @@ public final class ClassUtilsTest Properties properties = new Properties(); Appendable appendable = ClassUtils.create(Appendable.class, MyClass.class.getName(), properties); assertTrue(appendable instanceof MyClass); - assertSame(properties, ((MyClass) appendable).getProperties()); - } - - public static class MyClass implements Appendable - { - private final Properties properties; - - public MyClass(Properties properties) - { - this.properties = properties; - } - - public final Properties getProperties() - { - return properties; - } - - public Appendable append(char c) throws IOException - { - return null; - } - - public Appendable append(CharSequence csq, int start, int end) throws IOException - { - return null; - } - - public Appendable append(CharSequence csq) throws IOException - { - return null; - } - + assertSame(properties, ((MyClass) appendable).properties); } @Test @@ -153,4 +124,54 @@ public final class ClassUtilsTest .getMessage()); } } + + @Test + public final void testCreateInstanceWithAnInterfaceAsConstructorArgument() + { + final List<String> list = new ArrayList<String>(); + list.add("Hello"); + final Appendable appendable = ClassUtils.create(Appendable.class, MyClass.class.getName(), list); + assertSame(list, ((MyClass) appendable).iterable); + } + + // + // Helper Classes + // + + public final static class MyClass implements Appendable + { + Properties properties; + + Iterable<String> iterable; + + public MyClass(final Properties properties) + { + this.properties = properties; + } + + public MyClass(final Iterable<String> iterable) + { + this.iterable = iterable; + } + + // + // Appendable + // + + public Appendable append(char c) throws IOException + { + return null; + } + + public Appendable append(CharSequence csq, int start, int end) throws IOException + { + return null; + } + + public Appendable append(CharSequence csq) throws IOException + { + return null; + } + + } } -- GitLab