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

ro.pippo.controller.util.ClassUtils Maven / Gradle / Ivy

There is a newer version: 1.14.0
Show newest version
/*
 * Copyright (C) 2016 the original author or authors.
 *
 * 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 ro.pippo.controller.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.pippo.core.PippoRuntimeException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;

/**
 * Class reflection utility methods.
 *
 * @author James Moger
 */
public class ClassUtils {

    private final static Logger log = LoggerFactory.getLogger(ClassUtils.class);

    @SuppressWarnings("unchecked")
    public static  Class getClass(String className) {
        try {
            return (Class) Class.forName(className);
        } catch (Exception e) {
            throw new PippoRuntimeException("Failed to get class '{}'", className);
        }
    }

    /**
     * Returns the list of all classes within a package.
     *
     * @param packageNames
     * @return a collection of classes
     */
    public static Collection> getClasses(String... packageNames) {
        List> classes = new ArrayList<>();
        for (String packageName : packageNames) {
            final String packagePath = packageName.replace('.', '/');
            final String packagePrefix = packageName + '.';
            List packageUrls = getResources(packagePath);
            for (URL packageUrl : packageUrls) {
                if (packageUrl.getProtocol().equals("jar")) {
                    log.debug("Scanning jar {} for classes", packageUrl);
                    try {
                        String jar = packageUrl.toString().substring("jar:".length()).split("!")[0];
                        File file = new File(new URI(jar));
                        try (JarInputStream is = new JarInputStream(new FileInputStream(file))) {
                            JarEntry entry;
                            while ((entry = is.getNextJarEntry()) != null) {
                                if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
                                    String className = entry.getName().replace(".class", "").replace('/', '.');
                                    if (className.startsWith(packagePrefix)) {
                                        Class aClass = getClass(className);
                                        classes.add(aClass);
                                    }
                                }
                            }
                        }
                    } catch (URISyntaxException | IOException e) {
                        throw new PippoRuntimeException("Failed to get classes for package '{}'", e, packageName);
                    }
                } else {
                    log.debug("Scanning filesystem {} for classes", packageUrl);
                    log.debug(packageUrl.getProtocol());
                    try (InputStream is = packageUrl.openStream()) {
                        Objects.requireNonNull(is, String.format("Package url %s stream is null!", packageUrl));
                        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
                            classes.addAll(reader.lines()
                                    .filter(line -> line != null && line.endsWith(".class"))
                                    .map(line -> {
                                        String className = line.replace(".class", "").replace('/', '.');
                                        try {
                                            return getClass(packagePrefix + className);
                                        } catch (Exception e) {
                                            log.error("Failed to find {}", line, e);
                                        }

                                        return null;
                                    })
                                    .collect(Collectors.toList()));
                        }
                    } catch (IOException e) {
                        throw new PippoRuntimeException("Failed to get classes for package '{}'", e, packageName);
                    }
                }
            }
        }

        return Collections.unmodifiableCollection(classes);
    }

    public static Collection> getAnnotatedClasses(Class annotationClass, String... packageNames) {
        List> classes = getClasses(packageNames).stream()
                .filter(aClass -> aClass.isAnnotationPresent(annotationClass))
                .collect(Collectors.toList());

        return Collections.unmodifiableCollection(classes);
    }

    /**
     * Extract the annotation from the controllerMethod or the declaring class.
     *
     * @param method
     * @param annotationClass
     * @param 
     * @return the annotation or null
     */
    public static  T getAnnotation(Method method, Class annotationClass) {
        T annotation = method.getAnnotation(annotationClass);
        if (annotation == null) {
            annotation = getAnnotation(method.getDeclaringClass(), annotationClass);
        }

        return annotation;
    }

    public static  T getAnnotation(Class objectClass, Class annotationClass) {
        if (objectClass == null || Object.class == objectClass) {
            return null;
        }

        T annotation = objectClass.getAnnotation(annotationClass);
        if (annotation != null) {
            return annotation;
        }

        return getAnnotation(objectClass.getSuperclass(), annotationClass);
    }

    /**
     * Returns an array containing {@code Method} objects reflecting all the
     * declared methods of the class or interface represented by this {@code
     * Class} object, including public, protected, default (package)
     * access, and private methods, but excluding inherited methods.
     * 
     * 

This method differs from {@link Class#getDeclaredMethods()} since it * does not return bridge methods, in other words, only the methods of * the class are returned. If you just want the methods declared in * {@code clazz} use this method!

* * @param clazz Class * * @return the array of {@code Method} objects representing all the * declared methods of this class * * @see Class#getDeclaredMethods() */ public static List getDeclaredMethods(Class clazz) { return Arrays .stream(clazz.getDeclaredMethods()) .filter(method -> !method.isBridge()) .collect(Collectors.toList()); } public static List collectNestedAnnotation(Method method, Class annotationClass) { List list = new ArrayList<>(); for (Annotation annotation : method.getDeclaredAnnotations()) { if (annotation.annotationType().isAnnotationPresent(annotationClass)) { T nestedAnnotation = annotation.annotationType().getAnnotation(annotationClass); list.add(nestedAnnotation); } } list.addAll(collectNestedAnnotation(method.getDeclaringClass(), annotationClass)); return list; } public static List collectNestedAnnotation(Class objectClass, Class annotationClass) { if (objectClass == null || objectClass == Object.class) { return Collections.emptyList(); } List list = new ArrayList<>(); for (Annotation annotation : objectClass.getDeclaredAnnotations()) { if (annotation.annotationType().isAnnotationPresent(annotationClass)) { T nestedAnnotation = annotation.annotationType().getAnnotation(annotationClass); list.add(nestedAnnotation); } } list.addAll(collectNestedAnnotation(objectClass.getSuperclass(), annotationClass)); return list; } @SuppressWarnings("unchecked") public static T executeDeclaredMethod(Object o, String methodName, Object... args) { try { Method method; if (args != null && args.length > 0) { Class[] types = new Class[args.length]; for (int i = 0; i < args.length; i++) { types[i] = args[i].getClass(); } method = o.getClass().getDeclaredMethod(methodName, types); Objects.requireNonNull(method, String.format("Failed to find declared controllerMethod '%s' for args '{}' in type '%s'!", methodName, types, o.getClass().getName())); } else { method = o.getClass().getDeclaredMethod(methodName); Objects.requireNonNull(method, String.format("Failed to find declared controllerMethod '%s' in type '%s'!", methodName, o.getClass().getName())); } return (T) method.invoke(o, args); } catch (Exception e) { throw new PippoRuntimeException("Failed to execute controllerMethod '{}' on object '{}'!", e, methodName); } } public static List getResources(String name) { List list = new ArrayList<>(); try { Enumeration resources = ClassUtils.class.getClassLoader().getResources(name); while (resources.hasMoreElements()) { URL url = resources.nextElement(); list.add(url); } } catch (IOException e) { throw new PippoRuntimeException(e); } return list; } public static boolean isAssignable(Object value, Class type) { if (type.isInstance(value)) { // inheritance return true; } if (boolean.class == type && value instanceof Boolean) { return true; } else if (type.isPrimitive() && value instanceof Number) { return true; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy