InstantiationHelper.java
package net.secodo.jcircuitbreaker.breakhandler.helper;
import java.lang.reflect.Constructor;
import net.secodo.jcircuitbreaker.breakhandler.BreakHandler;
import net.secodo.jcircuitbreaker.breakhandler.BreakHandlerFactory;
import net.secodo.jcircuitbreaker.breakhandler.exception.BreakHandlerException;
/**
* Helper class which role is to create new instances of given {@link BreakHandler} class.
* The class given needs to have a public one-argument constructor.
*
*/
public class InstantiationHelper {
/**
* Creates new instances of given {@link BreakHandler} class. The class given needs to have a publicly accessible(!)
* one-argument constructor.
*
* @param handlerClass the class representing break handler which should be created
* @param constructorParam constructor parameter of break handler which should be created
* @param <R> the return type of real-method for which a <i>break handler</i> is created
* @param <P> the type of constructor parameter which is used to create new instance of break handler
*
* @return new instance of {@link BreakHandler} constructed using single parameter constructor with given parameter
* value
*
* @throws BreakHandlerException in case instantiation failed
*/
@SuppressWarnings("rawtypes")
public static <R, P> BreakHandler<R> constructSingleParamInstance(Class<? extends BreakHandler> handlerClass,
P constructorParam) throws BreakHandlerException {
final BreakHandler<R> breakHandler;
try {
Constructor<? extends BreakHandler> constructor = null;
try {
Class<P> parameterClass = getConstructorParamClass(constructorParam);
constructor = handlerClass.getConstructor(parameterClass);
} catch (NoSuchMethodException originalException) {
// try to find matching constructor containing primitive type
try {
if (Integer.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(int.class);
} else if (Long.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(long.class);
} else if (Float.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(float.class);
} else if (Double.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(double.class);
} else if (Short.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(short.class);
} else if (Byte.class.isInstance(constructorParam)) {
constructor = handlerClass.getConstructor(byte.class);
} else {
throw originalException;
}
} catch (NoSuchMethodException anotherException) {
throw originalException;
}
}
breakHandler = instantiate(constructor, constructorParam);
} catch (Exception ex) {
throw new BreakHandlerException(
"Unable to create new instance of break handler of class: " + handlerClass + " " +
"by using constructor with parameter: " + constructorParam + ". The constructor must be public - otherwise " +
"you need to create custom " + BreakHandlerFactory.class.getSimpleName() + " instead of using " +
InstantiationHelper.class.getSimpleName() + " to instantiate handler class)",
ex);
}
return breakHandler;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static <R, P> BreakHandler<R> instantiate(Constructor<? extends BreakHandler> constructor,
P constructorParam)
throws InstantiationException, IllegalAccessException,
java.lang.reflect.InvocationTargetException {
return constructor.newInstance(constructorParam);
}
@SuppressWarnings("unchecked")
private static <P> Class<P> getConstructorParamClass(P constructorParam) {
return (Class<P>) constructorParam.getClass();
}
}