1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dbforms.util;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import java.io.BufferedWriter;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.io.PrintWriter;
33 import java.io.StringWriter;
34 import java.io.Writer;
35
36 import java.lang.reflect.Constructor;
37 import java.lang.reflect.Field;
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Modifier;
40
41
42
43 /***
44 * ReflectionUtil class
45 *
46 * @author Luca Fossato
47 * @created 20 novembre 2002
48 */
49 public class ReflectionUtil {
50 /*** log4j category */
51 private static Log logCat = LogFactory.getLog(ReflectionUtil.class);
52
53 /***
54 * Invokes the underlying method represented by this Method object, on the
55 * specified object with the specified parameters. <br>
56 * Individual parameters are automatically unwrapped to match primitive
57 * formal parameters, and both primitive and reference parameters are
58 * subject to widening conversions as necessary. <br>
59 * The value returned by the underlying method is automatically wrapped in
60 * an object if it has a primitive type.
61 *
62 * @param className the object class name
63 * @param methodName the arguments classes for the object method
64 * @param argsTypes the arguments values for the object constructor
65 * @param args DOCUMENT ME!
66 *
67 * @return If the method completes normally, the value it returns is
68 * returned to the caller of invoke; if the value has a primitive
69 * type, it is first appropriately wrapped in an object. If the
70 * underlying method return type is void, the invocation returns
71 * null.
72 *
73 * @exception Exception if any error occurs
74 */
75 public static Object invoke(String className,
76 String methodName,
77 Class[] argsTypes,
78 Object[] args) throws Exception {
79 Class c = Class.forName(className);
80 Method m = c.getDeclaredMethod(methodName, argsTypes);
81 Object i = c.newInstance();
82 Object r = m.invoke(i, args);
83
84 return r;
85 }
86
87
88 /***
89 * Return the object having the input class name
90 * @param className the object class name
91 *
92 * @return the instanced object
93 *
94 * @exception Exception if any error occurs
95 */
96 public static Object newInstance(String className) throws Exception {
97 Class myClass = Class.forName(className);
98 return myClass.newInstance();
99 }
100
101
102 /***
103 * Return the object having the input class name, instanced with the
104 * constructor having the <code>constructorArgsTypes</code> arguments.
105 *
106 * @param className the object class name
107 * @param constructorArgsTypes the object constructor arguments classes
108 * @param constructorArgs the object constructor arguments values
109 *
110 * @return the instanced object
111 *
112 * @exception Exception if any error occurs
113 */
114 public static Object newInstance(String className,
115 Class[] constructorArgsTypes,
116 Object[] constructorArgs)
117 throws Exception {
118 Class myClass = Class.forName(className);
119
120 return newInstance(myClass, constructorArgsTypes, constructorArgs);
121 }
122
123
124 /***
125 * Return the object having the input class name, instanced with the
126 * constructor having the <code>constructorArgsTypes</code> arguments.
127 *
128 * @param clazz the object class name
129 * @param constructorArgsTypes the object constructor arguments classes
130 * @param constructorArgs the object constructor arguments values
131 *
132 * @return the instanced object
133 *
134 * @exception Exception if any error occurs
135 */
136 public static Object newInstance(Class clazz,
137 Class[] constructorArgsTypes,
138 Object[] constructorArgs)
139 throws Exception {
140 Constructor myConstructor = clazz.getConstructor(constructorArgsTypes);
141
142 return myConstructor.newInstance(constructorArgs);
143 }
144
145
146 /***
147 * Reflect the input class state.
148 *
149 * @param name Description of the Parameter
150 * @param os Description of the Parameter
151 */
152 public static void reflectClass(String name,
153 OutputStream os) {
154 Writer w = new BufferedWriter(new OutputStreamWriter(os));
155 reflectClass(name, w);
156 }
157
158
159 /***
160 * Reflect the input class state.
161 *
162 * @param name Description of the Parameter
163 * @param w Description of the Parameter
164 */
165 public static void reflectClass(String name,
166 Writer w) {
167 Class c = null;
168
169 try {
170 c = Class.forName(name);
171 reflectClass(c.newInstance(), false, w);
172 } catch (Exception e) {
173 logCat.error("Class " + name + " is not found.");
174
175 return;
176 }
177 }
178
179
180 /***
181 * Reflect the input object state.
182 *
183 * @param o Description of the Parameter
184 * @param os Description of the Parameter
185 */
186 public static void reflectObject(Object o,
187 OutputStream os) {
188 Writer w = new BufferedWriter(new OutputStreamWriter(os));
189 reflectClass(o, true, w);
190 }
191
192
193 /***
194 * Reflect the input object state.
195 *
196 * @param o Description of the Parameter
197 * @param w Description of the Parameter
198 */
199 public static void reflectObject(Object o,
200 Writer w) {
201 reflectClass(o, true, w);
202 }
203
204
205 /***
206 * Get the String representation of the input object
207 *
208 * @param o the object to introspect
209 *
210 * @return the String representation of the input object
211 */
212 public static String toString(Object o) {
213 StringWriter sw = new StringWriter();
214 BufferedWriter bw = new BufferedWriter(new PrintWriter(sw));
215 String s = null;
216
217 reflectObject(o, bw);
218 s = sw.getBuffer()
219 .toString();
220
221 try {
222 sw.close();
223 } catch (Exception e) {
224 logCat.error("::toString - cannot close the writer object", e);
225 }
226
227 return s;
228 }
229
230
231 /***
232 * Get the String representation of the class having the input full
233 * qualified name.
234 *
235 * @param c the full qualified name of the class to introspect
236 *
237 * @return the String representation of the input object
238 */
239 public static String toString(String c) {
240 StringWriter sw = new StringWriter();
241 BufferedWriter bw = new BufferedWriter(new PrintWriter(sw));
242 String s = null;
243
244 reflectClass(c, bw);
245 s = sw.getBuffer()
246 .toString();
247
248 try {
249 sw.close();
250 } catch (Exception e) {
251 logCat.error("::toString - cannot close the writer object", e);
252 }
253
254 return s;
255 }
256
257
258 /***
259 * Gets the typeName attribute of the input class
260 *
261 * @param c Description of the Parameter
262 *
263 * @return The typeName value
264 */
265 private static String getTypeName(Class c) {
266 if (c.isArray()) {
267 try {
268 Class cl = c;
269 int dimensions = 0;
270
271 while (cl.isArray()) {
272 dimensions++;
273 cl = cl.getComponentType();
274 }
275
276 StringBuffer sb = new StringBuffer();
277
278 sb.append(cl.getName());
279
280 for (int i = 0; i < dimensions; i++)
281 sb.append("[]");
282
283 return sb.toString();
284 } catch (Throwable e) {
285 logCat.error("::getTypeName - cannot get the class type", e);
286 }
287 }
288
289 return c.getName();
290 }
291
292
293 /***
294 * Get the class constructors.
295 *
296 * @param pw Description of the Parameter
297 * @param c Description of the Parameter
298 */
299 private static void listClassConstructors(PrintWriter pw,
300 Class c) {
301 Constructor[] constructors = c.getDeclaredConstructors();
302
303 for (int i = 0; i < constructors.length; i++) {
304 if (i == 0) {
305 pw.println(" // Constructors");
306 }
307
308 pw.print(" " + Modifier.toString(constructors[i].getModifiers())
309 + " " + constructors[i].getName() + "(");
310
311 listParameters(pw, constructors[i].getParameterTypes());
312 pw.println(");");
313 }
314
315 if (constructors.length > 0) {
316 pw.println();
317 }
318 }
319
320
321 /***
322 * Get the class methods
323 *
324 * @param pw Description of the Parameter
325 * @param c Description of the Parameter
326 */
327 private static void listClassMethods(PrintWriter pw,
328 Class c) {
329 Method[] methods = c.getDeclaredMethods();
330
331 for (int i = 0; i < methods.length; i++) {
332 if (i == 0) {
333 pw.println(" // Methods");
334 }
335
336 pw.print(" " + Modifier.toString(methods[i].getModifiers()) + " "
337 + getTypeName(methods[i].getReturnType()) + " "
338 + methods[i].getName() + "(");
339
340 listParameters(pw, methods[i].getParameterTypes());
341 pw.println(");");
342 }
343 }
344
345
346 /***
347 * Get the class variables
348 *
349 * @param pw Description of the Parameter
350 * @param o Description of the Parameter
351 * @param dumpValues Description of the Parameter
352 *
353 * @throws Exception DOCUMENT ME!
354 */
355 private static void listClassVariables(PrintWriter pw,
356 Object o,
357 boolean dumpValues)
358 throws Exception {
359 if (o != null) {
360 Class c = o.getClass();
361 Field[] fields = c.getDeclaredFields();
362
363 for (int i = 0; i < fields.length; i++) {
364 if (i == 0) {
365 pw.println(" // Variables");
366 }
367
368
369 pw.print(" " + Modifier.toString(fields[i].getModifiers()) + " "
370 + getTypeName(fields[i].getType()) + " "
371 + fields[i].getName());
372
373
374 if (dumpValues) {
375 Field f = fields[i];
376 String fValue = null;
377
378 if (f.isAccessible()) {
379 fValue = f.get(o)
380 .toString();
381 } else {
382 try {
383 f.setAccessible(true);
384 fValue = f.get(o)
385 .toString();
386 f.setAccessible(false);
387 } catch (Exception e) {
388 fValue = "NOT ACCESSIBLE";
389 }
390 }
391
392 pw.print(" = [ " + fValue + " ]");
393 }
394
395 pw.println(";");
396 }
397
398 if (fields.length > 0) {
399 pw.println();
400 }
401 }
402 }
403
404
405 /***
406 * Get the type of the class parameters
407 *
408 * @param pw Description of the Parameter
409 * @param parameters Description of the Parameter
410 */
411 private static void listParameters(PrintWriter pw,
412 Class[] parameters) {
413 for (int j = 0; j < parameters.length; j++) {
414 pw.print(getTypeName(parameters[j]));
415
416 if (j < (parameters.length - 1)) {
417 pw.print(", ");
418 }
419 }
420 }
421
422
423 /***
424 * PRIVATE methods here
425 *
426 * @param o DOCUMENT ME!
427 * @param dumpValues DOCUMENT ME!
428 * @param w DOCUMENT ME!
429 */
430 /***
431 * Reflect the input class state.
432 *
433 * @param o Description of the Parameter
434 * @param dumpValues DOCUMENT ME!
435 * @param w Description of the Parameter
436 */
437 private static void reflectClass(Object o,
438 boolean dumpValues,
439 Writer w) {
440 PrintWriter pw = new PrintWriter(w);
441 Class c = o.getClass();
442
443
444 pw.println(Modifier.toString(c.getModifiers()) + " " + c.getName());
445
446
447 if (c.getSuperclass() != null) {
448 pw.print(" extends " + c.getSuperclass().getName());
449 }
450
451
452 Class[] interfaces = c.getInterfaces();
453
454 for (int i = 0; i < interfaces.length; i++) {
455 if (i == 0) {
456 pw.print(" implements ");
457 } else {
458 pw.print(", ");
459 }
460
461 pw.print(interfaces[i].getName());
462 }
463
464 pw.println("\n{");
465
466 try {
467 listClassVariables(pw, o, dumpValues);
468 } catch (Exception e) {
469 logCat.error("::reflectClass - cannot list the class variables", e);
470 }
471
472 listClassConstructors(pw, c);
473 listClassMethods(pw, c);
474
475 pw.println("\n}");
476 pw.flush();
477 }
478 }