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

play.utils.Java Maven / Gradle / Ivy

There is a newer version: 2.6.2
Show newest version
package play.utils;

import play.mvc.With;

import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

import static java.util.Collections.sort;

/**
 * Java utils
 */
public class Java {

    protected static JavaWithCaching _javaWithCaching = new JavaWithCaching();

    protected static JavaWithCaching getJavaWithCaching() {
        return _javaWithCaching;
    }

    /**
     * Retrieve parameter names of a method
     * 
     * @param method
     *            The given method
     * @return Array of parameter names
     */
    public static String[] parameterNames(Method method) {
        Parameter[] parameters = method.getParameters();
        String[] names = new String[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            names[i] = parameters[i].getName();
        }
        return names;
    }

    /**
     * Find all annotated method from a class
     * 
     * @param clazz
     *            The class
     * @param annotationType
     *            The annotation class
     * @return A list of method object
     */
    public static List findAllAnnotatedMethods(Class clazz, Class annotationType) {
        return getJavaWithCaching().findAllAnnotatedMethods(clazz, annotationType);
    }

    public static byte[] serialize(Object o) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            try (ObjectOutputStream oo = new ObjectOutputStream(baos)) {
                oo.writeObject(o);
                oo.flush();
            }
            return baos.toByteArray();
        }
    }

    public static Object deserialize(byte[] b) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(b)) {
            try (ObjectInputStream oi = new ObjectInputStream(bais)) {
                return oi.readObject();
            }
        }
    }
}

/**
 * This is an internal class uses only by the Java-class. It contains functionality with caching..
 *
 * The idea is that the Java-objects creates a new instance of JavaWithCaching, each time something new is compiled..
 *
 */
class JavaWithCaching {

    /**
     * Class uses as key for storing info about the relation between a Class and an Annotation
     */
    private static class ClassAndAnnotation {
        private final Class clazz;
        private final Class annotation;

        private ClassAndAnnotation(Class clazz, Class annotation) {
            this.clazz = clazz;
            this.annotation = annotation;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            ClassAndAnnotation that = (ClassAndAnnotation) o;

            if (annotation != null ? !annotation.equals(that.annotation) : that.annotation != null)
                return false;
            return clazz != null ? clazz.equals(that.clazz) : that.clazz == null;
        }

        @Override
        public int hashCode() {
            int result = clazz != null ? clazz.hashCode() : 0;
            result = 31 * result + (annotation != null ? annotation.hashCode() : 0);
            return result;
        }
    }

    // cache follows..

    private final Object classAndAnnotationsLock = new Object();
    private final Map> classAndAnnotation2Methods = new HashMap<>();
    private final Map, List> class2AllMethodsWithAnnotations = new HashMap<>();

    /**
     * Find all annotated method from a class
     * 
     * @param clazz
     *            The class
     * @param annotationType
     *            The annotation class
     * @return A list of method object
     */
    public List findAllAnnotatedMethods(Class clazz, Class annotationType) {

        if (clazz == null) {
            return new ArrayList<>(0);
        }

        synchronized (classAndAnnotationsLock) {

            // first look in cache

            ClassAndAnnotation key = new ClassAndAnnotation(clazz, annotationType);

            List methods = classAndAnnotation2Methods.get(key);
            if (methods != null) {
                // cache hit
                return methods;
            }
            // have to resolve it.
            methods = new ArrayList<>();

            // get list of all annotated methods on this class..
            for (Method method : findAllAnnotatedMethods(clazz)) {
                if (method.isAnnotationPresent(annotationType)) {
                    methods.add(method);
                }
            }

            sortByPriority(methods, annotationType);

            // store it in cache
            classAndAnnotation2Methods.put(key, methods);

            return methods;
        }
    }

    private void sortByPriority(List methods, final Class annotationType) {
        try {
            final Method priority = annotationType.getMethod("priority");
            sort(methods, (m1, m2) -> {
                try {
                    Integer priority1 = (Integer) priority.invoke(m1.getAnnotation(annotationType));
                    Integer priority2 = (Integer) priority.invoke(m2.getAnnotation(annotationType));
                    return priority1.compareTo(priority2);
                } catch (Exception e) {
                    // should not happen
                    throw new RuntimeException(e);
                }
            });
        } catch (NoSuchMethodException e) {
            // no need to sort - this annotation doesn't have priority() method
        }
    }

    /**
     * Find all annotated method from a class
     * 
     * @param clazz
     *            The class
     * @return A list of method object
     */
    public List findAllAnnotatedMethods(Class clazz) {
        synchronized (classAndAnnotationsLock) {
            // first check the cache..
            List methods = class2AllMethodsWithAnnotations.get(clazz);
            if (methods != null) {
                // cache hit
                return methods;
            }
            // have to resolve it..
            methods = new ArrayList<>();
            // Clazz can be null if we are looking at an interface / annotation
            while (clazz != null && !clazz.equals(Object.class)) {
                for (Method method : clazz.getDeclaredMethods()) {
                    if (method.getAnnotations().length > 0) {
                        methods.add(method);
                    }
                }
                if (clazz.isAnnotationPresent(With.class)) {
                    for (Class withClass : clazz.getAnnotation(With.class).value()) {
                        methods.addAll(findAllAnnotatedMethods(withClass));
                    }
                }
                clazz = clazz.getSuperclass();
            }

            // store it in the cache.
            class2AllMethodsWithAnnotations.put(clazz, methods);
            return methods;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy