001    /*
002    Galois, a framework to exploit amorphous data-parallelism in irregular
003    programs.
004    
005    Copyright (C) 2010, The University of Texas at Austin. All rights reserved.
006    UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS SOFTWARE
007    AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR ANY
008    PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF PERFORMANCE, AND ANY
009    WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE.
010    NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF THE
011    SOFTWARE OR DOCUMENTATION. Under no circumstances shall University be liable
012    for incidental, special, indirect, direct or consequential damages or loss of
013    profits, interruption of business, or related expenses which may arise from use
014    of Software or Documentation, including but not limited to those resulting from
015    defects in Software and/or Documentation, or loss or inaccuracy of data of any
016    kind.
017    
018    File: Reflection.java 
019    
020    */
021    
022    
023    
024    package util;
025    
026    import java.lang.annotation.Annotation;
027    import java.lang.reflect.InvocationTargetException;
028    import java.lang.reflect.Method;
029    import java.util.ArrayList;
030    import java.util.Arrays;
031    import java.util.List;
032    
033    /**
034     * Helper methods for the package java.lang.reflect
035     */
036    public class Reflection {
037      /**
038       * Tests whether the package a class belongs to contains a given annotation.
039       * Annotations in packages are not automatically added by the compiler to the classes
040       * belonging to the package.
041       *
042       * @param className       the fully qualified name of the class
043       * @param annotationClass annotation in question
044       * @return true if the package to which the class belongs has been marked with
045       *         the given annotation.
046       */
047      public static boolean packageContainsAnnotation(String className, Class<? extends Annotation> annotationClass) {
048        return getPackageAnnotation(className, annotationClass) != null;
049      }
050    
051      public static <A extends Annotation> A getPackageAnnotation(String className, Class<A> annotationClass) {
052        Class<?> classClass = null;
053        try {
054          classClass = Class.forName(className);
055        } catch (ClassNotFoundException e) {
056          throw new RuntimeException(e);
057        }
058        Package classPackage = Package.getPackage(classClass.getPackage().getName());
059        return classPackage.getAnnotation(annotationClass);
060      }
061    
062      public static boolean containsAnnotation(String className, Class<? extends Annotation> annotationClass) {
063        return getAnnotation(className, annotationClass) != null;
064      }
065    
066      public static <A extends Annotation> A getAnnotation(String className, Class<A> annotationClass) {
067        Class<?> classClass = null;
068        try {
069          classClass = Class.forName(className);
070        } catch (ClassNotFoundException e) {
071          throw new RuntimeException(e);
072        }
073        return (A) classClass.getAnnotation(annotationClass);
074      }
075    
076      /**
077       * Creates an object of the given class, using the default constructor
078       * 
079       * @param className the fully qualified name of the class
080       * @return          an instance of the class
081       */
082      public static Object createObject(String className) {
083        Object object = null;
084        try {
085          Class<?> classDefinition = Class.forName(className);
086          object = classDefinition.newInstance();
087        } catch (Exception ex) {
088          throw new RuntimeException(ex);
089        }
090        return object;
091      }
092    
093      /**
094       * Invokes a instance method (of any visibility) of a given object.
095       * If there is more than one method with the given name in the class
096       * the instance belongs to, we invoke any of them in a non-deterministic
097       * fashion.
098       *
099       * @param o          object in which to invoke the given method
100       * @param methodName the name of the method to invoke
101       * @param params     actual parameters
102       * @return Object    return value of callee
103       */
104      public static Object invokeMethod(Object o, String methodName, Object[] params) {
105        String className = o.getClass().getName();
106        List<Object> actualParams = new ArrayList<Object>(Arrays.asList(params));
107        actualParams.add(0, o);
108        return invokeStaticMethod(className, methodName, actualParams.toArray());
109      }
110    
111      /**
112       * Invokes a static method (of any visibility) of a given class.
113       * If there is more than one static method with the given name in the class,
114       * we invoke one of them in non-deterministic fashion.
115       *
116       * @param className  the fully qualified name of the class
117       * @param methodName the name of the method to invoke
118       * @param params     actual parameters
119       * @return Object    return value of callee
120       */
121      public static Object invokeStaticMethod(String className, String methodName, Object[] params) {
122        Class<?> c = null;
123        try {
124          c = Class.forName(className);
125        } catch (ClassNotFoundException e) {
126          throw new RuntimeException(e);
127        }
128        final Method methods[] = c.getDeclaredMethods();
129        for (Method method : methods) {
130          if (methodName.equals(method.getName())) {
131            try {
132              method.setAccessible(true);
133              return method.invoke(null, params);
134            } catch (IllegalAccessException ex) {
135              throw new RuntimeException(ex);
136            } catch (InvocationTargetException ite) {
137              throw new RuntimeException(ite);
138            }
139          }
140        }
141        throw new RuntimeException("Method '" + methodName + "' not found");
142      }
143    }