com.opengamma.util.ReflectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.util.ReflectionUtils.java

Source

/**
 * 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
            }
        }
    }

}