JAL-3438 spotless for 2.11.2.0
[jalview.git] / test / junit / extensions / PrivilegedAccessor.java
index c5c0f04..49409e6 100644 (file)
@@ -32,618 +32,827 @@ import java.util.Map;
 import java.util.StringTokenizer;
 
 /**
- * This class is used to access a method or field of an object no matter what the access modifier of the method or field. The syntax
- * for accessing fields and methods is out of the ordinary because this class uses reflection to peel away protection.
+ * This class is used to access a method or field of an object no matter what
+ * the access modifier of the method or field. The syntax for accessing fields
+ * and methods is out of the ordinary because this class uses reflection to peel
+ * away protection.
  * <p>
  * a.k.a. The "ObjectMolester"
  * <p>
  * Here is an example of using this to access a private member: <br>
- * <code>myObject</code> is an object of type <code>MyClass</code>. <code>setName(String)</code> is a private method of
- * <code>MyClass</code>.
+ * <code>myObject</code> is an object of type <code>MyClass</code>.
+ * <code>setName(String)</code> is a private method of <code>MyClass</code>.
  * 
  * <pre>
- * PrivilegedAccessor.invokeMethod(myObject, &quot;setName(java.lang.String)&quot;, &quot;newName&quot;);
+ * PrivilegedAccessor.invokeMethod(myObject, &quot;setName(java.lang.String)&quot;,
+ *         &quot;newName&quot;);
  * </pre>
  * 
  * @author Charlie Hubbard (chubbard@iss.net)
  * @author Prashant Dhokte (pdhokte@iss.net)
  * @author Sebastian Dietrich (sebastian.dietrich@e-movimento.com)
  * 
- * @deprecated use PA instead. PA improves the functionality of PrivilegedAccessor by introducing support for varargs and removal of
- *             the necessity to catch exceptions.
+ * @deprecated use PA instead. PA improves the functionality of
+ *             PrivilegedAccessor by introducing support for varargs and removal
+ *             of the necessity to catch exceptions.
  */
 @Deprecated
 final class PrivilegedAccessor
 {
-   /**
-    * Private constructor to make it impossible to instantiate this class.
-    */
-   private PrivilegedAccessor() {
-      assert false : "You mustn't instantiate PrivilegedAccessor, use its methods statically";
-   }
-
-   /**
-    * Returns a string representation of the given object. The string has the following format: "<classname> {<attributes and values>}"
-    * whereas <attributes and values> is a comma separated list with <attributeName>=<attributeValue> <atributes and values> includes
-    * all attributes of the objects class followed by the attributes of its superclass (if any) and so on.
-    * 
-    * @param instanceOrClass the object or class to get a string representation of
-    * @return a string representation of the given object
-    */
-   public static String toString(final Object instanceOrClass) {
-      Collection<String> fields = getFieldNames(instanceOrClass);
-
-      if (fields.isEmpty())
+  /**
+   * Private constructor to make it impossible to instantiate this class.
+   */
+  private PrivilegedAccessor()
+  {
+    assert false : "You mustn't instantiate PrivilegedAccessor, use its methods statically";
+  }
+
+  /**
+   * Returns a string representation of the given object. The string has the
+   * following format: "<classname> {<attributes and values>}" whereas
+   * <attributes and values> is a comma separated list with
+   * <attributeName>=<attributeValue> <atributes and values> includes all
+   * attributes of the objects class followed by the attributes of its
+   * superclass (if any) and so on.
+   * 
+   * @param instanceOrClass
+   *          the object or class to get a string representation of
+   * @return a string representation of the given object
+   */
+  public static String toString(final Object instanceOrClass)
+  {
+    Collection<String> fields = getFieldNames(instanceOrClass);
+
+    if (fields.isEmpty())
+    {
+      return getClass(instanceOrClass).getName();
+    }
+
+    StringBuffer stringBuffer = new StringBuffer();
+
+    stringBuffer.append(getClass(instanceOrClass).getName() + " {");
+
+    for (String fieldName : fields)
+    {
+      try
       {
-        return getClass(instanceOrClass).getName();
-      }
-
-      StringBuffer stringBuffer = new StringBuffer();
-
-      stringBuffer.append(getClass(instanceOrClass).getName() + " {");
-
-      for (String fieldName : fields) {
-         try {
-            stringBuffer.append(fieldName + "=" + getValue(instanceOrClass, fieldName) + ", ");
-         } catch (NoSuchFieldException e) {
-            assert false : "It should always be possible to get a field that was just here";
-         }
-      }
-
-      stringBuffer.replace(stringBuffer.lastIndexOf(", "), stringBuffer.length(), "}");
-      return stringBuffer.toString();
-   }
-
-   /**
-    * Gets the name of all fields (public, private, protected, default) of the given instance or class. This includes as well all
-    * fields (public, private, protected, default) of all its super classes.
-    * 
-    * @param instanceOrClass the instance or class to get the fields of
-    * @return the collection of field names of the given instance or class
-    */
-   public static Collection<String> getFieldNames(final Object instanceOrClass) {
-      if (instanceOrClass == null)
-      {
-        return Collections.EMPTY_LIST;
-      }
-
-      Class<?> clazz = getClass(instanceOrClass);
-      Field[] fields = clazz.getDeclaredFields();
-      Collection<String> fieldNames = new ArrayList<String>(fields.length);
-
-      for (Field field : fields) {
-         fieldNames.add(field.getName());
-      }
-      fieldNames.addAll(getFieldNames(clazz.getSuperclass()));
-
-      return fieldNames;
-   }
-
-   /**
-    * Gets the signatures of all methods (public, private, protected, default) of the given instance or class. This includes as well
-    * all methods (public, private, protected, default) of all its super classes. This does not include constructors.
-    * 
-    * @param instanceOrClass the instance or class to get the method signatures of
-    * @return the collection of method signatures of the given instance or class
-    */
-   public static Collection<String> getMethodSignatures(final Object instanceOrClass) {
-      if (instanceOrClass == null)
-      {
-        return Collections.EMPTY_LIST;
-      }
-
-      Class<?> clazz = getClass(instanceOrClass);
-      Method[] methods = clazz.getDeclaredMethods();
-      Collection<String> methodSignatures = new ArrayList<String>(methods.length + Object.class.getDeclaredMethods().length);
-
-      for (Method method : methods) {
-         methodSignatures.add(method.getName() + "(" + getParameterTypesAsString(method.getParameterTypes()) + ")");
-      }
-      methodSignatures.addAll(getMethodSignatures(clazz.getSuperclass()));
-
-      return methodSignatures;
-   }
-
-   /**
-    * Gets the value of the named field and returns it as an object. If instanceOrClass is a class then a static field is returned.
-    * 
-    * @param instanceOrClass the instance or class to get the field from
-    * @param fieldName the name of the field
-    * @return an object representing the value of the field
-    * @throws NoSuchFieldException if the field does not exist
-    */
-   public static Object getValue(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException {
-      Field field = getField(instanceOrClass, fieldName);
-      try {
-         return field.get(instanceOrClass);
-      } catch (IllegalAccessException e) {
-         assert false : "getField() should have setAccessible(true), so an IllegalAccessException should not occur in this place";
-         return null;
-      }
-   }
-
-   /**
-    * Instantiates an object of the given class with the given arguments. If you want to instantiate a member class, you must provide
-    * the object it is a member of as first argument.
-    * 
-    * @param fromClass the class to instantiate an object from
-    * @param args the arguments to pass to the constructor
-    * @return an object of the given type
-    * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive
-    *            arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
-    *            parameter type by a method invocation conversion.
-    * @throws IllegalAccessException if this Constructor object enforces Java language access control and the underlying constructor is
-    *            inaccessible.
-    * @throws InvocationTargetException if the underlying constructor throws an exception.
-    * @throws NoSuchMethodException if the constructor could not be found
-    * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
-    * 
-    * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
-    */
-   public static <T> T instantiate(final Class<? extends T> fromClass, final Object[] args) throws IllegalArgumentException,
-      InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-      return instantiate(fromClass, getParameterTypes(args), args);
-   }
-
-   /**
-    * Instantiates an object of the given class with the given arguments and the given argument types. If you want to instantiate a
-    * member class, you must provide the object it is a member of as first argument.
-    * 
-    * 
-    * @param fromClass the class to instantiate an object from
-    * @param args the arguments to pass to the constructor
-    * @param argumentTypes the fully qualified types of the arguments of the constructor
-    * @return an object of the given type
-    * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive
-    *            arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
-    *            parameter type by a method invocation conversion.
-    * @throws IllegalAccessException if this Constructor object enforces Java language access control and the underlying constructor is
-    *            inaccessible.
-    * @throws InvocationTargetException if the underlying constructor throws an exception.
-    * @throws NoSuchMethodException if the constructor could not be found
-    * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
-    * 
-    * @see PrivilegedAccessor#instantiate(Class,Object[])
-    */
-   public static <T> T instantiate(final Class<? extends T> fromClass, final Class<?>[] argumentTypes, final Object[] args)
-      throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException,
-      NoSuchMethodException {
-      return getConstructor(fromClass, argumentTypes).newInstance(args);
-   }
-
-   /**
-    * Calls a method on the given object instance with the given arguments. Arguments can be object types or representations for
-    * primitives.
-    * 
-    * @param instanceOrClass the instance or class to invoke the method on
-    * @param methodSignature the name of the method and the parameters <br>
-    *           (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
-    * @param arguments an array of objects to pass as arguments
-    * @return the return value of this method or null if void
-    * @throws IllegalAccessException if the method is inaccessible
-    * @throws InvocationTargetException if the underlying method throws an exception.
-    * @throws NoSuchMethodException if no method with the given <code>methodSignature</code> could be found
-    * @throws IllegalArgumentException if an argument couldn't be converted to match the expected type
-    */
-   public static Object invokeMethod(final Object instanceOrClass, final String methodSignature, final Object[] arguments)
-      throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-      if ((methodSignature.indexOf('(') == -1) || (methodSignature.indexOf('(') >= methodSignature.indexOf(')')))
-      {
-        throw new NoSuchMethodException(methodSignature);
-      }
-      Class<?>[] parameterTypes = getParameterTypes(methodSignature);
-      return getMethod(instanceOrClass, getMethodName(methodSignature), parameterTypes).invoke(instanceOrClass,
-         getCorrectedArguments(parameterTypes, arguments));
-   }
-
-   /**
-    * Gets the given arguments corrected to match the given methodSignature. Correction is necessary for array arguments not to be
-    * mistaken by varargs.
-    * 
-    * @param parameterTypes the method signatue the given arguments should match
-    * @param arguments the arguments that should be corrected
-    * @return the corrected arguments
-    */
-   private static Object[] getCorrectedArguments(Class<?>[] parameterTypes, Object[] arguments) {
-      if (arguments == null)
-      {
-        return arguments;
-      }
-      if (parameterTypes.length > arguments.length)
-      {
-        return arguments;
-      }
-      if (parameterTypes.length < arguments.length)
-      {
-        return getCorrectedArguments(parameterTypes, new Object[] {arguments});
-      }
-
-      Object[] correctedArguments = new Object[arguments.length];
-      int currentArgument = 0;
-      for (Class<?> parameterType : parameterTypes) {
-         correctedArguments[currentArgument] = getCorrectedArgument(parameterType, arguments[currentArgument]);
-         currentArgument++;
-      }
-      return correctedArguments;
-   }
-
-   /**
-    * Gets the given argument corrected to match the given parameterType. Correction is necessary for array arguments not to be
-    * mistaken by varargs.
-    * 
-    * @param parameterType the type to match the given argument upon
-    * @param argument the argument to match the given parameterType
-    * @return the corrected argument
-    */
-   private static Object getCorrectedArgument(Class<?> parameterType, Object argument) {
-      if (!parameterType.isArray() || (argument == null)) {
-         return argument; // normal argument for normal parameterType
-      }
-
-      if (!argument.getClass().isArray()) {
-         return new Object[] {argument};
-      }
-
-      if (parameterType.equals(argument.getClass()))
-       {
-        return argument; // no need to cast
-      }
-
-      // (typed) array argument for (object) array parameterType, elements need to be casted
-      Object correctedArrayArgument = Array.newInstance(parameterType.getComponentType(), Array.getLength(argument));
-      for (int index = 0; index < Array.getLength(argument); index++) {
-         if (parameterType.getComponentType().isPrimitive()) { // rely on autoboxing
-            Array.set(correctedArrayArgument, index, Array.get(argument, index));
-         } else { // cast to expected type
-            try {
-               Array.set(correctedArrayArgument, index, parameterType.getComponentType().cast(Array.get(argument, index)));
-            } catch (ClassCastException e) {
-               throw new IllegalArgumentException("Argument " + argument + " of type " + argument.getClass()
-                  + " does not match expected argument type " + parameterType + ".");
-            }
-         }
-      }
-      return correctedArrayArgument;
-   }
-
-   /**
-    * Sets the value of the named field. If fieldName denotes a static field, provide a class, otherwise provide an instance. If the
-    * fieldName denotes a final field, this method could fail with an IllegalAccessException, since setting the value of final fields
-    * at other times than instantiation can have unpredictable effects.<br/>
-    * <br/>
-    * Example:<br/>
-    * <br/>
-    * <code>
-    * String myString = "Test"; <br/>
-    * <br/>
-    * //setting the private field value<br/>
-    * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
-    * <br/>
-    * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
-    * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
-    * <br/>
-    * </code>
-    * 
-    * @param instanceOrClass the instance or class to set the field
-    * @param fieldName the name of the field
-    * @param value the new value of the field
-    * @throws NoSuchFieldException if no field with the given <code>fieldName</code> can be found
-    * @throws IllegalAccessException possibly if the field was final
-    */
-   public static void setValue(final Object instanceOrClass, final String fieldName, final Object value) throws NoSuchFieldException,
-      IllegalAccessException {
-      Field field = getField(instanceOrClass, fieldName);
-      if (Modifier.isFinal(field.getModifiers())) {
-         PrivilegedAccessor.setValue(field, "modifiers", field.getModifiers() ^ Modifier.FINAL);
-      }
-      field.set(instanceOrClass, value);
-   }
-
-   /**
-    * Gets the class with the given className.
-    * 
-    * @param className the name of the class to get
-    * @return the class for the given className
-    * @throws ClassNotFoundException if the class could not be found
-    */
-   private static Class<?> getClassForName(final String className) throws ClassNotFoundException {
-      if (className.indexOf('[') > -1) {
-         Class<?> clazz = getClassForName(className.substring(0, className.indexOf('[')));
-         return Array.newInstance(clazz, 0).getClass();
-      }
-
-      if (className.indexOf("...") > -1) {
-         Class<?> clazz = getClassForName(className.substring(0, className.indexOf("...")));
-         return Array.newInstance(clazz, 0).getClass();
-      }
-
-      try {
-         return Class.forName(className, false, Thread.currentThread().getContextClassLoader());
-      } catch (ClassNotFoundException e) {
-         return getSpecialClassForName(className);
-      }
-   }
-
-   /**
-    * Maps string representation of primitives to their corresponding classes.
-    */
-   private static final Map<String, Class<?>> PRIMITIVE_MAPPER = new HashMap<String, Class<?>>(8);
-
-   /**
-    * Fills the map with all java primitives and their corresponding classes.
-    */
-   static {
-      PRIMITIVE_MAPPER.put("int", Integer.TYPE);
-      PRIMITIVE_MAPPER.put("float", Float.TYPE);
-      PRIMITIVE_MAPPER.put("double", Double.TYPE);
-      PRIMITIVE_MAPPER.put("short", Short.TYPE);
-      PRIMITIVE_MAPPER.put("long", Long.TYPE);
-      PRIMITIVE_MAPPER.put("byte", Byte.TYPE);
-      PRIMITIVE_MAPPER.put("char", Character.TYPE);
-      PRIMITIVE_MAPPER.put("boolean", Boolean.TYPE);
-   }
-
-   /**
-    * Gets special classes for the given className. Special classes are primitives and "standard" Java types (like String)
-    * 
-    * @param className the name of the class to get
-    * @return the class for the given className
-    * @throws ClassNotFoundException if the class could not be found
-    */
-   private static Class<?> getSpecialClassForName(final String className) throws ClassNotFoundException {
-      if (PRIMITIVE_MAPPER.containsKey(className))
+        stringBuffer.append(fieldName + "="
+                + getValue(instanceOrClass, fieldName) + ", ");
+      } catch (NoSuchFieldException e)
       {
-        return PRIMITIVE_MAPPER.get(className);
-      }
-
-      if (missesPackageName(className))
-      {
-        return getStandardClassForName(className);
-      }
-
-      throw new ClassNotFoundException(className);
-   }
-
-   /**
-    * Gets a 'standard' java class for the given className.
-    * 
-    * @param className the className
-    * @return the class for the given className (if any)
-    * @throws ClassNotFoundException of no 'standard' java class was found for the given className
-    */
-   private static Class<?> getStandardClassForName(String className) throws ClassNotFoundException {
-      try {
-         return Class.forName("java.lang." + className, false, Thread.currentThread().getContextClassLoader());
-      } catch (ClassNotFoundException e) {
-         try {
-            return Class.forName("java.util." + className, false, Thread.currentThread().getContextClassLoader());
-         } catch (ClassNotFoundException e1) {
-            throw new ClassNotFoundException(className);
-         }
+        assert false : "It should always be possible to get a field that was just here";
+      }
+    }
+
+    stringBuffer.replace(stringBuffer.lastIndexOf(", "),
+            stringBuffer.length(), "}");
+    return stringBuffer.toString();
+  }
+
+  /**
+   * Gets the name of all fields (public, private, protected, default) of the
+   * given instance or class. This includes as well all fields (public, private,
+   * protected, default) of all its super classes.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the fields of
+   * @return the collection of field names of the given instance or class
+   */
+  public static Collection<String> getFieldNames(
+          final Object instanceOrClass)
+  {
+    if (instanceOrClass == null)
+    {
+      return Collections.EMPTY_LIST;
+    }
+
+    Class<?> clazz = getClass(instanceOrClass);
+    Field[] fields = clazz.getDeclaredFields();
+    Collection<String> fieldNames = new ArrayList<String>(fields.length);
+
+    for (Field field : fields)
+    {
+      fieldNames.add(field.getName());
+    }
+    fieldNames.addAll(getFieldNames(clazz.getSuperclass()));
+
+    return fieldNames;
+  }
+
+  /**
+   * Gets the signatures of all methods (public, private, protected, default) of
+   * the given instance or class. This includes as well all methods (public,
+   * private, protected, default) of all its super classes. This does not
+   * include constructors.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the method signatures of
+   * @return the collection of method signatures of the given instance or class
+   */
+  public static Collection<String> getMethodSignatures(
+          final Object instanceOrClass)
+  {
+    if (instanceOrClass == null)
+    {
+      return Collections.EMPTY_LIST;
+    }
+
+    Class<?> clazz = getClass(instanceOrClass);
+    Method[] methods = clazz.getDeclaredMethods();
+    Collection<String> methodSignatures = new ArrayList<String>(
+            methods.length + Object.class.getDeclaredMethods().length);
+
+    for (Method method : methods)
+    {
+      methodSignatures.add(method.getName() + "("
+              + getParameterTypesAsString(method.getParameterTypes())
+              + ")");
+    }
+    methodSignatures.addAll(getMethodSignatures(clazz.getSuperclass()));
+
+    return methodSignatures;
+  }
+
+  /**
+   * Gets the value of the named field and returns it as an object. If
+   * instanceOrClass is a class then a static field is returned.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the field from
+   * @param fieldName
+   *          the name of the field
+   * @return an object representing the value of the field
+   * @throws NoSuchFieldException
+   *           if the field does not exist
+   */
+  public static Object getValue(final Object instanceOrClass,
+          final String fieldName) throws NoSuchFieldException
+  {
+    Field field = getField(instanceOrClass, fieldName);
+    try
+    {
+      return field.get(instanceOrClass);
+    } catch (IllegalAccessException e)
+    {
+      assert false : "getField() should have setAccessible(true), so an IllegalAccessException should not occur in this place";
+      return null;
+    }
+  }
+
+  /**
+   * Instantiates an object of the given class with the given arguments. If you
+   * want to instantiate a member class, you must provide the object it is a
+   * member of as first argument.
+   * 
+   * @param fromClass
+   *          the class to instantiate an object from
+   * @param args
+   *          the arguments to pass to the constructor
+   * @return an object of the given type
+   * @throws IllegalArgumentException
+   *           if the number of actual and formal parameters differ; if an
+   *           unwrapping conversion for primitive arguments fails; or if, after
+   *           possible unwrapping, a parameter value cannot be converted to the
+   *           corresponding formal parameter type by a method invocation
+   *           conversion.
+   * @throws IllegalAccessException
+   *           if this Constructor object enforces Java language access control
+   *           and the underlying constructor is inaccessible.
+   * @throws InvocationTargetException
+   *           if the underlying constructor throws an exception.
+   * @throws NoSuchMethodException
+   *           if the constructor could not be found
+   * @throws InstantiationException
+   *           if the class that declares the underlying constructor represents
+   *           an abstract class.
+   * 
+   * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
+   */
+  public static <T> T instantiate(final Class<? extends T> fromClass,
+          final Object[] args) throws IllegalArgumentException,
+          InstantiationException, IllegalAccessException,
+          InvocationTargetException, NoSuchMethodException
+  {
+    return instantiate(fromClass, getParameterTypes(args), args);
+  }
+
+  /**
+   * Instantiates an object of the given class with the given arguments and the
+   * given argument types. If you want to instantiate a member class, you must
+   * provide the object it is a member of as first argument.
+   * 
+   * 
+   * @param fromClass
+   *          the class to instantiate an object from
+   * @param args
+   *          the arguments to pass to the constructor
+   * @param argumentTypes
+   *          the fully qualified types of the arguments of the constructor
+   * @return an object of the given type
+   * @throws IllegalArgumentException
+   *           if the number of actual and formal parameters differ; if an
+   *           unwrapping conversion for primitive arguments fails; or if, after
+   *           possible unwrapping, a parameter value cannot be converted to the
+   *           corresponding formal parameter type by a method invocation
+   *           conversion.
+   * @throws IllegalAccessException
+   *           if this Constructor object enforces Java language access control
+   *           and the underlying constructor is inaccessible.
+   * @throws InvocationTargetException
+   *           if the underlying constructor throws an exception.
+   * @throws NoSuchMethodException
+   *           if the constructor could not be found
+   * @throws InstantiationException
+   *           if the class that declares the underlying constructor represents
+   *           an abstract class.
+   * 
+   * @see PrivilegedAccessor#instantiate(Class,Object[])
+   */
+  public static <T> T instantiate(final Class<? extends T> fromClass,
+          final Class<?>[] argumentTypes, final Object[] args)
+          throws IllegalArgumentException, InstantiationException,
+          IllegalAccessException, InvocationTargetException,
+          NoSuchMethodException
+  {
+    return getConstructor(fromClass, argumentTypes).newInstance(args);
+  }
+
+  /**
+   * Calls a method on the given object instance with the given arguments.
+   * Arguments can be object types or representations for primitives.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to invoke the method on
+   * @param methodSignature
+   *          the name of the method and the parameters <br>
+   *          (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
+   * @param arguments
+   *          an array of objects to pass as arguments
+   * @return the return value of this method or null if void
+   * @throws IllegalAccessException
+   *           if the method is inaccessible
+   * @throws InvocationTargetException
+   *           if the underlying method throws an exception.
+   * @throws NoSuchMethodException
+   *           if no method with the given <code>methodSignature</code> could be
+   *           found
+   * @throws IllegalArgumentException
+   *           if an argument couldn't be converted to match the expected type
+   */
+  public static Object invokeMethod(final Object instanceOrClass,
+          final String methodSignature, final Object[] arguments)
+          throws IllegalArgumentException, IllegalAccessException,
+          InvocationTargetException, NoSuchMethodException
+  {
+    if ((methodSignature.indexOf('(') == -1) || (methodSignature
+            .indexOf('(') >= methodSignature.indexOf(')')))
+    {
+      throw new NoSuchMethodException(methodSignature);
+    }
+    Class<?>[] parameterTypes = getParameterTypes(methodSignature);
+    return getMethod(instanceOrClass, getMethodName(methodSignature),
+            parameterTypes).invoke(instanceOrClass,
+                    getCorrectedArguments(parameterTypes, arguments));
+  }
+
+  /**
+   * Gets the given arguments corrected to match the given methodSignature.
+   * Correction is necessary for array arguments not to be mistaken by varargs.
+   * 
+   * @param parameterTypes
+   *          the method signatue the given arguments should match
+   * @param arguments
+   *          the arguments that should be corrected
+   * @return the corrected arguments
+   */
+  private static Object[] getCorrectedArguments(Class<?>[] parameterTypes,
+          Object[] arguments)
+  {
+    if (arguments == null)
+    {
+      return arguments;
+    }
+    if (parameterTypes.length > arguments.length)
+    {
+      return arguments;
+    }
+    if (parameterTypes.length < arguments.length)
+    {
+      return getCorrectedArguments(parameterTypes,
+              new Object[]
+              { arguments });
+    }
+
+    Object[] correctedArguments = new Object[arguments.length];
+    int currentArgument = 0;
+    for (Class<?> parameterType : parameterTypes)
+    {
+      correctedArguments[currentArgument] = getCorrectedArgument(
+              parameterType, arguments[currentArgument]);
+      currentArgument++;
+    }
+    return correctedArguments;
+  }
+
+  /**
+   * Gets the given argument corrected to match the given parameterType.
+   * Correction is necessary for array arguments not to be mistaken by varargs.
+   * 
+   * @param parameterType
+   *          the type to match the given argument upon
+   * @param argument
+   *          the argument to match the given parameterType
+   * @return the corrected argument
+   */
+  private static Object getCorrectedArgument(Class<?> parameterType,
+          Object argument)
+  {
+    if (!parameterType.isArray() || (argument == null))
+    {
+      return argument; // normal argument for normal parameterType
+    }
+
+    if (!argument.getClass().isArray())
+    {
+      return new Object[] { argument };
+    }
+
+    if (parameterType.equals(argument.getClass()))
+    {
+      return argument; // no need to cast
+    }
+
+    // (typed) array argument for (object) array parameterType, elements need to
+    // be casted
+    Object correctedArrayArgument = Array.newInstance(
+            parameterType.getComponentType(), Array.getLength(argument));
+    for (int index = 0; index < Array.getLength(argument); index++)
+    {
+      if (parameterType.getComponentType().isPrimitive())
+      { // rely on autoboxing
+        Array.set(correctedArrayArgument, index,
+                Array.get(argument, index));
+      }
+      else
+      { // cast to expected type
+        try
+        {
+          Array.set(correctedArrayArgument, index, parameterType
+                  .getComponentType().cast(Array.get(argument, index)));
+        } catch (ClassCastException e)
+        {
+          throw new IllegalArgumentException(
+                  "Argument " + argument + " of type " + argument.getClass()
+                          + " does not match expected argument type "
+                          + parameterType + ".");
+        }
       }
-   }
-
-   /**
-    * Tests if the given className possibly misses its package name.
-    * 
-    * @param className the className
-    * @return true if the className might miss its package name, otherwise false
-    */
-   private static boolean missesPackageName(String className) {
-      if (className.contains("."))
+    }
+    return correctedArrayArgument;
+  }
+
+  /**
+   * Sets the value of the named field. If fieldName denotes a static field,
+   * provide a class, otherwise provide an instance. If the fieldName denotes a
+   * final field, this method could fail with an IllegalAccessException, since
+   * setting the value of final fields at other times than instantiation can
+   * have unpredictable effects.<br/>
+   * <br/>
+   * Example:<br/>
+   * <br/>
+   * <code>
+   * String myString = "Test"; <br/>
+   * <br/>
+   * //setting the private field value<br/>
+   * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
+   * <br/>
+   * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
+   * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
+   * <br/>
+   * </code>
+   * 
+   * @param instanceOrClass
+   *          the instance or class to set the field
+   * @param fieldName
+   *          the name of the field
+   * @param value
+   *          the new value of the field
+   * @throws NoSuchFieldException
+   *           if no field with the given <code>fieldName</code> can be found
+   * @throws IllegalAccessException
+   *           possibly if the field was final
+   */
+  public static void setValue(final Object instanceOrClass,
+          final String fieldName, final Object value)
+          throws NoSuchFieldException, IllegalAccessException
+  {
+    Field field = getField(instanceOrClass, fieldName);
+    if (Modifier.isFinal(field.getModifiers()))
+    {
+      PrivilegedAccessor.setValue(field, "modifiers",
+              field.getModifiers() ^ Modifier.FINAL);
+    }
+    field.set(instanceOrClass, value);
+  }
+
+  /**
+   * Gets the class with the given className.
+   * 
+   * @param className
+   *          the name of the class to get
+   * @return the class for the given className
+   * @throws ClassNotFoundException
+   *           if the class could not be found
+   */
+  private static Class<?> getClassForName(final String className)
+          throws ClassNotFoundException
+  {
+    if (className.indexOf('[') > -1)
+    {
+      Class<?> clazz = getClassForName(
+              className.substring(0, className.indexOf('[')));
+      return Array.newInstance(clazz, 0).getClass();
+    }
+
+    if (className.indexOf("...") > -1)
+    {
+      Class<?> clazz = getClassForName(
+              className.substring(0, className.indexOf("...")));
+      return Array.newInstance(clazz, 0).getClass();
+    }
+
+    try
+    {
+      return Class.forName(className, false,
+              Thread.currentThread().getContextClassLoader());
+    } catch (ClassNotFoundException e)
+    {
+      return getSpecialClassForName(className);
+    }
+  }
+
+  /**
+   * Maps string representation of primitives to their corresponding classes.
+   */
+  private static final Map<String, Class<?>> PRIMITIVE_MAPPER = new HashMap<String, Class<?>>(
+          8);
+
+  /**
+   * Fills the map with all java primitives and their corresponding classes.
+   */
+  static
+  {
+    PRIMITIVE_MAPPER.put("int", Integer.TYPE);
+    PRIMITIVE_MAPPER.put("float", Float.TYPE);
+    PRIMITIVE_MAPPER.put("double", Double.TYPE);
+    PRIMITIVE_MAPPER.put("short", Short.TYPE);
+    PRIMITIVE_MAPPER.put("long", Long.TYPE);
+    PRIMITIVE_MAPPER.put("byte", Byte.TYPE);
+    PRIMITIVE_MAPPER.put("char", Character.TYPE);
+    PRIMITIVE_MAPPER.put("boolean", Boolean.TYPE);
+  }
+
+  /**
+   * Gets special classes for the given className. Special classes are
+   * primitives and "standard" Java types (like String)
+   * 
+   * @param className
+   *          the name of the class to get
+   * @return the class for the given className
+   * @throws ClassNotFoundException
+   *           if the class could not be found
+   */
+  private static Class<?> getSpecialClassForName(final String className)
+          throws ClassNotFoundException
+  {
+    if (PRIMITIVE_MAPPER.containsKey(className))
+    {
+      return PRIMITIVE_MAPPER.get(className);
+    }
+
+    if (missesPackageName(className))
+    {
+      return getStandardClassForName(className);
+    }
+
+    throw new ClassNotFoundException(className);
+  }
+
+  /**
+   * Gets a 'standard' java class for the given className.
+   * 
+   * @param className
+   *          the className
+   * @return the class for the given className (if any)
+   * @throws ClassNotFoundException
+   *           of no 'standard' java class was found for the given className
+   */
+  private static Class<?> getStandardClassForName(String className)
+          throws ClassNotFoundException
+  {
+    try
+    {
+      return Class.forName("java.lang." + className, false,
+              Thread.currentThread().getContextClassLoader());
+    } catch (ClassNotFoundException e)
+    {
+      try
       {
-        return false;
-      }
-      if (className.startsWith(className.substring(0, 1).toUpperCase(Locale.ROOT)))
+        return Class.forName("java.util." + className, false,
+                Thread.currentThread().getContextClassLoader());
+      } catch (ClassNotFoundException e1)
       {
-        return true;
-      }
+        throw new ClassNotFoundException(className);
+      }
+    }
+  }
+
+  /**
+   * Tests if the given className possibly misses its package name.
+   * 
+   * @param className
+   *          the className
+   * @return true if the className might miss its package name, otherwise false
+   */
+  private static boolean missesPackageName(String className)
+  {
+    if (className.contains("."))
+    {
       return false;
-   }
-
-   /**
-    * Gets the constructor for a given class with the given parameters.
-    * 
-    * @param type the class to instantiate
-    * @param parameterTypes the types of the parameters
-    * @return the constructor
-    * @throws NoSuchMethodException if the method could not be found
-    */
-   private static <T> Constructor<T> getConstructor(final Class<T> type, final Class<?>[] parameterTypes) throws NoSuchMethodException {
-      Constructor<T> constructor = type.getDeclaredConstructor(parameterTypes);
-      constructor.setAccessible(true);
-      return constructor;
-   }
-
-   /**
-    * Return the named field from the given instance or class. Returns a static field if instanceOrClass is a class.
-    * 
-    * @param instanceOrClass the instance or class to get the field from
-    * @param fieldName the name of the field to get
-    * @return the field
-    * @throws NoSuchFieldException if no such field can be found
-    * @throws InvalidParameterException if instanceOrClass was null
-    */
-   private static Field getField(final Object instanceOrClass, final String fieldName) throws NoSuchFieldException,
-      InvalidParameterException {
-      if (instanceOrClass == null)
+    }
+    if (className
+            .startsWith(className.substring(0, 1).toUpperCase(Locale.ROOT)))
+    {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Gets the constructor for a given class with the given parameters.
+   * 
+   * @param type
+   *          the class to instantiate
+   * @param parameterTypes
+   *          the types of the parameters
+   * @return the constructor
+   * @throws NoSuchMethodException
+   *           if the method could not be found
+   */
+  private static <T> Constructor<T> getConstructor(final Class<T> type,
+          final Class<?>[] parameterTypes) throws NoSuchMethodException
+  {
+    Constructor<T> constructor = type
+            .getDeclaredConstructor(parameterTypes);
+    constructor.setAccessible(true);
+    return constructor;
+  }
+
+  /**
+   * Return the named field from the given instance or class. Returns a static
+   * field if instanceOrClass is a class.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the field from
+   * @param fieldName
+   *          the name of the field to get
+   * @return the field
+   * @throws NoSuchFieldException
+   *           if no such field can be found
+   * @throws InvalidParameterException
+   *           if instanceOrClass was null
+   */
+  private static Field getField(final Object instanceOrClass,
+          final String fieldName)
+          throws NoSuchFieldException, InvalidParameterException
+  {
+    if (instanceOrClass == null)
+    {
+      throw new InvalidParameterException(
+              "Can't get field on null object/class");
+    }
+
+    Class<?> type = getClass(instanceOrClass);
+
+    try
+    {
+      Field field = type.getDeclaredField(fieldName);
+      field.setAccessible(true);
+      return field;
+    } catch (NoSuchFieldException e)
+    {
+      if (type.getSuperclass() == null)
       {
-        throw new InvalidParameterException("Can't get field on null object/class");
-      }
-
-      Class<?> type = getClass(instanceOrClass);
-
-      try {
-         Field field = type.getDeclaredField(fieldName);
-         field.setAccessible(true);
-         return field;
-      } catch (NoSuchFieldException e) {
-         if (type.getSuperclass() == null)
-        {
-          throw e;
-        }
-         return getField(type.getSuperclass(), fieldName);
-      }
-   }
-
-   /**
-    * Gets the class of the given parameter. If the parameter is a class, it is returned, if it is an object, its class is returned
-    * 
-    * @param instanceOrClass the instance or class to get the class of
-    * @return the class of the given parameter
-    */
-   private static Class<?> getClass(final Object instanceOrClass) {
-      if (instanceOrClass instanceof Class)
+        throw e;
+      }
+      return getField(type.getSuperclass(), fieldName);
+    }
+  }
+
+  /**
+   * Gets the class of the given parameter. If the parameter is a class, it is
+   * returned, if it is an object, its class is returned
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the class of
+   * @return the class of the given parameter
+   */
+  private static Class<?> getClass(final Object instanceOrClass)
+  {
+    if (instanceOrClass instanceof Class)
+    {
+      return (Class<?>) instanceOrClass;
+    }
+
+    return instanceOrClass.getClass();
+  }
+
+  /**
+   * Return the named method with a method signature matching classTypes from
+   * the given class.
+   * 
+   * @param type
+   *          the class to get the method from
+   * @param methodName
+   *          the name of the method to get
+   * @param parameterTypes
+   *          the parameter-types of the method to get
+   * @return the method
+   * @throws NoSuchMethodException
+   *           if the method could not be found
+   */
+  private static Method getMethod(final Class<?> type,
+          final String methodName, final Class<?>[] parameterTypes)
+          throws NoSuchMethodException
+  {
+    try
+    {
+      return type.getDeclaredMethod(methodName, parameterTypes);
+    } catch (NoSuchMethodException e)
+    {
+      if (type.getSuperclass() == null)
       {
-        return (Class<?>) instanceOrClass;
-      }
-
-      return instanceOrClass.getClass();
-   }
-
-   /**
-    * Return the named method with a method signature matching classTypes from the given class.
-    * 
-    * @param type the class to get the method from
-    * @param methodName the name of the method to get
-    * @param parameterTypes the parameter-types of the method to get
-    * @return the method
-    * @throws NoSuchMethodException if the method could not be found
-    */
-   private static Method getMethod(final Class<?> type, final String methodName, final Class<?>[] parameterTypes)
-      throws NoSuchMethodException {
-      try {
-         return type.getDeclaredMethod(methodName, parameterTypes);
-      } catch (NoSuchMethodException e) {
-         if (type.getSuperclass() == null)
-        {
-          throw e;
-        }
-         return getMethod(type.getSuperclass(), methodName, parameterTypes);
-      }
-   }
-
-   /**
-    * Gets the method with the given name and parameters from the given instance or class. If instanceOrClass is a class, then we get a
-    * static method.
-    * 
-    * @param instanceOrClass the instance or class to get the method of
-    * @param methodName the name of the method
-    * @param parameterTypes the parameter-types of the method to get
-    * @return the method
-    * @throws NoSuchMethodException if the method could not be found
-    */
-   private static Method getMethod(final Object instanceOrClass, final String methodName, final Class<?>[] parameterTypes)
-      throws NoSuchMethodException {
-      Class<?> type;
-
-      type = getClass(instanceOrClass);
-
-      Method accessMethod = getMethod(type, methodName, parameterTypes);
-      accessMethod.setAccessible(true);
-      return accessMethod;
-   }
-
-   /**
-    * Gets the name of a method.
-    * 
-    * @param methodSignature the signature of the method
-    * @return the name of the method
-    */
-   private static String getMethodName(final String methodSignature) {
-      try {
-         return methodSignature.substring(0, methodSignature.indexOf('(')).trim();
-      } catch (StringIndexOutOfBoundsException e) {
-         assert false : "Signature must have been checked before this method was called";
-         return null;
-      }
-   }
-
-   /**
-    * Gets the types of the parameters.
-    * 
-    * @param parameters the parameters
-    * @return the class-types of the arguments
-    */
-   private static Class<?>[] getParameterTypes(final Object[] parameters) {
-      if (parameters == null)
+        throw e;
+      }
+      return getMethod(type.getSuperclass(), methodName, parameterTypes);
+    }
+  }
+
+  /**
+   * Gets the method with the given name and parameters from the given instance
+   * or class. If instanceOrClass is a class, then we get a static method.
+   * 
+   * @param instanceOrClass
+   *          the instance or class to get the method of
+   * @param methodName
+   *          the name of the method
+   * @param parameterTypes
+   *          the parameter-types of the method to get
+   * @return the method
+   * @throws NoSuchMethodException
+   *           if the method could not be found
+   */
+  private static Method getMethod(final Object instanceOrClass,
+          final String methodName, final Class<?>[] parameterTypes)
+          throws NoSuchMethodException
+  {
+    Class<?> type;
+
+    type = getClass(instanceOrClass);
+
+    Method accessMethod = getMethod(type, methodName, parameterTypes);
+    accessMethod.setAccessible(true);
+    return accessMethod;
+  }
+
+  /**
+   * Gets the name of a method.
+   * 
+   * @param methodSignature
+   *          the signature of the method
+   * @return the name of the method
+   */
+  private static String getMethodName(final String methodSignature)
+  {
+    try
+    {
+      return methodSignature.substring(0, methodSignature.indexOf('('))
+              .trim();
+    } catch (StringIndexOutOfBoundsException e)
+    {
+      assert false : "Signature must have been checked before this method was called";
+      return null;
+    }
+  }
+
+  /**
+   * Gets the types of the parameters.
+   * 
+   * @param parameters
+   *          the parameters
+   * @return the class-types of the arguments
+   */
+  private static Class<?>[] getParameterTypes(final Object[] parameters)
+  {
+    if (parameters == null)
+    {
+      return new Class[0];
+    }
+
+    Class<?>[] typesOfParameters = new Class[parameters.length];
+
+    for (int i = 0; i < parameters.length; i++)
+    {
+      typesOfParameters[i] = parameters[i].getClass();
+    }
+    return typesOfParameters;
+  }
+
+  /**
+   * Gets the types of the given parameters. If the parameters don't match the
+   * given methodSignature an IllegalArgumentException is thrown.
+   * 
+   * @param methodSignature
+   *          the signature of the method
+   * @return the parameter types as class[]
+   * @throws NoSuchMethodException
+   *           if the method could not be found
+   * @throws IllegalArgumentException
+   *           if one of the given parameters doesn't math the given
+   *           methodSignature
+   */
+  private static Class<?>[] getParameterTypes(final String methodSignature)
+          throws NoSuchMethodException, IllegalArgumentException
+  {
+    String signature = getSignatureWithoutBraces(methodSignature);
+
+    StringTokenizer tokenizer = new StringTokenizer(signature, ", *");
+    Class<?>[] typesInSignature = new Class[tokenizer.countTokens()];
+
+    for (int x = 0; tokenizer.hasMoreTokens(); x++)
+    {
+      String className = tokenizer.nextToken();
+      try
       {
-        return new Class[0];
-      }
-
-      Class<?>[] typesOfParameters = new Class[parameters.length];
-
-      for (int i = 0; i < parameters.length; i++) {
-         typesOfParameters[i] = parameters[i].getClass();
-      }
-      return typesOfParameters;
-   }
-
-   /**
-    * Gets the types of the given parameters. If the parameters don't match the given methodSignature an IllegalArgumentException is
-    * thrown.
-    * 
-    * @param methodSignature the signature of the method
-    * @return the parameter types as class[]
-    * @throws NoSuchMethodException if the method could not be found
-    * @throws IllegalArgumentException if one of the given parameters doesn't math the given methodSignature
-    */
-   private static Class<?>[] getParameterTypes(final String methodSignature) throws NoSuchMethodException, IllegalArgumentException {
-      String signature = getSignatureWithoutBraces(methodSignature);
-
-      StringTokenizer tokenizer = new StringTokenizer(signature, ", *");
-      Class<?>[] typesInSignature = new Class[tokenizer.countTokens()];
-
-      for (int x = 0; tokenizer.hasMoreTokens(); x++) {
-         String className = tokenizer.nextToken();
-         try {
-            typesInSignature[x] = getClassForName(className);
-         } catch (ClassNotFoundException e) {
-            NoSuchMethodException noSuchMethodException = new NoSuchMethodException(methodSignature);
-            noSuchMethodException.initCause(e);
-            throw noSuchMethodException;
-         }
-      }
-      return typesInSignature;
-   }
-
-   /**
-    * Gets the parameter types as a string.
-    * 
-    * @param classTypes the types to get as names.
-    * @return the parameter types as a string
-    * 
-    * @see java.lang.Class#argumentTypesToString(Class[])
-    */
-   private static String getParameterTypesAsString(final Class<?>[] classTypes) {
-      assert classTypes != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
-      if (classTypes.length == 0)
+        typesInSignature[x] = getClassForName(className);
+      } catch (ClassNotFoundException e)
       {
-        return "";
-      }
-
-      StringBuilder parameterTypes = new StringBuilder();
-      for (Class<?> clazz : classTypes) {
-         assert clazz != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
-         parameterTypes.append(clazz.getName()).append(", ");
-      }
-
-      return parameterTypes.substring(0, parameterTypes.length() - 2);
-   }
-
-   /**
-    * Removes the braces around the methods signature.
-    * 
-    * @param methodSignature the signature with braces
-    * @return the signature without braces
-    */
-   private static String getSignatureWithoutBraces(final String methodSignature) {
-      try {
-         return methodSignature.substring(methodSignature.indexOf('(') + 1, methodSignature.indexOf(')'));
-      } catch (IndexOutOfBoundsException e) {
-         assert false : "signature must have been checked before this method";
-         return null;
-      }
-   }
+        NoSuchMethodException noSuchMethodException = new NoSuchMethodException(
+                methodSignature);
+        noSuchMethodException.initCause(e);
+        throw noSuchMethodException;
+      }
+    }
+    return typesInSignature;
+  }
+
+  /**
+   * Gets the parameter types as a string.
+   * 
+   * @param classTypes
+   *          the types to get as names.
+   * @return the parameter types as a string
+   * 
+   * @see java.lang.Class#argumentTypesToString(Class[])
+   */
+  private static String getParameterTypesAsString(
+          final Class<?>[] classTypes)
+  {
+    assert classTypes != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
+    if (classTypes.length == 0)
+    {
+      return "";
+    }
+
+    StringBuilder parameterTypes = new StringBuilder();
+    for (Class<?> clazz : classTypes)
+    {
+      assert clazz != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
+      parameterTypes.append(clazz.getName()).append(", ");
+    }
+
+    return parameterTypes.substring(0, parameterTypes.length() - 2);
+  }
+
+  /**
+   * Removes the braces around the methods signature.
+   * 
+   * @param methodSignature
+   *          the signature with braces
+   * @return the signature without braces
+   */
+  private static String getSignatureWithoutBraces(
+          final String methodSignature)
+  {
+    try
+    {
+      return methodSignature.substring(methodSignature.indexOf('(') + 1,
+              methodSignature.indexOf(')'));
+    } catch (IndexOutOfBoundsException e)
+    {
+      assert false : "signature must have been checked before this method";
+      return null;
+    }
+  }
 
 }