at.molindo.utils.reflect.ClassUtils.java Source code

Java tutorial

Introduction

Here is the source code for at.molindo.utils.reflect.ClassUtils.java

Source

/**
 * Copyright 2010 Molindo GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package at.molindo.utils.reflect;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import at.molindo.thirdparty.org.springframework.core.GenericTypeResolver;
import at.molindo.utils.collections.ArrayUtils;
import at.molindo.utils.collections.IteratorUtils;

public class ClassUtils {
    private ClassUtils() {
    }

    /**
     * @param type
     * @param genericCls
     * @return first actual type arguments of gernicCls in type hierarchy of cls
     */
    public static Class<?> getTypeArgument(Class<?> cls, Class<?> genericCls) {
        return ArrayUtils.first(getTypeArguments(cls, genericCls));
    }

    /**
     * @param type
     * @param genericCls
     * @return actual type arguments of gernicCls in type hierarchy of cls
     */
    public static Class<?>[] getTypeArguments(Class<?> cls, Class<?> genericCls) {
        return GenericTypeResolver.resolveTypeArguments(cls, genericCls);
    }

    public static Class<?> toClass(Class<?> declaringCls, Type type) {
        return GenericTypeResolver.extractClass(declaringCls, type);
    }

    /**
     * @return <code>true</code> if <code>cls</code> is assignable to at least
     *         one class in <code>classes</code>
     */
    public static boolean isAssignable(Class<?> cls, Set<Class<?>> classes) {
        if (cls == null || classes.isEmpty()) {
            return false;
        }
        for (Class<?> c : classes) {
            if (c.isAssignableFrom(cls)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return <code>true</code> if <code>cls</code> is assignable to all
     *         <code>classes</code>
     */
    public static boolean isAssignableToAll(Class<?> cls, Set<Class<?>> classes) {
        if (cls == null) {
            return false;
        }
        for (Class<?> c : classes) {
            if (!c.isAssignableFrom(cls)) {
                return false;
            }
        }
        return true;
    }

    public static Class<?> forName(String classname) throws ClassNotFoundException {
        return forName(classname, false, null, null);
    }

    public static Class<?> forName(String classname, boolean init) throws ClassNotFoundException {
        return forName(classname, init, null, null);
    }

    public static Class<?> forName(String classname, boolean init, Thread thread) throws ClassNotFoundException {
        return forName(classname, init, thread, null);
    }

    public static Class<?> forName(String classname, boolean init, Class<?> fallback)
            throws ClassNotFoundException {
        return forName(classname, init, null, fallback);
    }

    /**
     * @param
     * @param classname
     *            fully qualified name of the desired class
     * @param init
     *            whether the class must be initialized
     * @param thread
     *            thread to use for context classloader or <code>null</code> for
     *            current thread
     * @param fallback
     *            {@link ClassLoader} providing class if no context classloader
     *            or <code>null</code> for this class
     * @return class object representing the desired class
     * @throws ClassNotFoundException
     *             if the class cannot be located by the specified class loader
     * 
     * @see Thread#currentThread()
     * @see Thread#getContextClassLoader()
     * @see Class#getClassLoader()
     * @see Class#forName(String, boolean, ClassLoader)
     */
    public static Class<?> forName(String classname, boolean init, Thread thread, Class<?> fallback)
            throws ClassNotFoundException {

        return Class.forName(classname, init, getClassLoader(thread, fallback));
    }

    public static ClassLoader getClassLoader() {
        return getClassLoader(null, null);
    }

    public static ClassLoader getClassLoader(Class<?> fallback) {
        return getClassLoader(null, fallback);
    }

    public static ClassLoader getClassLoader(Thread thread) {
        return getClassLoader(thread, null);
    }

    /**
     * @param thread
     *            {@link Thread} to use for
     *            {@link Thread#getContextClassLoader() context ClassLoader} or
     *            <code>null</code> for {@link Thread#currentThread() current
     *            thread}
     * @param fallback
     *            {@link ClassLoader} providing class if no context classloader
     *            or <code>null</code> for this class
     * @return never <code>null</code>
     */
    public static ClassLoader getClassLoader(Thread thread, Class<?> fallback) {
        if (thread == null) {
            thread = Thread.currentThread();
        }
        ClassLoader loader = thread.getContextClassLoader();

        if (loader == null) {
            loader = (fallback != null ? fallback : ClassUtils.class).getClassLoader();
        }

        if (loader == null) {
            ClassLoader.getSystemClassLoader();
        }

        return loader;
    }

    /**
     * @see #getPackageResourcePath(Class, String)
     * @see ClassLoader#getResource(String)
     */
    public static URL getClasspathResource(Class<?> scope, String resource) {
        return getClassLoader(scope).getResource(getPackageResourcePath(scope, resource));
    }

    /**
     * @see #getPackageResourcePath(Class, String)
     * @see ClassLoader#getResourceAsStream(String)
     */
    public static InputStream getClasspathResourceAsStream(Class<?> scope, String resource) {
        return getClassLoader(scope).getResourceAsStream(getPackageResourcePath(scope, resource));
    }

    /**
     * @see #getPackageResourcePath(Class, String)
     * @see ClassLoader#getResources(String)
     */
    public static Enumeration<URL> getClasspathResources(Class<?> scope, String resource) throws IOException {
        return getClassLoader(scope).getResources(getPackageResourcePath(scope, resource));
    }

    /**
     * @return the full classpath for the resource in the same package as scope
     */
    public static String getPackageResourcePath(Class<?> scope, String resource) {
        return scope.getPackage().getName().replace('.', '/') + '/' + resource;
    }

    /**
     * @return an {@link Iterator} over the {@link Class} hierarchy
     * 
     * @see Class#getSuperclass()
     */
    public static Iterator<Class<?>> hierarchy(Class<?> cls) {
        if (cls == null) {
            return IteratorUtils.empty();
        }

        class ClassHierarchyIterator implements Iterator<Class<?>> {

            private Class<?> _next;

            private ClassHierarchyIterator(Class<?> cls) {
                if (cls == null) {
                    throw new NullPointerException("cls");
                }
                _next = cls;
            }

            @Override
            public boolean hasNext() {
                return _next != null;
            }

            @Override
            public Class<?> next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }

                Class<?> next = _next;
                _next = _next.getSuperclass();
                return next;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("read-only");
            }
        }

        return new ClassHierarchyIterator(cls);
    }
}