Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2013 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.jdt.core.tests.util; |
12 |
|
13 |
import java.lang.reflect.Constructor; |
14 |
import java.lang.reflect.Field; |
15 |
import java.lang.reflect.InvocationTargetException; |
16 |
import java.lang.reflect.Method; |
17 |
import java.lang.reflect.Modifier; |
18 |
|
19 |
import org.eclipse.core.runtime.Assert; |
20 |
|
21 |
|
22 |
/** |
23 |
* Helper class for accessing classes and members which cannot be accessed using standard Java |
24 |
* access control like private or package visible elements. |
25 |
* <p> |
26 |
* <strong>Note:</strong> Copied from org.eclipse.text.tests. |
27 |
* </p> |
28 |
* |
29 |
* @since 3.5 |
30 |
*/ |
31 |
public class Accessor { |
32 |
|
33 |
/** The class to access. */ |
34 |
private Class fClass; |
35 |
/** The instance to access. */ |
36 |
private Object fInstance; |
37 |
|
38 |
/** |
39 |
* Creates an accessor for the given <code>instance</code> and |
40 |
* <code>class</code>. Only non-inherited members that particular |
41 |
* <code>class</code> can be accessed. |
42 |
* |
43 |
* @param instance the instance |
44 |
* @param clazz the class |
45 |
*/ |
46 |
public Accessor(Object instance, Class clazz) { |
47 |
org.eclipse.core.runtime.Assert.isNotNull(instance); |
48 |
Assert.isNotNull(clazz); |
49 |
fInstance= instance; |
50 |
fClass= clazz; |
51 |
} |
52 |
|
53 |
/** |
54 |
* Creates an accessor for the given <code>instance</code> and |
55 |
* <code>class</code>. Only non-inherited members that particular |
56 |
* <code>class</code> can be accessed. |
57 |
* |
58 |
* @param instance the instance |
59 |
* @param className the name of the class |
60 |
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code> |
61 |
*/ |
62 |
public Accessor(Object instance, String className, ClassLoader classLoader) { |
63 |
Assert.isNotNull(instance); |
64 |
Assert.isNotNull(className); |
65 |
Assert.isNotNull(classLoader); |
66 |
fInstance= instance; |
67 |
try { |
68 |
fClass= Class.forName(className, true, classLoader); |
69 |
} catch (ClassNotFoundException e) { |
70 |
fail(); |
71 |
} catch (ExceptionInInitializerError e) { |
72 |
fail(); |
73 |
} |
74 |
} |
75 |
|
76 |
/** |
77 |
* Creates an accessor for the given class. |
78 |
* <p> |
79 |
* In order to get the type information from the given |
80 |
* arguments they must all be instanceof Object. Use |
81 |
* {@link #Accessor(String, ClassLoader, Class[], Object[])} if this |
82 |
* is not the case.</p> |
83 |
* |
84 |
* @param className the name of the class |
85 |
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code> |
86 |
* @param constructorArgs the constructor arguments which must all be instance of Object |
87 |
*/ |
88 |
public Accessor(String className, ClassLoader classLoader, Object[] constructorArgs) { |
89 |
this(className, classLoader, getTypes(constructorArgs), constructorArgs); |
90 |
} |
91 |
|
92 |
/** |
93 |
* Creates an accessor for the given class. |
94 |
* |
95 |
* @param className the name of the class |
96 |
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code> |
97 |
* @param constructorTypes the types of the constructor arguments |
98 |
* @param constructorArgs the constructor arguments |
99 |
*/ |
100 |
public Accessor(String className, ClassLoader classLoader, Class[] constructorTypes, Object[] constructorArgs) { |
101 |
try { |
102 |
fClass= Class.forName(className, true, classLoader); |
103 |
} catch (ClassNotFoundException e) { |
104 |
fail(); |
105 |
} catch (ExceptionInInitializerError e) { |
106 |
fail(); |
107 |
} |
108 |
Constructor constructor= null; |
109 |
try { |
110 |
constructor= fClass.getDeclaredConstructor(constructorTypes); |
111 |
} catch (SecurityException e2) { |
112 |
fail(); |
113 |
} catch (NoSuchMethodException e2) { |
114 |
fail(); |
115 |
} |
116 |
Assert.isNotNull(constructor); |
117 |
constructor.setAccessible(true); |
118 |
try { |
119 |
fInstance= constructor.newInstance(constructorArgs); |
120 |
} catch (IllegalArgumentException e) { |
121 |
fail(); |
122 |
} catch (InvocationTargetException e) { |
123 |
fail(); |
124 |
} catch (InstantiationException e) { |
125 |
fail(); |
126 |
} catch (IllegalAccessException e) { |
127 |
fail(); |
128 |
} |
129 |
} |
130 |
|
131 |
/** |
132 |
* Creates an accessor for the given class. |
133 |
* <p> |
134 |
* This constructor is used to access static stuff. |
135 |
* </p> |
136 |
* |
137 |
* @param className the name of the class |
138 |
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code> |
139 |
*/ |
140 |
public Accessor(String className, ClassLoader classLoader) { |
141 |
try { |
142 |
fClass= Class.forName(className, true, classLoader); |
143 |
} catch (ClassNotFoundException e) { |
144 |
fail(); |
145 |
} catch (ExceptionInInitializerError e) { |
146 |
fail(); |
147 |
} |
148 |
} |
149 |
|
150 |
/** |
151 |
* Invokes the method with the given method name and arguments. |
152 |
* <p> |
153 |
* In order to get the type information from the given |
154 |
* arguments all those arguments must be instance of Object. Use |
155 |
* {@link #invoke(String, Class[], Object[])} if this |
156 |
* is not the case.</p> |
157 |
* |
158 |
* @param methodName the method name |
159 |
* @param arguments the method arguments which must all be instance of Object |
160 |
* @return the method return value |
161 |
*/ |
162 |
public Object invoke(String methodName, Object[] arguments) { |
163 |
return invoke(methodName, getTypes(arguments), arguments); |
164 |
} |
165 |
|
166 |
/** |
167 |
* Invokes the method with the given method name and arguments. |
168 |
* |
169 |
* @param methodName the method name |
170 |
* @param types the argument types |
171 |
* @param arguments the method arguments |
172 |
* @return the method return value |
173 |
*/ |
174 |
public Object invoke(String methodName, Class[] types, Object[] arguments) { |
175 |
Method method= null; |
176 |
try { |
177 |
method= fClass.getDeclaredMethod(methodName, types); |
178 |
} catch (SecurityException e) { |
179 |
fail(); |
180 |
} catch (NoSuchMethodException ex) { |
181 |
fail(); |
182 |
} |
183 |
Assert.isNotNull(method); |
184 |
method.setAccessible(true); |
185 |
try { |
186 |
return method.invoke(fInstance, arguments); |
187 |
} catch (IllegalArgumentException e) { |
188 |
fail(); |
189 |
} catch (InvocationTargetException e) { |
190 |
fail(); |
191 |
} catch (IllegalAccessException e) { |
192 |
fail(); |
193 |
} |
194 |
return null; |
195 |
} |
196 |
|
197 |
/** |
198 |
* Assigns the given value to the field with the given name. |
199 |
* |
200 |
* @param fieldName the field name |
201 |
* @param value the value to assign to the field |
202 |
*/ |
203 |
public void set(String fieldName, Object value) { |
204 |
Field field= getField(fieldName); |
205 |
try { |
206 |
field.set(fInstance, value); |
207 |
} catch (IllegalArgumentException e) { |
208 |
fail(); |
209 |
} catch (IllegalAccessException e) { |
210 |
fail(); |
211 |
} |
212 |
} |
213 |
|
214 |
public void setFinal(String fieldName, boolean value) { |
215 |
|
216 |
Field field= getField(fieldName); |
217 |
Field modifiersField = getFieldModifiers(); |
218 |
boolean isFinal = false; |
219 |
try { |
220 |
// ensure the field is not final so that it can be modified |
221 |
modifiersField.setAccessible(true); |
222 |
isFinal = (field.getModifiers() & Modifier.FINAL) == Modifier.FINAL; |
223 |
if(isFinal) { |
224 |
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); |
225 |
} |
226 |
field.setBoolean(fInstance, value); |
227 |
} catch (IllegalArgumentException e) { |
228 |
fail(); |
229 |
} catch (IllegalAccessException e) { |
230 |
fail(); |
231 |
} catch (SecurityException e) { |
232 |
fail(); |
233 |
} |
234 |
finally { |
235 |
// re-apply the final modifier |
236 |
if(isFinal) { |
237 |
try { |
238 |
modifiersField.setInt(field, field.getModifiers() | Modifier.FINAL); |
239 |
} catch (IllegalArgumentException e) { |
240 |
fail(); |
241 |
} catch (IllegalAccessException e) { |
242 |
fail(); |
243 |
} |
244 |
} |
245 |
} |
246 |
} |
247 |
|
248 |
/** |
249 |
* Assigns the given value to the field with the given name. |
250 |
* |
251 |
* @param fieldName the field name |
252 |
* @param value the value to assign to the field |
253 |
*/ |
254 |
public void set(String fieldName, boolean value) { |
255 |
Field field= getField(fieldName); |
256 |
try { |
257 |
field.setBoolean(fInstance, value); |
258 |
} catch (IllegalArgumentException e) { |
259 |
fail(); |
260 |
} catch (IllegalAccessException e) { |
261 |
fail(); |
262 |
} |
263 |
} |
264 |
|
265 |
/** |
266 |
* Assigns the given value to the field with the given name. |
267 |
* |
268 |
* @param fieldName the field name |
269 |
* @param value the value to assign to the field |
270 |
*/ |
271 |
public void set(String fieldName, int value) { |
272 |
Field field= getField(fieldName); |
273 |
try { |
274 |
field.setInt(fInstance, value); |
275 |
} catch (IllegalArgumentException e) { |
276 |
fail(); |
277 |
} catch (IllegalAccessException e) { |
278 |
fail(); |
279 |
} |
280 |
} |
281 |
|
282 |
/** |
283 |
* Returns the value of the field with the given name. |
284 |
* |
285 |
* @param fieldName the field name |
286 |
* @return the value of the field |
287 |
*/ |
288 |
public Object get(String fieldName) { |
289 |
Field field= getField(fieldName); |
290 |
try { |
291 |
return field.get(fInstance); |
292 |
} catch (IllegalArgumentException e) { |
293 |
fail(); |
294 |
} catch (IllegalAccessException e) { |
295 |
fail(); |
296 |
} |
297 |
// Unreachable code |
298 |
return null; |
299 |
} |
300 |
|
301 |
/** |
302 |
* Returns the value of the field with the given name. |
303 |
* |
304 |
* @param fieldName the field name |
305 |
* @return the value of the field |
306 |
*/ |
307 |
public boolean getBoolean(String fieldName) { |
308 |
Field field= getField(fieldName); |
309 |
try { |
310 |
return field.getBoolean(fInstance); |
311 |
} catch (IllegalArgumentException e) { |
312 |
fail(); |
313 |
} catch (IllegalAccessException e) { |
314 |
fail(); |
315 |
} |
316 |
// Unreachable code |
317 |
return false; |
318 |
} |
319 |
|
320 |
/** |
321 |
* Returns the value of the field with the given name. |
322 |
* |
323 |
* @param fieldName the field name |
324 |
* @return the value of the field |
325 |
*/ |
326 |
public int getInt(String fieldName) { |
327 |
Field field= getField(fieldName); |
328 |
try { |
329 |
return field.getInt(fInstance); |
330 |
} catch (IllegalArgumentException e) { |
331 |
fail(); |
332 |
} catch (IllegalAccessException e) { |
333 |
fail(); |
334 |
} |
335 |
// Unreachable code |
336 |
return 0; |
337 |
} |
338 |
|
339 |
private Field getFieldModifiers() { |
340 |
Field field= null; |
341 |
try { |
342 |
field= Field.class.getDeclaredField("modifiers"); |
343 |
} catch (SecurityException e) { |
344 |
fail(); |
345 |
} catch (NoSuchFieldException e) { |
346 |
fail(); |
347 |
} |
348 |
return field; |
349 |
} |
350 |
|
351 |
private Field getField(String fieldName) { |
352 |
Field field= null; |
353 |
try { |
354 |
field= fClass.getDeclaredField(fieldName); |
355 |
} catch (SecurityException e) { |
356 |
fail(); |
357 |
} catch (NoSuchFieldException e) { |
358 |
fail(); |
359 |
} |
360 |
field.setAccessible(true); |
361 |
return field; |
362 |
} |
363 |
|
364 |
private static Class[] getTypes(Object[] objects) { |
365 |
if (objects == null) |
366 |
return null; |
367 |
|
368 |
int length= objects.length; |
369 |
Class[] classes= new Class[length]; |
370 |
for (int i= 0; i < length; i++) { |
371 |
Assert.isNotNull(objects[i]); |
372 |
classes[i]= objects[i].getClass(); |
373 |
} |
374 |
return classes; |
375 |
} |
376 |
|
377 |
private void fail() { |
378 |
Assert.isTrue(false); |
379 |
} |
380 |
} |