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 java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

import javassist.CtClass;
import javassist.CtConstructor;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.annotation.AnnotationImpl;
import javassist.bytecode.annotation.StringMemberValue;

import com.googlecode.gwt.test.exceptions.GwtTestPatchException;
import com.googlecode.gwt.test.internal.GwtClassPool;

/**
 * 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