001package org.unix4j.util;
002
003/**
004 * Utility class with static methods to help loading a Java 7 version of a class
005 * if it is available, and the Java 6 version otherwise.
006 */
007public class Java7Util {
008
009        /**
010         * The suffix used for Java 7 classes, the string "7".
011         */
012        public static final String JAVA7_CLASS_NAME_SUFFIX = "7";
013
014        /**
015         * Returns a new instance of the Java 7 version of the given class if it
016         * exists and can be instantiated. Otherwise, the given
017         * {@code defaultInstance} is returned.
018         * <p>
019         * The Java 7 version of the class must be a subtype of {@code baseClass}
020         * and its fully qualified name must be identical to that of
021         * {@code baseClass} with a suffix "7". For instance, if the Java 6 base
022         * class is called "org.unix4j.MyClass", the Java 7 version must be called
023         * "org.unix4j.MyClass7". Furthermore, the class must have a default
024         * constructor with no arguments.
025         * <p>
026         * If the Java 7 version of the class is not found (usually because unix4j
027         * was compiled with a Java 6 compiler) or if the Java 7 class cannot be
028         * instantiated (usually because unix4j is run in a Java 6 JVM), the given
029         * {@code defaultInstance} is returned.
030         * 
031         * @param <T>
032         *            the generic return type
033         * @param baseClass
034         *            the base class and superclass of the Java 7 class
035         * @return a new instance of the Java 7 subtype if possible and
036         *         {@code defaultInstance} otherwise
037         */
038        public static <T> T newInstance(Class<T> baseClass, T defaultInstance) {
039                final Class<? extends T> clazz = loadClass(baseClass);
040                try {
041                        return clazz.newInstance();
042                } catch (Exception e) {
043                        return defaultInstance;
044                }
045        }
046
047        /**
048         * Returns the Java 7 version of the given class if it exists and can be
049         * loaded, and the given {@code baseClass} otherwise.
050         * <p>
051         * The Java 7 version of the class must be a subtype of {@code baseClass}
052         * and its fully qualified name must be identical to that of
053         * {@code baseClass} with a suffix "7". For instance, if the Java 6 base
054         * class is called "org.unix4j.MyClass", the Java 7 version must be called
055         * "org.unix4j.MyClass7".
056         * <p>
057         * If the Java 7 version of the class is not found (usually because unix4j
058         * was compiled with a Java 6 compiler), the given {@code defaultInstance}
059         * is returned. If the class is found but it is not a subtype of the given
060         * {@code baseClass}, an exception is thrown.
061         * 
062         * @param <T>
063         *            the generic type of the base class
064         * @param baseClass
065         *            the base class and superclass of the Java 7 class
066         * @return the Java 7 subclass if possible and {@code baseClass} otherwise
067         * @throws NullPointerException
068         *             if {@code baseClass} is null
069         * @throws IllegalArgumentException
070         *             if the Java 7 class is found but it is not a subclass of
071         *             {@code baseClass}
072         */
073        public static <T> Class<? extends T> loadClass(Class<T> baseClass) {
074                if (baseClass == null) {
075                        throw new NullPointerException("baseClass cannot be null");
076                }
077                final Class<?> java7Class;
078                try {
079                        java7Class = Class.forName(baseClass.getName() + JAVA7_CLASS_NAME_SUFFIX);
080                } catch (ClassNotFoundException e) {
081                        return baseClass;
082                }
083                if (baseClass.isAssignableFrom(java7Class)) {
084                        return java7Class.asSubclass(baseClass);
085                }
086                throw new IllegalArgumentException("class " + java7Class.getName() + " is not a subclass of " + baseClass.getName());
087        }
088}