1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.util;
20
21 import javax.el.ExpressionFactory;
22 import javax.faces.FacesException;
23 import javax.faces.context.FacesContext;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.lang.reflect.Array;
27 import java.lang.reflect.Constructor;
28 import java.lang.reflect.InvocationTargetException;
29 import java.net.URL;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41
42
43
44
45
46
47 public final class ClassUtils
48 {
49
50
51
52 private static final Logger log = Logger.getLogger(ClassUtils.class.getName());
53
54 public static final Class BOOLEAN_ARRAY_CLASS = boolean[].class;
55 public static final Class BYTE_ARRAY_CLASS = byte[].class;
56 public static final Class CHAR_ARRAY_CLASS = char[].class;
57 public static final Class SHORT_ARRAY_CLASS = short[].class;
58 public static final Class INT_ARRAY_CLASS = int[].class;
59 public static final Class LONG_ARRAY_CLASS = long[].class;
60 public static final Class FLOAT_ARRAY_CLASS = float[].class;
61 public static final Class DOUBLE_ARRAY_CLASS = double[].class;
62 public static final Class OBJECT_ARRAY_CLASS = Object[].class;
63 public static final Class BOOLEAN_OBJECT_ARRAY_CLASS = Boolean[].class;
64 public static final Class BYTE_OBJECT_ARRAY_CLASS = Byte[].class;
65 public static final Class CHARACTER_OBJECT_ARRAY_CLASS = Character[].class;
66 public static final Class SHORT_OBJECT_ARRAY_CLASS = Short[].class;
67 public static final Class INTEGER_OBJECT_ARRAY_CLASS = Integer[].class;
68 public static final Class LONG_OBJECT_ARRAY_CLASS = Long[].class;
69 public static final Class FLOAT_OBJECT_ARRAY_CLASS = Float[].class;
70 public static final Class DOUBLE_OBJECT_ARRAY_CLASS = Double[].class;
71 public static final Class STRING_OBJECT_ARRAY_CLASS = String[].class;
72
73 public static ClassLoaderExtension [] classLoadingExtensions = new ClassLoaderExtension[0];
74
75
76
77 public static final Map COMMON_TYPES = new HashMap(64);
78 static
79 {
80 COMMON_TYPES.put("byte", Byte.TYPE);
81 COMMON_TYPES.put("char", Character.TYPE);
82 COMMON_TYPES.put("double", Double.TYPE);
83 COMMON_TYPES.put("float", Float.TYPE);
84 COMMON_TYPES.put("int", Integer.TYPE);
85 COMMON_TYPES.put("long", Long.TYPE);
86 COMMON_TYPES.put("short", Short.TYPE);
87 COMMON_TYPES.put("boolean", Boolean.TYPE);
88 COMMON_TYPES.put("void", Void.TYPE);
89 COMMON_TYPES.put("java.lang.Object", Object.class);
90 COMMON_TYPES.put("java.lang.Boolean", Boolean.class);
91 COMMON_TYPES.put("java.lang.Byte", Byte.class);
92 COMMON_TYPES.put("java.lang.Character", Character.class);
93 COMMON_TYPES.put("java.lang.Short", Short.class);
94 COMMON_TYPES.put("java.lang.Integer", Integer.class);
95 COMMON_TYPES.put("java.lang.Long", Long.class);
96 COMMON_TYPES.put("java.lang.Float", Float.class);
97 COMMON_TYPES.put("java.lang.Double", Double.class);
98 COMMON_TYPES.put("java.lang.String", String.class);
99
100 COMMON_TYPES.put("byte[]", BYTE_ARRAY_CLASS);
101 COMMON_TYPES.put("char[]", CHAR_ARRAY_CLASS);
102 COMMON_TYPES.put("double[]", DOUBLE_ARRAY_CLASS);
103 COMMON_TYPES.put("float[]", FLOAT_ARRAY_CLASS);
104 COMMON_TYPES.put("int[]", INT_ARRAY_CLASS);
105 COMMON_TYPES.put("long[]", LONG_ARRAY_CLASS);
106 COMMON_TYPES.put("short[]", SHORT_ARRAY_CLASS);
107 COMMON_TYPES.put("boolean[]", BOOLEAN_ARRAY_CLASS);
108 COMMON_TYPES.put("java.lang.Object[]", OBJECT_ARRAY_CLASS);
109 COMMON_TYPES.put("java.lang.Boolean[]", BOOLEAN_OBJECT_ARRAY_CLASS);
110 COMMON_TYPES.put("java.lang.Byte[]", BYTE_OBJECT_ARRAY_CLASS);
111 COMMON_TYPES.put("java.lang.Character[]", CHARACTER_OBJECT_ARRAY_CLASS);
112 COMMON_TYPES.put("java.lang.Short[]", SHORT_OBJECT_ARRAY_CLASS);
113 COMMON_TYPES.put("java.lang.Integer[]", INTEGER_OBJECT_ARRAY_CLASS);
114 COMMON_TYPES.put("java.lang.Long[]", LONG_OBJECT_ARRAY_CLASS);
115 COMMON_TYPES.put("java.lang.Float[]", FLOAT_OBJECT_ARRAY_CLASS);
116 COMMON_TYPES.put("java.lang.Double[]", DOUBLE_OBJECT_ARRAY_CLASS);
117 COMMON_TYPES.put("java.lang.String[]", STRING_OBJECT_ARRAY_CLASS);
118
119 }
120
121
122 private ClassUtils()
123 {
124
125 }
126
127
128
129 public synchronized static void addClassLoadingExtension(ClassLoaderExtension extension, boolean top)
130 {
131
132
133
134
135
136
137
138
139 ClassLoaderExtension [] retVal = new ClassLoaderExtension[classLoadingExtensions.length+1];
140 ArrayList extensions = new ArrayList(classLoadingExtensions.length+1);
141
142 if(!top)
143 {
144 extensions.addAll(Arrays.asList(classLoadingExtensions));
145 }
146 extensions.add(extension);
147 if(top)
148 {
149 extensions.addAll(Arrays.asList(classLoadingExtensions));
150 }
151
152 classLoadingExtensions = (ClassLoaderExtension []) extensions.toArray(retVal);
153 }
154
155
156
157
158
159
160
161
162
163
164
165 public static Class classForName(String type)
166 throws ClassNotFoundException
167 {
168
169
170
171 ClassLoaderExtension [] loaderPlugins = classLoadingExtensions;
172
173 int plugins = loaderPlugins.length;
174 for(int cnt = 0; cnt < loaderPlugins.length; cnt ++)
175 {
176 ClassLoaderExtension extension = loaderPlugins[cnt];
177 Class retVal = extension.forName(type);
178 if(retVal != null)
179 {
180 return retVal;
181 }
182 }
183
184
185 if (type == null)
186 {
187 throw new NullPointerException("type");
188 }
189 try
190 {
191
192 return Class.forName(type,
193 false,
194 getContextClassLoader());
195 }
196 catch (ClassNotFoundException ignore)
197 {
198
199 return Class.forName(type,
200 false,
201 ClassUtils.class.getClassLoader());
202 }
203 }
204
205
206
207
208
209
210
211
212
213
214 public static Class simpleClassForName(String type)
215 {
216 try
217 {
218 return classForName(type);
219 }
220 catch (ClassNotFoundException e)
221 {
222 log.log(Level.SEVERE, "Class " + type + " not found", e);
223 throw new FacesException(e);
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238 public static Class javaTypeToClass(String type)
239 throws ClassNotFoundException
240 {
241 if (type == null)
242 {
243 throw new NullPointerException("type");
244 }
245
246
247 Class clazz = (Class) COMMON_TYPES.get(type);
248 if (clazz != null)
249 {
250 return clazz;
251 }
252
253 int len = type.length();
254 if (len > 2 && type.charAt(len - 1) == ']' && type.charAt(len - 2) == '[')
255 {
256 String componentType = type.substring(0, len - 2);
257 Class componentTypeClass = classForName(componentType);
258 return Array.newInstance(componentTypeClass, 0).getClass();
259 }
260
261 return classForName(type);
262
263 }
264
265
266
267
268
269
270
271
272
273
274 public static Class simpleJavaTypeToClass(String type)
275 {
276 try
277 {
278 return javaTypeToClass(type);
279 }
280 catch (ClassNotFoundException e)
281 {
282 log.log(Level.SEVERE, "Class " + type + " not found", e);
283 throw new FacesException(e);
284 }
285 }
286
287 public static URL getResource(String resource)
288 {
289 URL url = getContextClassLoader().getResource(resource);
290 if (url == null)
291 {
292 url = ClassUtils.class.getClassLoader().getResource(resource);
293 }
294 return url;
295 }
296
297 public static InputStream getResourceAsStream(String resource)
298 {
299 InputStream stream = getContextClassLoader()
300 .getResourceAsStream(resource);
301 if (stream == null)
302 {
303
304 stream = ClassUtils.class.getClassLoader().getResourceAsStream(resource);
305 }
306 return stream;
307 }
308
309
310
311
312
313
314
315 public static Iterator getResources(String resource, Object defaultObject)
316 {
317 try
318 {
319 Enumeration resources = getCurrentLoader(defaultObject).getResources(resource);
320 List lst = new ArrayList();
321 while (resources.hasMoreElements())
322 {
323 lst.add(resources.nextElement());
324 }
325 return lst.iterator();
326 }
327 catch (IOException e)
328 {
329 log.log(Level.SEVERE, e.getMessage(), e);
330 throw new FacesException(e);
331 }
332 }
333
334
335 public static Object newInstance(String type)
336 throws FacesException
337 {
338 if (type == null)
339 {
340 return null;
341 }
342 return newInstance(simpleClassForName(type));
343 }
344
345 public static Object newInstance(String type, Class expectedType) throws FacesException
346 {
347 return newInstance(type, expectedType == null ? null : new Class[] {expectedType});
348 }
349
350 public static Object newInstance(String type, Class[] expectedTypes)
351 {
352 if (type == null)
353 {
354 return null;
355 }
356
357 Class clazzForName = simpleClassForName(type);
358
359 if(expectedTypes != null)
360 {
361 for (int i = 0, size = expectedTypes.length; i < size; i++)
362 {
363 if (!expectedTypes[i].isAssignableFrom(clazzForName))
364 {
365 throw new FacesException("'" + type + "' does not implement expected type '" + expectedTypes[i]
366 + "'");
367 }
368 }
369 }
370
371 return newInstance(clazzForName);
372 }
373
374 public static <T> T newInstance(Class<T> clazz)
375 throws FacesException
376 {
377 try
378 {
379 return clazz.newInstance();
380 }
381 catch(NoClassDefFoundError e)
382 {
383 log.log(Level.SEVERE, "Class : "+clazz.getName()+" not found.",e);
384 throw new FacesException(e);
385 }
386 catch (InstantiationException e)
387 {
388 log.log(Level.SEVERE, e.getMessage(), e);
389 throw new FacesException(e);
390 }
391 catch (IllegalAccessException e)
392 {
393 log.log(Level.SEVERE, e.getMessage(), e);
394 throw new FacesException(e);
395 }
396 }
397
398 public static <T> T newInstance(Class<T> clazz,
399 Class<?>[] constructorArgClasses,
400 Object... constructorArgs) throws NoSuchMethodException
401 {
402 if (constructorArgs.length == 0)
403 {
404
405 return newInstance(clazz);
406 }
407
408
409 Constructor constructor = clazz.getConstructor(constructorArgClasses);
410
411 try
412 {
413
414 return (T) constructor.newInstance(constructorArgs);
415 }
416 catch (Exception e)
417 {
418 throw new FacesException(e);
419 }
420 }
421
422 public static Object convertToType(Object value, Class desiredClass)
423 {
424 if (value == null)
425 {
426 return null;
427 }
428
429 try
430 {
431 ExpressionFactory expFactory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
432 return expFactory.coerceToType(value, desiredClass);
433 }
434 catch (Exception e)
435 {
436 String message = "Cannot coerce " + value.getClass().getName()
437 + " to " + desiredClass.getName();
438 log.log(Level.SEVERE, message, e);
439 throw new FacesException(message, e);
440 }
441 }
442
443
444
445
446
447
448
449
450
451 protected static ClassLoader getCurrentLoader(Object defaultObject)
452 {
453 ClassLoader loader = getContextClassLoader();
454 if(loader == null)
455 {
456 loader = defaultObject.getClass().getClassLoader();
457 }
458 return loader;
459 }
460
461
462
463
464
465
466
467
468 public static ClassLoader getContextClassLoader()
469 {
470
471 return ClassLoaderUtils.getContextClassLoader();
472 }
473
474
475
476
477
478
479
480
481
482
483
484 public static <T> T buildApplicationObject(Class<T> interfaceClass,
485 Collection<String> classNamesIterator, T defaultObject)
486 {
487 return buildApplicationObject(interfaceClass, null, null, classNamesIterator, defaultObject);
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505 @SuppressWarnings("unchecked")
506 public static <T> T buildApplicationObject(Class<T> interfaceClass, Class<? extends T> extendedInterfaceClass,
507 Class<? extends T> extendedInterfaceWrapperClass,
508 Collection<String> classNamesIterator, T defaultObject)
509 {
510 T current = defaultObject;
511
512
513 for (String implClassName : classNamesIterator)
514 {
515 Class<? extends T> implClass = ClassUtils.simpleClassForName(implClassName);
516
517
518 if (!interfaceClass.isAssignableFrom(implClass))
519 {
520 throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
521 }
522
523 if (current == null)
524 {
525
526 current = (T) ClassUtils.newInstance(implClass);
527 }
528 else
529 {
530
531 T newCurrent = null;
532 try
533 {
534 Constructor<? extends T> delegationConstructor = null;
535
536
537
538 if (extendedInterfaceClass != null
539 && extendedInterfaceClass.isAssignableFrom(current.getClass()))
540 {
541 try
542 {
543 delegationConstructor =
544 implClass.getConstructor(new Class[] {extendedInterfaceClass});
545 }
546 catch (NoSuchMethodException mnfe)
547 {
548
549 }
550 }
551 if (delegationConstructor == null)
552 {
553
554 delegationConstructor =
555 implClass.getConstructor(new Class[] {interfaceClass});
556 }
557
558 try
559 {
560
561 newCurrent = delegationConstructor.newInstance(new Object[] { current });
562 }
563 catch (InstantiationException e)
564 {
565 log.log(Level.SEVERE, e.getMessage(), e);
566 throw new FacesException(e);
567 }
568 catch (IllegalAccessException e)
569 {
570 log.log(Level.SEVERE, e.getMessage(), e);
571 throw new FacesException(e);
572 }
573 catch (InvocationTargetException e)
574 {
575 log.log(Level.SEVERE, e.getMessage(), e);
576 throw new FacesException(e);
577 }
578 }
579 catch (NoSuchMethodException e)
580 {
581
582 newCurrent = (T) ClassUtils.newInstance(implClass);
583 }
584
585
586
587
588 if (extendedInterfaceWrapperClass != null
589 && !extendedInterfaceClass.isAssignableFrom(newCurrent.getClass()))
590 {
591 try
592 {
593 Constructor<? extends T> wrapperConstructor
594 = extendedInterfaceWrapperClass.getConstructor(
595 new Class[] {interfaceClass, extendedInterfaceClass});
596 newCurrent = wrapperConstructor.newInstance(new Object[] {newCurrent, current});
597 }
598 catch (NoSuchMethodException e)
599 {
600 log.log(Level.SEVERE, e.getMessage(), e);
601 throw new FacesException(e);
602 }
603 catch (InstantiationException e)
604 {
605 log.log(Level.SEVERE, e.getMessage(), e);
606 throw new FacesException(e);
607 }
608 catch (IllegalAccessException e)
609 {
610 log.log(Level.SEVERE, e.getMessage(), e);
611 throw new FacesException(e);
612 }
613 catch (InvocationTargetException e)
614 {
615 log.log(Level.SEVERE, e.getMessage(), e);
616 throw new FacesException(e);
617 }
618 }
619
620 current = newCurrent;
621 }
622 }
623
624 return current;
625 }
626 }