/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.util; import java.io.Closeable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.Lifecycle; import org.springframework.util.ClassUtils; import com.opengamma.OpenGammaRuntimeException; /** * Utility to provide reflection helpers. * <p> * This is a thread-safe static utility class. */ public final class ReflectionUtils { /** * Restricted constructor. */ private ReflectionUtils() { } //------------------------------------------------------------------------- /** * Loads a Class from a full class name. * <p> * This uses Spring's {@link org.springframework.util.ClassUtils#forName(String, ClassLoader)} * passing null for the class loader. * * @param <T> the auto-cast class * @param className the class name, not null * @return the class, not null * @throws RuntimeException if the class cannot be loaded */ @SuppressWarnings("unchecked") public static <T> Class<T> loadClass(final String className) { try { return (Class<T>) ClassUtils.forName(className, null); } catch (ClassNotFoundException ex) { throw new OpenGammaRuntimeException("Class not found: " + className, ex); } } /** * Loads a Class from a full class name with a fallback class loader. * <p> * This uses Spring's {@link org.springframework.util.ClassUtils#forName(String, ClassLoader)} * passing null for the class loader. * If that fails, it calls the same method with the class loader * * @param <T> the auto-cast class * @param className the class name, not null * @param fallbackClassLoader a suitable class loader, may be null * @return the class, not null * @throws RuntimeException if the class cannot be loaded */ @SuppressWarnings("unchecked") public static <T> Class<T> loadClassWithFallbackLoader(final String className, final ClassLoader fallbackClassLoader) { try { return (Class<T>) ClassUtils.forName(className, null); } catch (ClassNotFoundException ex) { try { return (Class<T>) ClassUtils.forName(className, fallbackClassLoader); } catch (ClassNotFoundException ex2) { throw new OpenGammaRuntimeException("Class not found: " + className, ex2); } } } //------------------------------------------------------------------------- /** * Finds a constructor from a Class. * * @param <T> the type * @param type the type to create, not null * @param arguments the arguments, not null * @return the constructor, not null * @throws RuntimeException if the class cannot be loaded */ @SuppressWarnings("unchecked") public static <T> Constructor<T> findConstructorByArguments(final Class<T> type, final Object... arguments) { Class<?>[] paramTypes = new Class<?>[arguments.length]; for (int i = 0; i < arguments.length; i++) { paramTypes[i] = (arguments[i] != null ? arguments[i].getClass() : null); } Constructor<?> matched = null; for (Constructor<?> constructor : type.getConstructors()) { if (org.apache.commons.lang.ClassUtils.isAssignable(paramTypes, constructor.getParameterTypes())) { if (matched == null) { matched = constructor; } else { throw new OpenGammaRuntimeException("Multiple matching constructors: " + type); } } } if (matched == null) { throw new OpenGammaRuntimeException("No matching constructor: " + type); } return (Constructor<T>) matched; } //------------------------------------------------------------------------- /** * Finds a constructor from a Class. * * @param <T> the type * @param type the type to create, not null * @param paramTypes the parameter types, not null * @return the constructor, not null * @throws RuntimeException if the class cannot be loaded */ public static <T> Constructor<T> findConstructor(final Class<T> type, final Class<?>... paramTypes) { try { return type.getConstructor(paramTypes); } catch (NoSuchMethodException ex) { throw new OpenGammaRuntimeException(ex.getMessage(), ex); } } //------------------------------------------------------------------------- /** * Creates an instance of a class from a constructor. * * @param <T> the type * @param constructor the constructor to call, not null * @param args the arguments, not null * @return the constructor, not null * @throws RuntimeException if the class cannot be loaded */ public static <T> T newInstance(final Constructor<T> constructor, final Object... args) { try { return constructor.newInstance(args); } catch (InstantiationException ex) { throw new OpenGammaRuntimeException(ex.getMessage(), ex); } catch (IllegalAccessException ex) { throw new OpenGammaRuntimeException(ex.getMessage(), ex); } catch (InvocationTargetException ex) { if (ex.getCause() instanceof RuntimeException) { throw (RuntimeException) ex.getCause(); } throw new OpenGammaRuntimeException(ex.getMessage(), ex); } } //------------------------------------------------------------------------- /** * Checks if the class is closeable. * <p> * This invokes the close method if it is present. * * @param type the type, not null * @return true if closeable */ public static boolean isCloseable(final Class<?> type) { if (Closeable.class.isAssignableFrom(type)) { return true; } else if (Lifecycle.class.isAssignableFrom(type)) { return true; } else if (DisposableBean.class.isAssignableFrom(type)) { return true; } try { Method method = type.getMethod("close"); if (Modifier.isPublic(method.getModifiers()) && method.isSynthetic() == false) { return true; } } catch (Exception ex) { try { Method method = type.getMethod("stop"); if (Modifier.isPublic(method.getModifiers()) && method.isSynthetic() == false) { return true; } } catch (Exception ex2) { try { Method method = type.getMethod("shutdown"); if (Modifier.isPublic(method.getModifiers()) && method.isSynthetic() == false) { return true; } } catch (Exception ex3) { // ignored } } } return false; } /** * Tries to "close" an object. * <p> * This invokes the close method if it is present. * * @param obj the object, null ignored */ public static void close(final Object obj) { if (obj != null) { try { if (obj instanceof Closeable) { ((Closeable) obj).close(); } else if (obj instanceof Lifecycle) { ((Lifecycle) obj).stop(); } else if (obj instanceof DisposableBean) { ((DisposableBean) obj).destroy(); } else { invokeNoArgsNoException(obj, "close"); invokeNoArgsNoException(obj, "stop"); invokeNoArgsNoException(obj, "shutdown"); } } catch (Exception ex) { // ignored } } } /** * Invokes a no-args method on an object, throwing no errors. * * @param obj the object, null ignored * @param methodName the method name, not null */ public static void invokeNoArgsNoException(final Object obj, final String methodName) { if (obj != null) { try { obj.getClass().getMethod(methodName).invoke(obj); } catch (Exception ex2) { // ignored } } } }