package rescuecore2.misc.java;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import rescuecore2.log.Logger;
/**
A set of useful functions related to the Java language.
*/
public final class JavaTools {
private JavaTools() {}
/**
Instantiate a class by reflection. This method will not throw exceptions but will return null on error.
@param className The class name to instantiate.
@param outputClass The class that specifies the type that should be returned. This will usually be a superclass of the given class name.
@param <T> The desired return type.
@return A new instance of the given class name cast as the output class, or null if the class cannot be instantiated.
*/
public static <T> T instantiate(String className, Class<T> outputClass) {
try {
Class<? extends T> clazz = Class.forName(className).asSubclass(outputClass);
if (Modifier.isAbstract(clazz.getModifiers())) {
return null;
}
return clazz.newInstance();
}
catch (ClassNotFoundException e) {
Logger.info("Could not find class " + className);
}
catch (IllegalAccessException e) {
Logger.info("Could not instantiate class " + className);
}
catch (InstantiationException e) {
Logger.info("Could not instantiate class " + className);
}
return null;
}
/**
Instantiate a factory class by reflection. Essentially the same as {@link #instantiate(String, Class)} except that it will look for a static field called INSTANCE that contains an instance of the right class. If this doesn't exist (or in inaccessable or the wrong type) then a constructor will be used.
@param classname The class name to instantiate.
@param outputClass The class that specifies the type that should be returned. This will usually be a superclass of the given class name.
@param <T> The desired return type.
@return The content of the INSTANCE field if it exists; a new instance of the given class name cast as the output class, or null if the class cannot be instantiated.
*/
public static <T> T instantiateFactory(String classname, Class<T> outputClass) {
Class<? extends T> clazz;
try {
clazz = Class.forName(classname).asSubclass(outputClass);
}
catch (ClassNotFoundException e) {
Logger.info("Could not find class " + classname);
return null;
}
catch (ClassCastException e) {
Logger.info(classname + " is not a subclass of " + outputClass.getName(), e);
return null;
}
// Is there a singleton instance called INSTANCE?
try {
Field field = clazz.getField("INSTANCE");
if (Modifier.isStatic(field.getModifiers())) {
try {
Object o = field.get(null);
if (o != null) {
return outputClass.cast(o);
}
}
catch (IllegalAccessException e) {
Logger.info("Could not access INSTANCE field in class " + classname + ": trying constructor.");
}
catch (ClassCastException e) {
Logger.info("Could not cast INSTANCE field to " + outputClass + " in class " + classname + ": trying constructor.");
}
}
}
catch (NoSuchFieldException e) {
Logger.info("No INSTANCE field in class " + classname);
// No singleton instance. Try instantiating it.
}
try {
return clazz.newInstance();
}
catch (IllegalAccessException e) {
Logger.info("Could not instantiate class " + classname);
}
catch (InstantiationException e) {
Logger.info("Could not instantiate class " + classname);
}
return null;
}
}