All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.okta.commons.lang.Classes Maven / Gradle / Ivy

Go to download

Provides utility classes for common functionality (with no dependencies like Spring, Guava or Apache Commons.

The newest version!
/*
 * Copyright 2014 Stormpath, Inc.
 * Modifications Copyright 2018-Present Okta, Inc.
 *
 * 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 com.okta.commons.lang;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Optional;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.stream.StreamSupport;

/**
 * @since 0.5.0
 */
public class Classes {

    /**
     * Private internal log instance.
     */
    private static final Logger log = LoggerFactory.getLogger(Classes.class);

    /**
     */
    private static final ClassLoaderAccessor THREAD_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
        @Override
        protected ClassLoader doGetClassLoader() {
            return Thread.currentThread().getContextClassLoader();
        }
    };

    /**
     */
    private static final ClassLoaderAccessor CLASS_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
        @Override
        protected ClassLoader doGetClassLoader() {
            return Classes.class.getClassLoader();
        }
    };

    /**
     */
    private static final ClassLoaderAccessor SYSTEM_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
        @Override
        protected ClassLoader doGetClassLoader() {
            return ClassLoader.getSystemClassLoader();
        }
    };

    /**
     * Attempts to load the specified class name from the current thread's
     * {@link Thread#getContextClassLoader() context class loader}, then the
     * current ClassLoader ({@code Classes.class.getClassLoader()}), then the system/application
     * ClassLoader ({@code ClassLoader.getSystemClassLoader()}, in that order.  If any of them cannot locate
     * the specified class, an {@code UnknownClassException} is thrown (our RuntimeException equivalent of
     * the JRE's {@code ClassNotFoundException}.
     *
     * @param fqcn the fully qualified class name to load
     * @param  type of class
     * @return the located class
     * @throws UnknownClassException if the class cannot be found.
     */
    public static  Class forName(String fqcn) throws UnknownClassException {

        Class clazz = THREAD_CL_ACCESSOR.loadClass(fqcn);

        if (clazz == null) {
            if (log.isTraceEnabled()) {
                log.trace("Unable to load class named [" + fqcn +
                        "] from the thread context ClassLoader.  Trying the current ClassLoader...");
            }
            clazz = CLASS_CL_ACCESSOR.loadClass(fqcn);
        }

        if (clazz == null) {
            if (log.isTraceEnabled()) {
                log.trace("Unable to load class named [" + fqcn + "] from the current ClassLoader.  " +
                        "Trying the system/application ClassLoader...");
            }
            clazz = SYSTEM_CL_ACCESSOR.loadClass(fqcn);
        }

        if (clazz == null) {
            String msg = "Unable to load class named [" + fqcn + "] from the thread context, current, or " +
                    "system/application ClassLoaders.  All heuristics have been exhausted.  Class could not be found.";

            if (fqcn != null && fqcn.startsWith("com.okta.sdk.impl")) {
                msg += "  Have you remembered to include the okta-sdk-impl .jar in your runtime classpath?";
            }

            throw new UnknownClassException(msg);
        }

        return clazz;
    }

    /**
     * Returns the specified resource by checking the current thread's
     * {@link Thread#getContextClassLoader() context class loader}, then the
     * current ClassLoader ({@code Classes.class.getClassLoader()}), then the system/application
     * ClassLoader ({@code ClassLoader.getSystemClassLoader()}, in that order, using
     * {@link ClassLoader#getResourceAsStream(String) getResourceAsStream(name)}.
     *
     * @param name the name of the resource to acquire from the classloader(s).
     * @return the InputStream of the resource found, or {@code null} if the resource cannot be found from any
     *         of the three mentioned ClassLoaders.
     */
    public static InputStream getResourceAsStream(String name) {

        InputStream is = THREAD_CL_ACCESSOR.getResourceStream(name);

        if (is == null) {
            is = CLASS_CL_ACCESSOR.getResourceStream(name);
        }

        if (is == null) {
            is = SYSTEM_CL_ACCESSOR.getResourceStream(name);
        }

        return is;
    }

    public static boolean isAvailable(String fullyQualifiedClassName) {
        try {
            forName(fullyQualifiedClassName);
            return true;
        } catch (UnknownClassException e) {
            return false;
        }
    }

    public static  T newInstance(String fqcn) {
        Class clazz = forName(fqcn);
        return newInstance(clazz);
    }

    public static  T newInstance(String fqcn, Object... args) {
        Class clazz = forName(fqcn);
        return newInstance(clazz, args);
    }

    public static  T newInstance(Class clazz) {
        if (clazz == null) {
            String msg = "Class method parameter cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new InstantiationException("Unable to instantiate class [" + clazz.getName() + "]", e);
        }
    }

    public static  T newInstance(Class clazz, Object... args) {
        Class[] argTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            argTypes[i] = args[i].getClass();
        }
        Constructor ctor = getConstructor(clazz, argTypes);
        return instantiate(ctor, args);
    }

    public static  Constructor getConstructor(Class clazz, Class... argTypes) {
        try {
            return clazz.getConstructor(argTypes);
        } catch (NoSuchMethodException e) {
            throw new IllegalStateException(e);
        }

    }

    public static  T instantiate(Constructor ctor, Object... args) {
        try {
            return ctor.newInstance(args);
        } catch (Exception e) {
            String msg = "Unable to instantiate instance with constructor [" + ctor + "]";
            throw new InstantiationException(msg, e);
        }
    }

    public static  T loadFromService(Class clazz) {
        return loadFromService(clazz, "ServiceLoader failed to find implementation for class: " + clazz);
    }

    public static  T loadFromService(Class clazz, String errorMessage) {
        try {
            ServiceLoader serviceLoader = ServiceLoader.load(clazz);
            Optional result = StreamSupport.stream(serviceLoader.spliterator(), false).findFirst();
            return result.orElseThrow(() -> new IllegalStateException(errorMessage));
        } catch(ServiceConfigurationError e) {
            throw new IllegalStateException(errorMessage, e);
        }
    }

    /**
     */
    private interface ClassLoaderAccessor {
         Class loadClass(String fqcn);
        InputStream getResourceStream(String name);
    }

    /**
     */
    private static abstract class ExceptionIgnoringAccessor implements ClassLoaderAccessor {

        @SuppressWarnings("unchecked")
        public  Class loadClass(String fqcn) {
            Class clazz = null;
            ClassLoader cl = getClassLoader();
            if (cl != null) {
                try {
                    clazz = (Class)cl.loadClass(fqcn);
                } catch (ClassNotFoundException e) {
                    if (log.isTraceEnabled()) {
                        log.trace("Unable to load clazz named [" + fqcn + "] from class loader [" + cl + "]");
                    }
                }
            }
            return clazz;
        }

        public InputStream getResourceStream(String name) {
            InputStream is = null;
            ClassLoader cl = getClassLoader();
            if (cl != null) {
                is = cl.getResourceAsStream(name);
            }
            return is;
        }

        protected final ClassLoader getClassLoader() {
            try {
                return doGetClassLoader();
            } catch (Throwable t) {
                if (log.isDebugEnabled()) {
                    log.debug("Unable to acquire ClassLoader.", t);
                }
            }
            return null;
        }

        protected abstract ClassLoader doGetClassLoader() throws Throwable;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy