ch.sdi.core.util.ClassUtil.java Source code

Java tutorial

Introduction

Here is the source code for ch.sdi.core.util.ClassUtil.java

Source

/**
 * Copyright (c) 2014 by the original author or authors.
 *
 * This code is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package ch.sdi.core.util;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.StringUtils;

/**
 * Provides some static methods for dealing with classes
 * <p>
 *
 * @version 1.0 (07.11.2014)
 * @author  Heri
 */
public class ClassUtil {

    /** logger for this class */
    private static Logger myLog = LogManager.getLogger(ClassUtil.class);

    /**
     * Constructor
     *
     */
    public ClassUtil() {
        super();
    }

    /**
     * Lists all types in the given package (recursive) which are annotated by the given annotation and
     * are assignable from given class.
     * <p>
     * All types which match the criteria are returned, no further checks (interface, abstract, embedded,
     * etc. are performed.
     * <p>
     *
     * @param aClass
     *        the desired (base) class
     * @param aAnnotation
     *        the desired annotation type
     * @param aRoot
     *        the package name where to start the search. Must not be empty. And not start
     *        with 'org.springframework' (cannot parse springs library itself).
     * @return a list of found types
     */
    @SuppressWarnings("unchecked")
    public static <T> Collection<Class<T>> findCandidatesByAnnotation(Class<T> aClass,
            Class<? extends Annotation> aAnnotation, String aRoot) {
        Collection<Class<T>> result = new ArrayList<Class<T>>();

        Collection<? extends Class<?>> candidates = findCandidatesByAnnotation(aAnnotation, aRoot);

        candidates.stream().peek(c -> myLog.trace("inspecting candidate " + c.getName()))
                .filter(c -> aClass.isAssignableFrom(c))
                .peek(c -> myLog.debug("candidate " + c.getName() + " is of desired type"))
                .forEach(c -> result.add((Class<T>) c));

        return result;

    }

    /**
    * Lists all types in the given package (recursive) which are annotated by the given annotation.
    * <p>
    * All types which match the criteria are returned, no further checks (interface, abstract, embedded, etc.
    * are performed.
    * <p>
    *
    * @param aAnnotation
    *        the desired annotation type
    * @param aRoot
    *        the package name where to start the search. Must not be empty. And not start
    *        with 'org.springframework' (cannot parse springs library itself).
    * @return a list of found types
    */
    public static Collection<? extends Class<?>> findCandidatesByAnnotation(Class<? extends Annotation> aAnnotation,
            String aRoot) {
        if (!StringUtils.hasText(aRoot)) {
            throw new IllegalArgumentException("aRoot must not be empty (cannot parse spring library classes)");

        } // if StringUtils.hasText( aRoot )

        if (aRoot.startsWith("org.springframework")) {
            throw new IllegalArgumentException("cannot parse spring library classes");

        } // if StringUtils.hasText( aRoot )

        List<Class<?>> result = new ArrayList<Class<?>>();

        MyClassScanner scanner = new MyClassScanner();

        scanner.addIncludeFilter(new AnnotationTypeFilter(aAnnotation));
        Set<BeanDefinition> canditates = scanner.findCandidateComponents(aRoot);
        for (BeanDefinition beanDefinition : canditates) {
            try {
                String classname = beanDefinition.getBeanClassName();
                Class<?> clazz = Class.forName(classname);
                result.add(clazz);
            } catch (ClassNotFoundException t) {
                myLog.error("Springs type scanner returns a class name whose class cannot be evaluated!!!", t);
            }
        }

        return result;
    }

    static class MyClassScanner extends ClassPathScanningCandidateComponentProvider {
        /**
         * Constructor
         */
        public MyClassScanner() {
            super(false);
        }

        @Override
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return true;
        }
    };

}