Clover icon

Coverage Report

  1. Project Clover database Mon Nov 11 2024 20:42:03 GMT
  2. Package junit.extensions

File PrivilegedAccessor.java

 

Coverage histogram

../../img/srcFileCovDistChart2.png
54% of files have more coverage

Code metrics

58
155
26
1
858
431
68
0.44
5.96
26
2.62

Classes

Class Line # Actions
PrivilegedAccessor 60 155 68
0.1464435214.6%
 

Contributing tests

This file is covered by 34 tests. .

Source view

1    /*
2    * Copyright 2004-2012 Sebastian Dietrich (Sebastian.Dietrich@e-movimento.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16    package junit.extensions;
17   
18    import java.util.Locale;
19   
20    import java.lang.reflect.Array;
21    import java.lang.reflect.Constructor;
22    import java.lang.reflect.Field;
23    import java.lang.reflect.InvocationTargetException;
24    import java.lang.reflect.Method;
25    import java.lang.reflect.Modifier;
26    import java.security.InvalidParameterException;
27    import java.util.ArrayList;
28    import java.util.Collection;
29    import java.util.Collections;
30    import java.util.HashMap;
31    import java.util.Map;
32    import java.util.StringTokenizer;
33   
34    /**
35    * This class is used to access a method or field of an object no matter what
36    * the access modifier of the method or field. The syntax for accessing fields
37    * and methods is out of the ordinary because this class uses reflection to peel
38    * away protection.
39    * <p>
40    * a.k.a. The "ObjectMolester"
41    * <p>
42    * Here is an example of using this to access a private member: <br>
43    * <code>myObject</code> is an object of type <code>MyClass</code>.
44    * <code>setName(String)</code> is a private method of <code>MyClass</code>.
45    *
46    * <pre>
47    * PrivilegedAccessor.invokeMethod(myObject, &quot;setName(java.lang.String)&quot;,
48    * &quot;newName&quot;);
49    * </pre>
50    *
51    * @author Charlie Hubbard (chubbard@iss.net)
52    * @author Prashant Dhokte (pdhokte@iss.net)
53    * @author Sebastian Dietrich (sebastian.dietrich@e-movimento.com)
54    *
55    * @deprecated use PA instead. PA improves the functionality of
56    * PrivilegedAccessor by introducing support for varargs and removal
57    * of the necessity to catch exceptions.
58    */
59    @Deprecated
 
60    final class PrivilegedAccessor
61    {
62    /**
63    * Private constructor to make it impossible to instantiate this class.
64    */
 
65  0 toggle private PrivilegedAccessor()
66    {
67    assert false : "You mustn't instantiate PrivilegedAccessor, use its methods statically";
68    }
69   
70    /**
71    * Returns a string representation of the given object. The string has the
72    * following format: "<classname> {<attributes and values>}" whereas
73    * <attributes and values> is a comma separated list with
74    * <attributeName>=<attributeValue> <atributes and values> includes all
75    * attributes of the objects class followed by the attributes of its
76    * superclass (if any) and so on.
77    *
78    * @param instanceOrClass
79    * the object or class to get a string representation of
80    * @return a string representation of the given object
81    */
 
82  0 toggle public static String toString(final Object instanceOrClass)
83    {
84  0 Collection<String> fields = getFieldNames(instanceOrClass);
85   
86  0 if (fields.isEmpty())
87    {
88  0 return getClass(instanceOrClass).getName();
89    }
90   
91  0 StringBuffer stringBuffer = new StringBuffer();
92   
93  0 stringBuffer.append(getClass(instanceOrClass).getName() + " {");
94   
95  0 for (String fieldName : fields)
96    {
97  0 try
98    {
99  0 stringBuffer.append(fieldName + "="
100    + getValue(instanceOrClass, fieldName) + ", ");
101    } catch (NoSuchFieldException e)
102    {
103    assert false : "It should always be possible to get a field that was just here";
104    }
105    }
106   
107  0 stringBuffer.replace(stringBuffer.lastIndexOf(", "),
108    stringBuffer.length(), "}");
109  0 return stringBuffer.toString();
110    }
111   
112    /**
113    * Gets the name of all fields (public, private, protected, default) of the
114    * given instance or class. This includes as well all fields (public, private,
115    * protected, default) of all its super classes.
116    *
117    * @param instanceOrClass
118    * the instance or class to get the fields of
119    * @return the collection of field names of the given instance or class
120    */
 
121  0 toggle public static Collection<String> getFieldNames(
122    final Object instanceOrClass)
123    {
124  0 if (instanceOrClass == null)
125    {
126  0 return Collections.EMPTY_LIST;
127    }
128   
129  0 Class<?> clazz = getClass(instanceOrClass);
130  0 Field[] fields = clazz.getDeclaredFields();
131  0 Collection<String> fieldNames = new ArrayList<String>(fields.length);
132   
133  0 for (Field field : fields)
134    {
135  0 fieldNames.add(field.getName());
136    }
137  0 fieldNames.addAll(getFieldNames(clazz.getSuperclass()));
138   
139  0 return fieldNames;
140    }
141   
142    /**
143    * Gets the signatures of all methods (public, private, protected, default) of
144    * the given instance or class. This includes as well all methods (public,
145    * private, protected, default) of all its super classes. This does not
146    * include constructors.
147    *
148    * @param instanceOrClass
149    * the instance or class to get the method signatures of
150    * @return the collection of method signatures of the given instance or class
151    */
 
152  0 toggle public static Collection<String> getMethodSignatures(
153    final Object instanceOrClass)
154    {
155  0 if (instanceOrClass == null)
156    {
157  0 return Collections.EMPTY_LIST;
158    }
159   
160  0 Class<?> clazz = getClass(instanceOrClass);
161  0 Method[] methods = clazz.getDeclaredMethods();
162  0 Collection<String> methodSignatures = new ArrayList<String>(
163    methods.length + Object.class.getDeclaredMethods().length);
164   
165  0 for (Method method : methods)
166    {
167  0 methodSignatures.add(method.getName() + "("
168    + getParameterTypesAsString(method.getParameterTypes())
169    + ")");
170    }
171  0 methodSignatures.addAll(getMethodSignatures(clazz.getSuperclass()));
172   
173  0 return methodSignatures;
174    }
175   
176    /**
177    * Gets the value of the named field and returns it as an object. If
178    * instanceOrClass is a class then a static field is returned.
179    *
180    * @param instanceOrClass
181    * the instance or class to get the field from
182    * @param fieldName
183    * the name of the field
184    * @return an object representing the value of the field
185    * @throws NoSuchFieldException
186    * if the field does not exist
187    */
 
188  174 toggle public static Object getValue(final Object instanceOrClass,
189    final String fieldName) throws NoSuchFieldException
190    {
191  174 Field field = getField(instanceOrClass, fieldName);
192  174 try
193    {
194  174 return field.get(instanceOrClass);
195    } catch (IllegalAccessException e)
196    {
197    assert false : "getField() should have setAccessible(true), so an IllegalAccessException should not occur in this place";
198  0 return null;
199    }
200    }
201   
202    /**
203    * Instantiates an object of the given class with the given arguments. If you
204    * want to instantiate a member class, you must provide the object it is a
205    * member of as first argument.
206    *
207    * @param fromClass
208    * the class to instantiate an object from
209    * @param args
210    * the arguments to pass to the constructor
211    * @return an object of the given type
212    * @throws IllegalArgumentException
213    * if the number of actual and formal parameters differ; if an
214    * unwrapping conversion for primitive arguments fails; or if, after
215    * possible unwrapping, a parameter value cannot be converted to the
216    * corresponding formal parameter type by a method invocation
217    * conversion.
218    * @throws IllegalAccessException
219    * if this Constructor object enforces Java language access control
220    * and the underlying constructor is inaccessible.
221    * @throws InvocationTargetException
222    * if the underlying constructor throws an exception.
223    * @throws NoSuchMethodException
224    * if the constructor could not be found
225    * @throws InstantiationException
226    * if the class that declares the underlying constructor represents
227    * an abstract class.
228    *
229    * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
230    */
 
231  0 toggle public static <T> T instantiate(final Class<? extends T> fromClass,
232    final Object[] args) throws IllegalArgumentException,
233    InstantiationException, IllegalAccessException,
234    InvocationTargetException, NoSuchMethodException
235    {
236  0 return instantiate(fromClass, getParameterTypes(args), args);
237    }
238   
239    /**
240    * Instantiates an object of the given class with the given arguments and the
241    * given argument types. If you want to instantiate a member class, you must
242    * provide the object it is a member of as first argument.
243    *
244    *
245    * @param fromClass
246    * the class to instantiate an object from
247    * @param args
248    * the arguments to pass to the constructor
249    * @param argumentTypes
250    * the fully qualified types of the arguments of the constructor
251    * @return an object of the given type
252    * @throws IllegalArgumentException
253    * if the number of actual and formal parameters differ; if an
254    * unwrapping conversion for primitive arguments fails; or if, after
255    * possible unwrapping, a parameter value cannot be converted to the
256    * corresponding formal parameter type by a method invocation
257    * conversion.
258    * @throws IllegalAccessException
259    * if this Constructor object enforces Java language access control
260    * and the underlying constructor is inaccessible.
261    * @throws InvocationTargetException
262    * if the underlying constructor throws an exception.
263    * @throws NoSuchMethodException
264    * if the constructor could not be found
265    * @throws InstantiationException
266    * if the class that declares the underlying constructor represents
267    * an abstract class.
268    *
269    * @see PrivilegedAccessor#instantiate(Class,Object[])
270    */
 
271  0 toggle public static <T> T instantiate(final Class<? extends T> fromClass,
272    final Class<?>[] argumentTypes, final Object[] args)
273    throws IllegalArgumentException, InstantiationException,
274    IllegalAccessException, InvocationTargetException,
275    NoSuchMethodException
276    {
277  0 return getConstructor(fromClass, argumentTypes).newInstance(args);
278    }
279   
280    /**
281    * Calls a method on the given object instance with the given arguments.
282    * Arguments can be object types or representations for primitives.
283    *
284    * @param instanceOrClass
285    * the instance or class to invoke the method on
286    * @param methodSignature
287    * the name of the method and the parameters <br>
288    * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
289    * @param arguments
290    * an array of objects to pass as arguments
291    * @return the return value of this method or null if void
292    * @throws IllegalAccessException
293    * if the method is inaccessible
294    * @throws InvocationTargetException
295    * if the underlying method throws an exception.
296    * @throws NoSuchMethodException
297    * if no method with the given <code>methodSignature</code> could be
298    * found
299    * @throws IllegalArgumentException
300    * if an argument couldn't be converted to match the expected type
301    */
 
302  0 toggle public static Object invokeMethod(final Object instanceOrClass,
303    final String methodSignature, final Object[] arguments)
304    throws IllegalArgumentException, IllegalAccessException,
305    InvocationTargetException, NoSuchMethodException
306    {
307  0 if ((methodSignature.indexOf('(') == -1) || (methodSignature
308    .indexOf('(') >= methodSignature.indexOf(')')))
309    {
310  0 throw new NoSuchMethodException(methodSignature);
311    }
312  0 Class<?>[] parameterTypes = getParameterTypes(methodSignature);
313  0 return getMethod(instanceOrClass, getMethodName(methodSignature),
314    parameterTypes).invoke(instanceOrClass,
315    getCorrectedArguments(parameterTypes, arguments));
316    }
317   
318    /**
319    * Gets the given arguments corrected to match the given methodSignature.
320    * Correction is necessary for array arguments not to be mistaken by varargs.
321    *
322    * @param parameterTypes
323    * the method signatue the given arguments should match
324    * @param arguments
325    * the arguments that should be corrected
326    * @return the corrected arguments
327    */
 
328  0 toggle private static Object[] getCorrectedArguments(Class<?>[] parameterTypes,
329    Object[] arguments)
330    {
331  0 if (arguments == null)
332    {
333  0 return arguments;
334    }
335  0 if (parameterTypes.length > arguments.length)
336    {
337  0 return arguments;
338    }
339  0 if (parameterTypes.length < arguments.length)
340    {
341  0 return getCorrectedArguments(parameterTypes,
342    new Object[]
343    { arguments });
344    }
345   
346  0 Object[] correctedArguments = new Object[arguments.length];
347  0 int currentArgument = 0;
348  0 for (Class<?> parameterType : parameterTypes)
349    {
350  0 correctedArguments[currentArgument] = getCorrectedArgument(
351    parameterType, arguments[currentArgument]);
352  0 currentArgument++;
353    }
354  0 return correctedArguments;
355    }
356   
357    /**
358    * Gets the given argument corrected to match the given parameterType.
359    * Correction is necessary for array arguments not to be mistaken by varargs.
360    *
361    * @param parameterType
362    * the type to match the given argument upon
363    * @param argument
364    * the argument to match the given parameterType
365    * @return the corrected argument
366    */
 
367  0 toggle private static Object getCorrectedArgument(Class<?> parameterType,
368    Object argument)
369    {
370  0 if (!parameterType.isArray() || (argument == null))
371    {
372  0 return argument; // normal argument for normal parameterType
373    }
374   
375  0 if (!argument.getClass().isArray())
376    {
377  0 return new Object[] { argument };
378    }
379   
380  0 if (parameterType.equals(argument.getClass()))
381    {
382  0 return argument; // no need to cast
383    }
384   
385    // (typed) array argument for (object) array parameterType, elements need to
386    // be casted
387  0 Object correctedArrayArgument = Array.newInstance(
388    parameterType.getComponentType(), Array.getLength(argument));
389  0 for (int index = 0; index < Array.getLength(argument); index++)
390    {
391  0 if (parameterType.getComponentType().isPrimitive())
392    { // rely on autoboxing
393  0 Array.set(correctedArrayArgument, index,
394    Array.get(argument, index));
395    }
396    else
397    { // cast to expected type
398  0 try
399    {
400  0 Array.set(correctedArrayArgument, index, parameterType
401    .getComponentType().cast(Array.get(argument, index)));
402    } catch (ClassCastException e)
403    {
404  0 throw new IllegalArgumentException(
405    "Argument " + argument + " of type " + argument.getClass()
406    + " does not match expected argument type "
407    + parameterType + ".");
408    }
409    }
410    }
411  0 return correctedArrayArgument;
412    }
413   
414    /**
415    * Sets the value of the named field. If fieldName denotes a static field,
416    * provide a class, otherwise provide an instance. If the fieldName denotes a
417    * final field, this method could fail with an IllegalAccessException, since
418    * setting the value of final fields at other times than instantiation can
419    * have unpredictable effects.<br/>
420    * <br/>
421    * Example:<br/>
422    * <br/>
423    * <code>
424    * String myString = "Test"; <br/>
425    * <br/>
426    * //setting the private field value<br/>
427    * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
428    * <br/>
429    * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
430    * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
431    * <br/>
432    * </code>
433    *
434    * @param instanceOrClass
435    * the instance or class to set the field
436    * @param fieldName
437    * the name of the field
438    * @param value
439    * the new value of the field
440    * @throws NoSuchFieldException
441    * if no field with the given <code>fieldName</code> can be found
442    * @throws IllegalAccessException
443    * possibly if the field was final
444    */
 
445  18 toggle public static void setValue(final Object instanceOrClass,
446    final String fieldName, final Object value)
447    throws NoSuchFieldException, IllegalAccessException
448    {
449  18 Field field = getField(instanceOrClass, fieldName);
450  18 if (Modifier.isFinal(field.getModifiers()))
451    {
452  0 PrivilegedAccessor.setValue(field, "modifiers",
453    field.getModifiers() ^ Modifier.FINAL);
454    }
455  18 field.set(instanceOrClass, value);
456    }
457   
458    /**
459    * Gets the class with the given className.
460    *
461    * @param className
462    * the name of the class to get
463    * @return the class for the given className
464    * @throws ClassNotFoundException
465    * if the class could not be found
466    */
 
467  0 toggle private static Class<?> getClassForName(final String className)
468    throws ClassNotFoundException
469    {
470  0 if (className.indexOf('[') > -1)
471    {
472  0 Class<?> clazz = getClassForName(
473    className.substring(0, className.indexOf('[')));
474  0 return Array.newInstance(clazz, 0).getClass();
475    }
476   
477  0 if (className.indexOf("...") > -1)
478    {
479  0 Class<?> clazz = getClassForName(
480    className.substring(0, className.indexOf("...")));
481  0 return Array.newInstance(clazz, 0).getClass();
482    }
483   
484  0 try
485    {
486  0 return Class.forName(className, false,
487    Thread.currentThread().getContextClassLoader());
488    } catch (ClassNotFoundException e)
489    {
490  0 return getSpecialClassForName(className);
491    }
492    }
493   
494    /**
495    * Maps string representation of primitives to their corresponding classes.
496    */
497    private static final Map<String, Class<?>> PRIMITIVE_MAPPER = new HashMap<String, Class<?>>(
498    8);
499   
500    /**
501    * Fills the map with all java primitives and their corresponding classes.
502    */
 
503  1 toggle static
504    {
505  1 PRIMITIVE_MAPPER.put("int", Integer.TYPE);
506  1 PRIMITIVE_MAPPER.put("float", Float.TYPE);
507  1 PRIMITIVE_MAPPER.put("double", Double.TYPE);
508  1 PRIMITIVE_MAPPER.put("short", Short.TYPE);
509  1 PRIMITIVE_MAPPER.put("long", Long.TYPE);
510  1 PRIMITIVE_MAPPER.put("byte", Byte.TYPE);
511  1 PRIMITIVE_MAPPER.put("char", Character.TYPE);
512  1 PRIMITIVE_MAPPER.put("boolean", Boolean.TYPE);
513    }
514   
515    /**
516    * Gets special classes for the given className. Special classes are
517    * primitives and "standard" Java types (like String)
518    *
519    * @param className
520    * the name of the class to get
521    * @return the class for the given className
522    * @throws ClassNotFoundException
523    * if the class could not be found
524    */
 
525  0 toggle private static Class<?> getSpecialClassForName(final String className)
526    throws ClassNotFoundException
527    {
528  0 if (PRIMITIVE_MAPPER.containsKey(className))
529    {
530  0 return PRIMITIVE_MAPPER.get(className);
531    }
532   
533  0 if (missesPackageName(className))
534    {
535  0 return getStandardClassForName(className);
536    }
537   
538  0 throw new ClassNotFoundException(className);
539    }
540   
541    /**
542    * Gets a 'standard' java class for the given className.
543    *
544    * @param className
545    * the className
546    * @return the class for the given className (if any)
547    * @throws ClassNotFoundException
548    * of no 'standard' java class was found for the given className
549    */
 
550  0 toggle private static Class<?> getStandardClassForName(String className)
551    throws ClassNotFoundException
552    {
553  0 try
554    {
555  0 return Class.forName("java.lang." + className, false,
556    Thread.currentThread().getContextClassLoader());
557    } catch (ClassNotFoundException e)
558    {
559  0 try
560    {
561  0 return Class.forName("java.util." + className, false,
562    Thread.currentThread().getContextClassLoader());
563    } catch (ClassNotFoundException e1)
564    {
565  0 throw new ClassNotFoundException(className);
566    }
567    }
568    }
569   
570    /**
571    * Tests if the given className possibly misses its package name.
572    *
573    * @param className
574    * the className
575    * @return true if the className might miss its package name, otherwise false
576    */
 
577  0 toggle private static boolean missesPackageName(String className)
578    {
579  0 if (className.contains("."))
580    {
581  0 return false;
582    }
583  0 if (className
584    .startsWith(className.substring(0, 1).toUpperCase(Locale.ROOT)))
585    {
586  0 return true;
587    }
588  0 return false;
589    }
590   
591    /**
592    * Gets the constructor for a given class with the given parameters.
593    *
594    * @param type
595    * the class to instantiate
596    * @param parameterTypes
597    * the types of the parameters
598    * @return the constructor
599    * @throws NoSuchMethodException
600    * if the method could not be found
601    */
 
602  0 toggle private static <T> Constructor<T> getConstructor(final Class<T> type,
603    final Class<?>[] parameterTypes) throws NoSuchMethodException
604    {
605  0 Constructor<T> constructor = type
606    .getDeclaredConstructor(parameterTypes);
607  0 constructor.setAccessible(true);
608  0 return constructor;
609    }
610   
611    /**
612    * Return the named field from the given instance or class. Returns a static
613    * field if instanceOrClass is a class.
614    *
615    * @param instanceOrClass
616    * the instance or class to get the field from
617    * @param fieldName
618    * the name of the field to get
619    * @return the field
620    * @throws NoSuchFieldException
621    * if no such field can be found
622    * @throws InvalidParameterException
623    * if instanceOrClass was null
624    */
 
625  204 toggle private static Field getField(final Object instanceOrClass,
626    final String fieldName)
627    throws NoSuchFieldException, InvalidParameterException
628    {
629  204 if (instanceOrClass == null)
630    {
631  0 throw new InvalidParameterException(
632    "Can't get field on null object/class");
633    }
634   
635  204 Class<?> type = getClass(instanceOrClass);
636   
637  204 try
638    {
639  204 Field field = type.getDeclaredField(fieldName);
640  192 field.setAccessible(true);
641  192 return field;
642    } catch (NoSuchFieldException e)
643    {
644  12 if (type.getSuperclass() == null)
645    {
646  0 throw e;
647    }
648  12 return getField(type.getSuperclass(), fieldName);
649    }
650    }
651   
652    /**
653    * Gets the class of the given parameter. If the parameter is a class, it is
654    * returned, if it is an object, its class is returned
655    *
656    * @param instanceOrClass
657    * the instance or class to get the class of
658    * @return the class of the given parameter
659    */
 
660  204 toggle private static Class<?> getClass(final Object instanceOrClass)
661    {
662  204 if (instanceOrClass instanceof Class)
663    {
664  14 return (Class<?>) instanceOrClass;
665    }
666   
667  190 return instanceOrClass.getClass();
668    }
669   
670    /**
671    * Return the named method with a method signature matching classTypes from
672    * the given class.
673    *
674    * @param type
675    * the class to get the method from
676    * @param methodName
677    * the name of the method to get
678    * @param parameterTypes
679    * the parameter-types of the method to get
680    * @return the method
681    * @throws NoSuchMethodException
682    * if the method could not be found
683    */
 
684  0 toggle private static Method getMethod(final Class<?> type,
685    final String methodName, final Class<?>[] parameterTypes)
686    throws NoSuchMethodException
687    {
688  0 try
689    {
690  0 return type.getDeclaredMethod(methodName, parameterTypes);
691    } catch (NoSuchMethodException e)
692    {
693  0 if (type.getSuperclass() == null)
694    {
695  0 throw e;
696    }
697  0 return getMethod(type.getSuperclass(), methodName, parameterTypes);
698    }
699    }
700   
701    /**
702    * Gets the method with the given name and parameters from the given instance
703    * or class. If instanceOrClass is a class, then we get a static method.
704    *
705    * @param instanceOrClass
706    * the instance or class to get the method of
707    * @param methodName
708    * the name of the method
709    * @param parameterTypes
710    * the parameter-types of the method to get
711    * @return the method
712    * @throws NoSuchMethodException
713    * if the method could not be found
714    */
 
715  0 toggle private static Method getMethod(final Object instanceOrClass,
716    final String methodName, final Class<?>[] parameterTypes)
717    throws NoSuchMethodException
718    {
719  0 Class<?> type;
720   
721  0 type = getClass(instanceOrClass);
722   
723  0 Method accessMethod = getMethod(type, methodName, parameterTypes);
724  0 accessMethod.setAccessible(true);
725  0 return accessMethod;
726    }
727   
728    /**
729    * Gets the name of a method.
730    *
731    * @param methodSignature
732    * the signature of the method
733    * @return the name of the method
734    */
 
735  0 toggle private static String getMethodName(final String methodSignature)
736    {
737  0 try
738    {
739  0 return methodSignature.substring(0, methodSignature.indexOf('('))
740    .trim();
741    } catch (StringIndexOutOfBoundsException e)
742    {
743    assert false : "Signature must have been checked before this method was called";
744  0 return null;
745    }
746    }
747   
748    /**
749    * Gets the types of the parameters.
750    *
751    * @param parameters
752    * the parameters
753    * @return the class-types of the arguments
754    */
 
755  0 toggle private static Class<?>[] getParameterTypes(final Object[] parameters)
756    {
757  0 if (parameters == null)
758    {
759  0 return new Class[0];
760    }
761   
762  0 Class<?>[] typesOfParameters = new Class[parameters.length];
763   
764  0 for (int i = 0; i < parameters.length; i++)
765    {
766  0 typesOfParameters[i] = parameters[i].getClass();
767    }
768  0 return typesOfParameters;
769    }
770   
771    /**
772    * Gets the types of the given parameters. If the parameters don't match the
773    * given methodSignature an IllegalArgumentException is thrown.
774    *
775    * @param methodSignature
776    * the signature of the method
777    * @return the parameter types as class[]
778    * @throws NoSuchMethodException
779    * if the method could not be found
780    * @throws IllegalArgumentException
781    * if one of the given parameters doesn't math the given
782    * methodSignature
783    */
 
784  0 toggle private static Class<?>[] getParameterTypes(final String methodSignature)
785    throws NoSuchMethodException, IllegalArgumentException
786    {
787  0 String signature = getSignatureWithoutBraces(methodSignature);
788   
789  0 StringTokenizer tokenizer = new StringTokenizer(signature, ", *");
790  0 Class<?>[] typesInSignature = new Class[tokenizer.countTokens()];
791   
792  0 for (int x = 0; tokenizer.hasMoreTokens(); x++)
793    {
794  0 String className = tokenizer.nextToken();
795  0 try
796    {
797  0 typesInSignature[x] = getClassForName(className);
798    } catch (ClassNotFoundException e)
799    {
800  0 NoSuchMethodException noSuchMethodException = new NoSuchMethodException(
801    methodSignature);
802  0 noSuchMethodException.initCause(e);
803  0 throw noSuchMethodException;
804    }
805    }
806  0 return typesInSignature;
807    }
808   
809    /**
810    * Gets the parameter types as a string.
811    *
812    * @param classTypes
813    * the types to get as names.
814    * @return the parameter types as a string
815    *
816    * @see java.lang.Class#argumentTypesToString(Class[])
817    */
 
818  0 toggle private static String getParameterTypesAsString(
819    final Class<?>[] classTypes)
820    {
821  0 assert classTypes != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
822  0 if (classTypes.length == 0)
823    {
824  0 return "";
825    }
826   
827  0 StringBuilder parameterTypes = new StringBuilder();
828  0 for (Class<?> clazz : classTypes)
829    {
830  0 assert clazz != null : "getParameterTypes() should have been called before this method and should have provided not-null classTypes";
831  0 parameterTypes.append(clazz.getName()).append(", ");
832    }
833   
834  0 return parameterTypes.substring(0, parameterTypes.length() - 2);
835    }
836   
837    /**
838    * Removes the braces around the methods signature.
839    *
840    * @param methodSignature
841    * the signature with braces
842    * @return the signature without braces
843    */
 
844  0 toggle private static String getSignatureWithoutBraces(
845    final String methodSignature)
846    {
847  0 try
848    {
849  0 return methodSignature.substring(methodSignature.indexOf('(') + 1,
850    methodSignature.indexOf(')'));
851    } catch (IndexOutOfBoundsException e)
852    {
853    assert false : "signature must have been checked before this method";
854  0 return null;
855    }
856    }
857   
858    }