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

com.googlecode.gwt.test.utils.JavassistUtils Maven / Gradle / Ivy

There is a newer version: 0.63
Show newest version
package com.googlecode.gwt.test.utils;

import com.googlecode.gwt.test.exceptions.GwtTestPatchException;
import com.googlecode.gwt.test.internal.GwtClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.annotation.AnnotationImpl;
import javassist.bytecode.annotation.StringMemberValue;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

/**
 * Utility class over the javassist API.
 *
 * @author Gael Lazzari
 */
public class JavassistUtils {

    public static CtConstructor findConstructor(CtClass ctClass, Class... argsClasses) {

        Set set = new HashSet();

        findConstructors(ctClass, set, argsClasses);

        switch (set.size()) {
            case 0:
                return null;
            case 1:
                return set.iterator().next();
            default:
                throw new GwtTestPatchException("Multiple constructors (" + set.size() + ") in class "
                        + ctClass.getName() + ", you have to set parameter types discriminators");
        }
    }

    @SuppressWarnings("unchecked")
    public static  javassist.bytecode.annotation.Annotation getAnnotation(
            CtClass ctClass, Class annotationClass) throws ClassNotFoundException {

        T proxiedAnnot = (T) ctClass.getAnnotation(annotationClass);

        if (proxiedAnnot == null) {
            return null;
        } else if (!Proxy.isProxyClass(proxiedAnnot.getClass())) {
            return null;
        }

        AnnotationImpl impl = (AnnotationImpl) Proxy.getInvocationHandler(proxiedAnnot);

        return impl.getAnnotation();
    }

    /**
     * Retrieve the String value of an annotation which is not available at runtime.
     *
     * @param clazz      The annotated class
     * @param annotation The annotation which is not visible at runtime
     * @param name       The name of the String property of the annotation to retrieve
     * @return The String value of the annotation or null if the annotation or its property is not
     * present
     */
    public static String getInvisibleAnnotationStringValue(Class clazz,
                                                           Class annotation, String name) {
        CtClass ctClass = GwtClassPool.getCtClass(clazz);
        ctClass.defrost();

        AnnotationsAttribute attr = (AnnotationsAttribute) ctClass.getClassFile().getAttribute(
                AnnotationsAttribute.visibleTag);
        if (attr == null) {
            attr = (AnnotationsAttribute) ctClass.getClassFile().getAttribute(
                    AnnotationsAttribute.invisibleTag);
        }
        if (attr == null) {
            return null;
        }

        javassist.bytecode.annotation.Annotation an = attr.getAnnotation(annotation.getName());

        ctClass.freeze();

        return an != null ? ((StringMemberValue) an.getMemberValue(name)).getValue() : null;
    }

    /**
     * Retrieve the String value of an annotation which is not available at runtime.
     *
     * @param method     The annotated method
     * @param annotation The annotation which is not visible at runtime
     * @param name       The name of the String property of the annotation to retrieve
     * @return The String value of the annotation or null if the annotation or its property is not
     * present
     */
    public static String getInvisibleAnnotationStringValue(Method method,
                                                           Class annotation, String name) {
        CtClass ctClass = GwtClassPool.getCtClass(method.getDeclaringClass());
        ctClass.defrost();

        AnnotationsAttribute attr = (AnnotationsAttribute) ctClass.getClassFile().getMethod(
                method.getName()).getAttribute(AnnotationsAttribute.visibleTag);
        if (attr == null) {
            attr = (AnnotationsAttribute) ctClass.getClassFile().getMethod(method.getName()).getAttribute(
                    AnnotationsAttribute.invisibleTag);
        }
        if (attr == null) {
            return null;
        }
        javassist.bytecode.annotation.Annotation an = attr.getAnnotation(annotation.getName());

        ctClass.freeze();

        return an != null ? ((StringMemberValue) an.getMemberValue(name)).getValue() : null;
    }

    private static void findConstructors(CtClass ctClass, Set set,
                                         Class... argsClasses) {
        try {

            if (ctClass == null) {
                return;
            }

            CtConstructor[] constructors = ctClass.getDeclaredConstructors();

            if (constructors.length == 0) {
                findConstructors(ctClass.getSuperclass(), set, argsClasses);
            } else if (constructors.length == 1 && argsClasses.length == 0) {
                set.add(constructors[0]);
            } else {
                for (CtConstructor c : constructors) {

                    if (c.getParameterTypes().length != argsClasses.length) {
                        continue;
                    }

                    boolean sameArgs = true;
                    for (int i = 0; i < argsClasses.length; i++) {
                        String requestedClassName = argsClasses[i].getName();
                        String currentClassName = c.getParameterTypes()[i].getName();

                        if (!requestedClassName.equals(currentClassName)) {
                            sameArgs = false;
                        }
                    }

                    if (sameArgs) {
                        set.add(c);
                    }
                }
            }
        } catch (NotFoundException e) {
            // should never happen
            throw new GwtTestPatchException("Error while trying find a constructor in class '"
                    + ctClass.getName() + "'", e);
        }
    }

    private JavassistUtils() {

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy