Skip to content
Snippets Groups Projects
Commit 3bc6ace6 authored by ribeaudc's avatar ribeaudc
Browse files

change:

- 'ClassUtils.create' might accept not only 'Properties' as parameter.
- throws an 'IllegalArgumentException' instead of 'ConfigurationFailureException'.

SVN: 2980
parent 6bd7734c
No related branches found
No related tags found
No related merge requests found
......@@ -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();
}
}
......@@ -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;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment