Clover icon

Coverage Report

  1. Project Clover database Thu Nov 28 2024 18:06:40 GMT
  2. Package junit.extensions

File PA.java

 

Coverage histogram

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

Code metrics

6
32
14
1
449
118
24
0.75
2.29
14
1.71

Classes

Class Line # Actions
PA 67 32 24
0.1730769317.3%
 

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.Collection;
19   
20    /**
21    * This class is used to access a method or field of an object no matter what
22    * the access modifier of the method or field. The syntax for accessing fields
23    * and methods is out of the ordinary because this class uses reflection to peel
24    * away protection.
25    * <p>
26    * a.k.a. The "ObjectMolester"
27    * <p>
28    * Here is an example of using this to access a private member: <br>
29    * Given the following class <code>MyClass</code>: <br>
30    *
31    * <pre>
32    * public class MyClass
33    * {
34    * private String name; // private attribute
35    *
36    * // private constructor
37    * private MyClass()
38    * {
39    * super();
40    * }
41    *
42    * // private method
43    * private void setName(String newName)
44    * {
45    * this.name = newName;
46    * }
47    * }
48    * </pre>
49    *
50    * We now want to access the class: <br>
51    *
52    * <pre>
53    * MyClass myObj = PA.instantiate(MyClass.class);
54    * PA.invokeMethod(myObj, &quot;setName(java.lang.String)&quot;, &quot;myNewName&quot;);
55    * String name = PA.getValue(myObj, &quot;name&quot;);
56    * </pre>
57    *
58    * This class extends {@link PrivilegedAccessor} by re-throwing checked
59    * {@link Exception}s as {@link RuntimeException}s.
60    *
61    *
62    * @see PrivilegedAccessor
63    *
64    * @author Sebastian Dietrich (sebastian.dietrich@e-movimento.com)
65    * @author Lubos Bistak (lubos@bistak.sk)
66    */
 
67    public class PA
68    {
69    private final Object instanceOrClass;
70   
71    /**
72    * Private constructor to make it impossible to instantiate this class from
73    * outside of PA.
74    *
75    * @param instanceOrClass
76    */
 
77  18 toggle private PA(Object instanceOrClass)
78    {
79  18 this.instanceOrClass = instanceOrClass;
80    }
81   
82    /**
83    * Returns a string representation of the given object. The string has the
84    * following format: "<classname> {<attributes and values>}" whereas
85    * <attributes and values> is a comma separated list with
86    * <attributeName>=<attributeValue> <atributes and values> includes all
87    * attributes of the objects class followed by the attributes of its
88    * superclass (if any) and so on.
89    *
90    * @param instanceOrClass
91    * the object or class to get a string representation of
92    * @return a string representation of the given object
93    *
94    * @see PrivilegedAccessor#toString(Object)
95    */
 
96  0 toggle public static String toString(final Object instanceOrClass)
97    {
98  0 return PrivilegedAccessor.toString(instanceOrClass);
99    }
100   
101    /**
102    * Gets the name of all fields (public, private, protected, default) of the
103    * given instance or class. This includes as well all fields (public, private,
104    * protected, default) of all its super classes.
105    *
106    * @param instanceOrClass
107    * the instance or class to get the fields of
108    * @return the collection of field names of the given instance or class
109    *
110    * @see PrivilegedAccessor#getFieldNames(Object)
111    */
 
112  0 toggle public static Collection<String> getFieldNames(
113    final Object instanceOrClass)
114    {
115  0 return PrivilegedAccessor.getFieldNames(instanceOrClass);
116    }
117   
118    /**
119    * Gets the signatures of all methods (public, private, protected, default) of
120    * the given instance or class. This includes as well all methods (public,
121    * private, protected, default) of all its super classes. This does not
122    * include constructors.
123    *
124    * @param instanceOrClass
125    * the instance or class to get the method signatures of
126    * @return the collection of method signatures of the given instance or class
127    *
128    * @see PrivilegedAccessor#getMethodSignatures(Object)
129    */
 
130  0 toggle public static Collection<String> getMethodSignatures(
131    final Object instanceOrClass)
132    {
133  0 return PrivilegedAccessor.getMethodSignatures(instanceOrClass);
134    }
135   
136    /**
137    * Gets the value of the named field and returns it as an object. If
138    * instanceOrClass is a class then a static field is returned.
139    *
140    * @param instanceOrClass
141    * the instance or class to get the field from
142    * @param fieldName
143    * the name of the field
144    * @return an object representing the value of the field
145    * @throws IllegalArgumentException
146    * if the field does not exist
147    *
148    * @see PrivilegedAccessor#getValue(Object,String)
149    */
 
150  174 toggle public static Object getValue(final Object instanceOrClass,
151    final String fieldName)
152    {
153  174 try
154    {
155  174 return PrivilegedAccessor.getValue(instanceOrClass, fieldName);
156    } catch (Exception e)
157    {
158  0 throw new IllegalArgumentException("Can't get value of " + fieldName
159    + " from " + instanceOrClass, e);
160    }
161    }
162   
163    /**
164    * Gets the value of the named field and returns it as an object.
165    *
166    * @param fieldName
167    * the name of the field
168    * @return an object representing the value of the field
169    * @throws IllegalArgumentException
170    * if the field does not exist
171    *
172    * @see PA#getValue(Object,String)
173    */
 
174  0 toggle public Object getValue(final String fieldName)
175    {
176  0 return PA.getValue(instanceOrClass, fieldName);
177    }
178   
179    /**
180    * Instantiates an object of the given class with the given arguments and the
181    * given argument types. If you want to instantiate a member class, you must
182    * provide the object it is a member of as first argument.
183    *
184    * @param fromClass
185    * the class to instantiate an object from
186    * @param arguments
187    * the arguments to pass to the constructor
188    * @param argumentTypes
189    * the fully qualified types of the arguments of the constructor
190    * @return an object of the given type
191    * @throws IllegalArgumentException
192    * if the class can't be instantiated. This could be the case if the
193    * number of actual and formal parameters differ; if an unwrapping
194    * conversion for primitive arguments fails; if, after possible
195    * unwrapping, a parameter value cannot be converted to the
196    * corresponding formal parameter type by a method invocation
197    * conversion; if this Constructor object enforces Java language
198    * access control and the underlying constructor is inaccessible; if
199    * the underlying constructor throws an exception; if the
200    * constructor could not be found; or if the class that declares the
201    * underlying constructor represents an abstract class.
202    *
203    * @see PrivilegedAccessor#instantiate(Class,Class[],Object[])
204    */
 
205  0 toggle public static <T> T instantiate(final Class<? extends T> fromClass,
206    final Class<?>[] argumentTypes, final Object... arguments)
207    {
208  0 try
209    {
210  0 return PrivilegedAccessor.instantiate(fromClass, argumentTypes,
211    correctVarargs(arguments));
212    } catch (Exception e)
213    {
214  0 throw new IllegalArgumentException("Can't instantiate class "
215    + fromClass + " with arguments " + arguments, e);
216    }
217    }
218   
219    /**
220    * Instantiates an object of the given class with the given arguments. If you
221    * want to instantiate a member class, you must provide the object it is a
222    * member of as first argument.
223    *
224    * @param fromClass
225    * the class to instantiate an object from
226    * @param arguments
227    * the arguments to pass to the constructor
228    * @return an object of the given type
229    * @throws IllegalArgumentException
230    * if the class can't be instantiated. This could be the case if the
231    * number of actual and formal parameters differ; if an unwrapping
232    * conversion for primitive arguments fails; or if, after possible
233    * unwrapping, a parameter value cannot be converted to the
234    * corresponding formal parameter type by a method invocation
235    * conversion; if this Constructor object enforces Java language
236    * access control and the underlying constructor is inaccessible; if
237    * the underlying constructor throws an exception; if the
238    * constructor could not be found; or if the class that declares the
239    * underlying constructor represents an abstract class.
240    *
241    * @see PrivilegedAccessor#instantiate(Class,Object[])
242    */
 
243  0 toggle public static <T> T instantiate(final Class<? extends T> fromClass,
244    final Object... arguments)
245    {
246  0 try
247    {
248  0 return PrivilegedAccessor.instantiate(fromClass,
249    correctVarargs(arguments));
250    } catch (Exception e)
251    {
252  0 throw new IllegalArgumentException("Can't instantiate class "
253    + fromClass + " with arguments " + arguments, e);
254    }
255    }
256   
257    /**
258    * Calls a method on the given object instance with the given arguments.
259    * Arguments can be object types or representations for primitives.
260    *
261    * @param instanceOrClass
262    * the instance or class to invoke the method on
263    * @param methodSignature
264    * the name of the method and the parameters <br>
265    * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
266    * @param arguments
267    * an array of objects to pass as arguments
268    * @return the return value of this method or null if void
269    * @throws IllegalArgumentException
270    * if the method could not be invoked. This could be the case if the
271    * method is inaccessible; if the underlying method throws an
272    * exception; if no method with the given
273    * <code>methodSignature</code> could be found; or if an argument
274    * couldn't be converted to match the expected type
275    *
276    * @see PrivilegedAccessor#invokeMethod(Object,String,Object[])
277    */
 
278  0 toggle public static Object invokeMethod(final Object instanceOrClass,
279    final String methodSignature, final Object... arguments)
280    {
281  0 try
282    {
283  0 return PrivilegedAccessor.invokeMethod(instanceOrClass,
284    methodSignature, correctVarargs(arguments));
285    } catch (Exception e)
286    {
287  0 throw new IllegalArgumentException(
288    "Can't invoke method " + methodSignature + " on "
289    + instanceOrClass + " with arguments " + arguments,
290    e);
291    }
292    }
293   
294    /**
295    * Calls a method with the given arguments. Arguments can be object types or
296    * representations for primitives.
297    *
298    * @param methodSignature
299    * the name of the method and the parameters <br>
300    * (e.g. "myMethod(java.lang.String, com.company.project.MyObject)")
301    * @param arguments
302    * an array of objects to pass as arguments
303    * @return the return value of this method or null if void
304    * @throws IllegalArgumentException
305    * if the method could not be invoked. This could be the case if the
306    * method is inaccessible; if the underlying method throws an
307    * exception; if no method with the given
308    * <code>methodSignature</code> could be found; or if an argument
309    * couldn't be converted to match the expected type
310    * @see PA#invokeMethod(Object, String, Object...)
311    */
 
312  0 toggle public Object invokeMethod(final String methodSignature,
313    final Object... arguments)
314    {
315  0 return PA.invokeMethod(instanceOrClass, methodSignature, arguments);
316    }
317   
318    /**
319    * Corrects varargs to their initial form. If you call a method with an
320    * object-array as last argument the Java varargs mechanism converts this
321    * array in single arguments. This method returns an object array if the
322    * arguments are all of the same type.
323    *
324    * @param arguments
325    * the possibly converted arguments of a vararg method
326    * @return arguments possibly converted
327    */
 
328  0 toggle private static Object[] correctVarargs(final Object... arguments)
329    {
330  0 if ((arguments == null) || changedByVararg(arguments))
331  0 return new Object[] { arguments };
332  0 return arguments;
333    }
334   
335    /**
336    * Tests if the arguments were changed by vararg. Arguments are changed by
337    * vararg if they are of a non primitive array type. E.g. arguments[] =
338    * Object[String[]] is converted to String[] while e.g. arguments[] =
339    * Object[int[]] is not converted and stays Object[int[]]
340    *
341    * Unfortunately we can't detect the difference for arg = Object[primitive]
342    * since arguments[] = Object[Object[primitive]] which is converted to
343    * Object[primitive] and arguments[] = Object[primitive] which stays
344    * Object[primitive]
345    *
346    * and we can't detect the difference for arg = Object[non primitive] since
347    * arguments[] = Object[Object[non primitive]] is converted to Object[non
348    * primitive] and arguments[] = Object[non primitive] stays Object[non
349    * primitive]
350    *
351    * @param parameters
352    * the parameters
353    * @return true if parameters were changes by varargs, false otherwise
354    */
 
355  0 toggle private static boolean changedByVararg(final Object[] parameters)
356    {
357  0 if ((parameters.length == 0) || (parameters[0] == null))
358  0 return false;
359   
360  0 if (parameters.getClass() == Object[].class)
361  0 return false;
362   
363  0 return true;
364    }
365   
366    /**
367    * Sets the value of the named field. If fieldName denotes a static field,
368    * provide a class, otherwise provide an instance. If the fieldName denotes a
369    * final field, this method could fail with an IllegalAccessException, since
370    * setting the value of final fields at other times than instantiation can
371    * have unpredictable effects.<br/>
372    * <br/>
373    * Example:<br/>
374    * <br/>
375    * <code>
376    * String myString = "Test"; <br/>
377    * <br/>
378    * //setting the private field value<br/>
379    * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
380    * <br/>
381    * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
382    * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
383    * <br/>
384    * </code>
385    *
386    * @param instanceOrClass
387    * the instance or class to set the field
388    * @param fieldName
389    * the name of the field
390    * @param value
391    * the new value of the field
392    * @throws IllegalArgumentException
393    * if the value could not be set. This could be the case if no field
394    * with the given <code>fieldName</code> can be found; or if the
395    * field was final
396    *
397    * @see PrivilegedAccessor.setValue(Object,String,Object)
398    */
 
399  18 toggle public static PA setValue(final Object instanceOrClass,
400    final String fieldName, final Object value)
401    {
402  18 try
403    {
404  18 PrivilegedAccessor.setValue(instanceOrClass, fieldName, value);
405    } catch (Exception e)
406    {
407  0 throw new IllegalArgumentException("Can't set value " + value + " at "
408    + fieldName + " in " + instanceOrClass, e);
409    }
410  18 return new PA(instanceOrClass);
411    }
412   
413    /**
414    * Sets the value of the named field. If fieldName denotes a static field,
415    * provide a class, otherwise provide an instance. If the fieldName denotes a
416    * final field, this method could fail with an IllegalAccessException, since
417    * setting the value of final fields at other times than instantiation can
418    * have unpredictable effects.<br/>
419    * <br/>
420    * Example:<br/>
421    * <br/>
422    * <code>
423    * String myString = "Test"; <br/>
424    * <br/>
425    * //setting the private field value<br/>
426    * PrivilegedAccessor.setValue(myString, "value", new char[] {'T', 'e', 's', 't'});<br/>
427    * <br/>
428    * //setting the static final field serialVersionUID - MIGHT FAIL<br/>
429    * PrivilegedAccessor.setValue(myString.getClass(), "serialVersionUID", 1);<br/>
430    * <br/>
431    * </code>
432    *
433    * @param fieldName
434    * the name of the field
435    * @param value
436    * the new value of the field
437    * @throws IllegalArgumentException
438    * if the value could not be set. This could be the case if no field
439    * with the given <code>fieldName</code> can be found; or if the
440    * field was final
441    *
442    * @see PA.setValue(Object,String,Object)
443    */
 
444  0 toggle public PA setValue(final String fieldName, final Object value)
445    {
446  0 PA.setValue(instanceOrClass, fieldName, value);
447  0 return this;
448    }
449    }