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