org.yestech.lib.lang.Clazz Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yeslib Show documentation
Show all versions of yeslib Show documentation
A collection of classes that can be used across yestech artifacts/components, but must not be dependant
on any yestech component. Most of the code is utility type code. When more than a few classes are
found to be in a package or the package start to handle more that a few reposibilities then a new
independant component is created and the existing code in yeslib is ported to the new component.
/*
* Copyright LGPL3
* YES Technology Association
* http://yestech.org
*
* http://www.opensource.org/licenses/lgpl-3.0.html
*/
package org.yestech.lib.lang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.Serializable;
/**
* Utility Class for Dealing with {@link Class} and Reflection.
*
*/
final public class Clazz {
final private static Logger logger = LoggerFactory.getLogger(Clazz.class);
private Clazz() {
super();
}
/**
* Looks up and retrieves an Initialized class. This means that the
* class with only load it's static block!
*
* @param classFqn FQN of the class to initialize
* @return The initialized Class
* @throws RuntimeException If error happens Loading or Initializing
*/
public static Class getClass(String classFqn) {
Class clazz = InMemoryReflectionCache.getClass(classFqn);
return clazz;
}
/**
* Instantiates a Class from a Fully Qualified Name. It assumes that there
* is a default Constructor.
*
* @param classFQN FQN of the class to Instantiate
* @return The Instantiated Class
* @throws RuntimeException If error happens Instantiating
*/
@SuppressWarnings("unchecked")
public static I instantiateClass(String classFQN) {
return (I)instantiateClass(getClass(classFQN));
}
/**
* Instantiates a Class from a Class. It assumes that there
* is a default Constructor.
*
* @param clazz Class to Instantiate
* @return The Instantiated Class
* @throws RuntimeException If error happens Instantiating
*/
@SuppressWarnings("unchecked")
public static I instantiateClass(Class clazz) {
try {
return (I)clazz.newInstance();
} catch (Exception e) {
logger.error("Error Instantiating Class: " + clazz, e);
throw new RuntimeException("Error Instantiating Class: " + clazz, e);
}
}
/**
* Returns the Method that is a associated with the FQN class.
*
* @param classFQN The FQN of the class method is a member of
* @param methodName The method name
* @param params Array of Class the are in the method parameter list
* @return the {@link Method} found
* @throws RuntimeException If error happens Loading Method
*/
public static Method getMethod(String classFQN, String methodName, Class[] params) {
return InMemoryReflectionCache.getMethod(classFQN, methodName, params);
}
/**
* Dynamically invokes a method using the supplied params as the parameters for the call.
* If the method being invoked is static, the instance should be null.
*
* @param method Method to invoke
* @param methodArgs Parameters that will be passed to the method
* @param instance Instance of the Onject to invoke method on. (null if method is static)
* @return The result of the method call
* @throws RuntimeException If error happens Invoking Method
*/
public static Object invoke(Method method, Object[] methodArgs, Object instance) {
try {
return method.invoke(instance, methodArgs);
} catch (Exception e) {
logger.error("Error Invoking Method: " + method.getName(), e);
throw new RuntimeException("Error Invoking Method: " + method.getName(), e);
}
}
/**
* Dynamically invokes a method using the supplied params as the parameters for the call.
* If the method being invoked is static, the instance should be null.
*
* @param classFQN The FQN of the class method is a member of
* @param methodName The method name
* @param params Array of Class the are in the method parameter list
* @param methodArgs Parameters that will be passed to the method
* @param instance Instance of the Onject to invoke method on. (null if method is static)
* @return The result of the method call
* @throws RuntimeException If error happens Invoking Method
*/
public static Object invoke(String classFQN, String methodName, Class[] params,
Object[] methodArgs, Object instance) {
return invoke(getMethod(classFQN, methodName, params), methodArgs, instance);
}
/**
* Returns a Cached Method associated by the methodName. If the method
* isn't in the cache a new one is created and added to the cache. There
* will ALWAYS be only one method instance in the cache.
*
* @param clazz Class method associated with
* @param methodName Name of the method
* @param argTypes Class Array of argument types in method signature
* @return The Method
*/
public static Method getMethod(Class clazz, String methodName, Class[] argTypes) {
return InMemoryReflectionCache.getMethod(clazz, methodName, argTypes);
}
/**
* Returns a Cached Constructor associated with the Class. If the
* Constructor isn't in the cache a new one is created and added to the
* cache. There will ALWAYS be only one Constructor instance in the
* cache.
*
* @param clazz Class Constructor associated with
* @param ctorTypes Class Array of argument types in Constructors signature
* @return The Constructor
*/
public static Constructor getConstructor(Class clazz, Class[] ctorTypes) {
return InMemoryReflectionCache.getCtor(clazz, ctorTypes);
}
/**
* This class represents the manager for all the different cache policies.
*
* @author Arthur Copeland
*/
private static class InMemoryReflectionCache implements Serializable {
//--------------------------------------------------------------------------
// C L A S S V A R I A B L E S
//--------------------------------------------------------------------------
final private static Logger logger = LoggerFactory.getLogger(InMemoryReflectionCache.class);
final private static HashMap classCache = new HashMap();
final private static HashMap methodCache = new HashMap();
final private static HashMap ctorCache = new HashMap();
//--------------------------------------------------------------------------
// S T A T I C I N I T I A L I Z E R
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// C O N S T R U C T O R S
//--------------------------------------------------------------------------
/**
* default ctor
*/
private InMemoryReflectionCache() {
super();
}
//--------------------------------------------------------------------------
// S T A T I C M E T H O D S
//--------------------------------------------------------------------------
/**
* Returns a Cached Initialized Class associated by the className. If the
* class isn't in the cache a new one is created, initialized and added to
* the cache. There will ALWAYS be only one class instance in the
* cache.
*
* @param className FQN of Class to find and initialize
* @return The Class
*/
public static Class getClass(String className) {
Class clazz = classCache.get(className);
if (clazz == null) {
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
classCache.put(className, clazz);
}
return clazz;
}
/**
* Returns a Cached Method associated by the methodName. If the method
* isn't in the cache a new one is created and added to the cache. There
* will ALWAYS be only one method instance in the cache.
*
* @param clazzName FQN of Class method associated with
* @param methodName Name of the method
* @param argTypes Class Array of argument types in method signature
* @return The Method
*/
public static Method getMethod(String clazzName, String methodName,
Class[] argTypes) {
return getMethod(getClass(clazzName), methodName, argTypes);
}
/**
* Returns a Cached Method associated by the methodName. If the method
* isn't in the cache a new one is created and added to the cache. There
* will ALWAYS be only one method instance in the cache.
*
* @param clazz Class method associated with
* @param methodName Name of the method
* @param argTypes Class Array of argument types in method signature
* @return The Method
*/
public static Method getMethod(Class clazz, String methodName,
Class[] argTypes) {
Method method = null;
ArrayList methods = null;
methods = methodCache.get(methodName);
if (methods == null) {
synchronized (methodCache) {
methods = methodCache.get(methodName);
if (methods == null) {
methods = new ArrayList();
methodCache.put(methodName, methods);
}
}
}
int sz = methods.size();
if (sz == 0) {
try {
method = clazz.getMethod(methodName, argTypes);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
synchronized (methods) {
if (!methods.contains(method)) {
methods.add(method);
}
}
} else {
for (int i = 0; i < sz; i++) {
Method tmethod = methods.get(i);
Class targTypes[] = tmethod.getParameterTypes();
if ((argTypes == null || argTypes.length == 0) &&
(targTypes == null || targTypes.length == 0)) {
method = tmethod;
} else {
int tsz = targTypes.length;
if (argTypes.length == tsz) {
//find the first method that satisfies the argTypes!!!!!
boolean valid = false;
for (int t = 0; t < tsz; t++) {
boolean good =
argTypes[t].isAssignableFrom(targTypes[t]);
if (!good) {
valid = false;
break;
} else {
valid = true;
}
}
if (valid) {
method = tmethod;
}
}
}
}
if (method == null) {
try {
method = clazz.getMethod(methodName, argTypes);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
synchronized (methods) {
if (!methods.contains(method)) {
methods.add(method);
}
}
}
}
return method;
}
/**
* Returns a Cached Constructor associated with the className. If the
* Constructor isn't in the cache a new one is created and added to the
* cache. There will ALWAYS be only one Constructor instance in the
* cache.
*
* @param clazzName FQN of Class Constructor associated with
* @param ctorTypes Class Array of argument types in Constructors signature
* @return The Constructor
*/
public static Constructor getCtor(String clazzName, Class[] ctorTypes) {
return getCtor(getClass(clazzName), ctorTypes);
}
/**
* Returns a Cached Constructor associated with the Class. If the
* Constructor isn't in the cache a new one is created and added to the
* cache. There will ALWAYS be only one Constructor instance in the
* cache.
*
* @param clazz Class Constructor associated with
* @param ctorTypes Class Array of argument types in Constructors signature
* @return The Constructor
*/
public static Constructor getCtor(Class clazz, Class[] ctorTypes) {
String ctorName = clazz.getName();
Constructor ctor = null;
ArrayList ctors = null;
ctors = ctorCache.get(ctorName);
if (ctors == null) {
synchronized (ctorCache) {
ctors = ctorCache.get(ctorName);
if (ctors == null) {
ctors = new ArrayList();
ctorCache.put(ctorName, ctors);
}
}
}
int sz = ctors.size();
if (sz == 0) {
try {
ctor = clazz.getConstructor(ctorTypes);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
synchronized (ctors) {
if (!ctors.contains(ctor)) {
ctors.add(ctor);
}
}
} else {
for (int i = 0; i < sz; i++) {
Constructor tctor = ctors.get(i);
Class tctorTypes[] = tctor.getParameterTypes();
if ((ctorTypes == null || ctorTypes.length == 0) &&
(tctorTypes == null || tctorTypes.length == 0)) {
ctor = tctor;
} else {
int tsz = tctorTypes.length;
if (ctorTypes.length == tsz) {
//find the first ctor that satisfies the ctorTypes!!!!!
boolean valid = false;
for (int t = 0; t < tsz; t++) {
boolean good =
ctorTypes[t].isAssignableFrom(tctorTypes[t]);
if (!good) {
valid = false;
break;
} else {
valid = true;
}
}
if (valid) {
ctor = tctor;
}
}
}
}
if (ctor == null) {
try {
ctor = clazz.getConstructor(ctorTypes);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
synchronized (ctors) {
if (!ctors.contains(ctor)) {
ctors.add(ctor);
}
}
}
}
return ctor;
}
//--------------------------------------------------------------------------
// F A C T O R Y M E T H O D S
//--------------------------------------------------------------------------
/**
* Returns a CacheManager.
*
* @return a CacheManager
*/
public static InMemoryReflectionCache getManager() {
return new InMemoryReflectionCache();
}
}
}