1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces;
20
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.security.AccessController;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31
32 import javax.faces.application.ApplicationFactory;
33 import javax.faces.component.visit.VisitContextFactory;
34 import javax.faces.context.ExceptionHandlerFactory;
35 import javax.faces.context.ExternalContextFactory;
36 import javax.faces.context.FacesContextFactory;
37 import javax.faces.context.PartialViewContextFactory;
38 import javax.faces.lifecycle.LifecycleFactory;
39 import javax.faces.render.RenderKitFactory;
40 import javax.faces.view.ViewDeclarationLanguageFactory;
41 import javax.faces.view.facelets.FaceletCacheFactory;
42 import javax.faces.view.facelets.TagHandlerDelegateFactory;
43
44
45
46
47
48
49
50 public final class FactoryFinder
51 {
52 public static final String APPLICATION_FACTORY = "javax.faces.application.ApplicationFactory";
53 public static final String EXCEPTION_HANDLER_FACTORY = "javax.faces.context.ExceptionHandlerFactory";
54 public static final String EXTERNAL_CONTEXT_FACTORY = "javax.faces.context.ExternalContextFactory";
55 public static final String FACES_CONTEXT_FACTORY = "javax.faces.context.FacesContextFactory";
56 public static final String LIFECYCLE_FACTORY = "javax.faces.lifecycle.LifecycleFactory";
57 public static final String PARTIAL_VIEW_CONTEXT_FACTORY = "javax.faces.context.PartialViewContextFactory";
58 public static final String RENDER_KIT_FACTORY = "javax.faces.render.RenderKitFactory";
59 public static final String TAG_HANDLER_DELEGATE_FACTORY = "javax.faces.view.facelets.TagHandlerDelegateFactory";
60 public static final String VIEW_DECLARATION_LANGUAGE_FACTORY = "javax.faces.view.ViewDeclarationLanguageFactory";
61 public static final String VISIT_CONTEXT_FACTORY = "javax.faces.component.visit.VisitContextFactory";
62 public static final String FACELET_CACHE_FACTORY = "javax.faces.view.facelets.FaceletCacheFactory";
63
64
65
66
67
68 private static Map<ClassLoader, Map<String, List<String>>> registeredFactoryNames
69 = new HashMap<ClassLoader, Map<String, List<String>>>();
70
71
72
73
74
75
76
77
78
79 private static Map<ClassLoader, Map<String, Object>> factories
80 = new HashMap<ClassLoader, Map<String, Object>>();
81
82 private static final Set<String> VALID_FACTORY_NAMES = new HashSet<String>();
83 private static final Map<String, Class<?>> ABSTRACT_FACTORY_CLASSES = new HashMap<String, Class<?>>();
84 private static final ClassLoader MYFACES_CLASSLOADER;
85
86 static
87 {
88 VALID_FACTORY_NAMES.add(APPLICATION_FACTORY);
89 VALID_FACTORY_NAMES.add(EXCEPTION_HANDLER_FACTORY);
90 VALID_FACTORY_NAMES.add(EXTERNAL_CONTEXT_FACTORY);
91 VALID_FACTORY_NAMES.add(FACES_CONTEXT_FACTORY);
92 VALID_FACTORY_NAMES.add(LIFECYCLE_FACTORY);
93 VALID_FACTORY_NAMES.add(PARTIAL_VIEW_CONTEXT_FACTORY);
94 VALID_FACTORY_NAMES.add(RENDER_KIT_FACTORY);
95 VALID_FACTORY_NAMES.add(TAG_HANDLER_DELEGATE_FACTORY);
96 VALID_FACTORY_NAMES.add(VIEW_DECLARATION_LANGUAGE_FACTORY);
97 VALID_FACTORY_NAMES.add(VISIT_CONTEXT_FACTORY);
98 VALID_FACTORY_NAMES.add(FACELET_CACHE_FACTORY);
99
100 ABSTRACT_FACTORY_CLASSES.put(APPLICATION_FACTORY, ApplicationFactory.class);
101 ABSTRACT_FACTORY_CLASSES.put(EXCEPTION_HANDLER_FACTORY, ExceptionHandlerFactory.class);
102 ABSTRACT_FACTORY_CLASSES.put(EXTERNAL_CONTEXT_FACTORY, ExternalContextFactory.class);
103 ABSTRACT_FACTORY_CLASSES.put(FACES_CONTEXT_FACTORY, FacesContextFactory.class);
104 ABSTRACT_FACTORY_CLASSES.put(LIFECYCLE_FACTORY, LifecycleFactory.class);
105 ABSTRACT_FACTORY_CLASSES.put(PARTIAL_VIEW_CONTEXT_FACTORY, PartialViewContextFactory.class);
106 ABSTRACT_FACTORY_CLASSES.put(RENDER_KIT_FACTORY, RenderKitFactory.class);
107 ABSTRACT_FACTORY_CLASSES.put(TAG_HANDLER_DELEGATE_FACTORY, TagHandlerDelegateFactory.class);
108 ABSTRACT_FACTORY_CLASSES.put(VIEW_DECLARATION_LANGUAGE_FACTORY, ViewDeclarationLanguageFactory.class);
109 ABSTRACT_FACTORY_CLASSES.put(VISIT_CONTEXT_FACTORY, VisitContextFactory.class);
110 ABSTRACT_FACTORY_CLASSES.put(FACELET_CACHE_FACTORY, FaceletCacheFactory.class);
111 try
112 {
113 ClassLoader classLoader;
114 if (System.getSecurityManager() != null)
115 {
116 classLoader = (ClassLoader) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction()
117 {
118 public Object run()
119 {
120 return FactoryFinder.class.getClassLoader();
121 }
122 });
123 }
124 else
125 {
126 classLoader = FactoryFinder.class.getClassLoader();
127 }
128
129 if (classLoader == null)
130 {
131 throw new FacesException("jsf api class loader cannot be identified", null);
132 }
133 MYFACES_CLASSLOADER = classLoader;
134 }
135 catch (Exception e)
136 {
137 throw new FacesException("jsf api class loader cannot be identified", e);
138 }
139 }
140
141
142
143 private static Object factoryFinderProviderFactoryInstance;
144
145 private static volatile boolean initialized = false;
146
147 private static void initializeFactoryFinderProviderFactory()
148 {
149 if (!initialized)
150 {
151 factoryFinderProviderFactoryInstance = _FactoryFinderProviderFactory.getInstance();
152 initialized = true;
153 }
154 }
155
156
157
158
159 FactoryFinder()
160 {
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 public static Object getFactory(String factoryName) throws FacesException
195 {
196 if (factoryName == null)
197 {
198 throw new NullPointerException("factoryName may not be null");
199 }
200
201 initializeFactoryFinderProviderFactory();
202
203 if (factoryFinderProviderFactoryInstance == null)
204 {
205
206 return _getFactory(factoryName);
207 }
208 else
209 {
210 try
211 {
212
213 Object ffp = _FactoryFinderProviderFactory
214 .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
215 .invoke(factoryFinderProviderFactoryInstance, null);
216
217
218 return _FactoryFinderProviderFactory
219 .FACTORY_FINDER_PROVIDER_GET_FACTORY_METHOD.invoke(ffp, factoryName);
220 }
221 catch (InvocationTargetException e)
222 {
223 Throwable targetException = e.getCause();
224 if (targetException instanceof NullPointerException)
225 {
226 throw (NullPointerException) targetException;
227 }
228 else if (targetException instanceof FacesException)
229 {
230 throw (FacesException) targetException;
231 }
232 else if (targetException instanceof IllegalArgumentException)
233 {
234 throw (IllegalArgumentException) targetException;
235 }
236 else if (targetException instanceof IllegalStateException)
237 {
238 throw (IllegalStateException) targetException;
239 }
240 else if (targetException == null)
241 {
242 throw new FacesException(e);
243 }
244 else
245 {
246 throw new FacesException(targetException);
247 }
248 }
249 catch (Exception e)
250 {
251
252 throw new FacesException(e);
253 }
254 }
255 }
256
257 private static Object _getFactory(String factoryName) throws FacesException
258 {
259 ClassLoader classLoader = getClassLoader();
260
261
262
263
264 Map<String, List<String>> factoryClassNames = null;
265 Map<String, Object> factoryMap = null;
266
267 synchronized (registeredFactoryNames)
268 {
269 factoryClassNames = registeredFactoryNames.get(classLoader);
270
271 if (factoryClassNames == null)
272 {
273 String message
274 = "No Factories configured for this Application. This happens if the faces-initialization "
275 + "does not work at all - make sure that you properly include all configuration "
276 + "settings necessary for a basic faces application "
277 + "and that all the necessary libs are included. Also check the logging output of your "
278 + "web application and your container for any exceptions!"
279 + "\nIf you did that and find nothing, the mistake might be due to the fact "
280 + "that you use some special web-containers which "
281 + "do not support registering context-listeners via TLD files and "
282 + "a context listener is not setup in your web.xml.\n"
283 + "A typical config looks like this;\n<listener>\n"
284 + " <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>\n"
285 + "</listener>\n";
286 throw new IllegalStateException(message);
287 }
288
289 if (!factoryClassNames.containsKey(factoryName))
290 {
291 throw new IllegalArgumentException("no factory " + factoryName + " configured for this application.");
292 }
293
294 factoryMap = factories.get(classLoader);
295
296 if (factoryMap == null)
297 {
298 factoryMap = new HashMap<String, Object>();
299 factories.put(classLoader, factoryMap);
300 }
301 }
302
303 List<String> classNames;
304 Object factory;
305 synchronized (factoryClassNames)
306 {
307 factory = factoryMap.get(factoryName);
308 if (factory != null)
309 {
310 return factory;
311 }
312
313 classNames = factoryClassNames.get(factoryName);
314 }
315
316
317 factory = newFactoryInstance(ABSTRACT_FACTORY_CLASSES.get(factoryName), classNames.iterator(), classLoader);
318
319 synchronized (factoryClassNames)
320 {
321
322 if (factoryMap.get(factoryName) == null)
323 {
324 factoryMap.put(factoryName, factory);
325 }
326 }
327
328 return factory;
329 }
330
331 private static Object newFactoryInstance(Class<?> interfaceClass, Iterator<String> classNamesIterator,
332 ClassLoader classLoader)
333 {
334 try
335 {
336 Object current = null;
337
338 while (classNamesIterator.hasNext())
339 {
340 String implClassName = classNamesIterator.next();
341 Class<?> implClass = null;
342 try
343 {
344 implClass = classLoader.loadClass(implClassName);
345 }
346 catch (ClassNotFoundException e)
347 {
348 implClass = MYFACES_CLASSLOADER.loadClass(implClassName);
349 }
350
351
352 if (!interfaceClass.isAssignableFrom(implClass))
353 {
354 throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
355 }
356
357 if (current == null)
358 {
359
360 current = implClass.newInstance();
361 }
362 else
363 {
364
365 try
366 {
367 Constructor<?> delegationConstructor = implClass.getConstructor(new Class[] { interfaceClass });
368
369 try
370 {
371
372 current = delegationConstructor.newInstance(new Object[] { current });
373 }
374 catch (InstantiationException e)
375 {
376 throw new FacesException(e);
377 }
378 catch (IllegalAccessException e)
379 {
380 throw new FacesException(e);
381 }
382 catch (InvocationTargetException e)
383 {
384 throw new FacesException(e);
385 }
386 }
387 catch (NoSuchMethodException e)
388 {
389
390 current = implClass.newInstance();
391 }
392 }
393 }
394
395 return current;
396 }
397 catch (ClassNotFoundException e)
398 {
399 throw new FacesException(e);
400 }
401 catch (InstantiationException e)
402 {
403 throw new FacesException(e);
404 }
405 catch (IllegalAccessException e)
406 {
407 throw new FacesException(e);
408 }
409 }
410
411 public static void setFactory(String factoryName, String implName)
412 {
413 if (factoryName == null)
414 {
415 throw new NullPointerException("factoryName may not be null");
416 }
417
418 initializeFactoryFinderProviderFactory();
419
420 if (factoryFinderProviderFactoryInstance == null)
421 {
422
423 _setFactory(factoryName, implName);
424 }
425 else
426 {
427 try
428 {
429
430 Object ffp = _FactoryFinderProviderFactory
431 .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
432 .invoke(factoryFinderProviderFactoryInstance, null);
433
434
435 _FactoryFinderProviderFactory
436 .FACTORY_FINDER_PROVIDER_SET_FACTORY_METHOD.invoke(ffp, factoryName, implName);
437 }
438 catch (InvocationTargetException e)
439 {
440 Throwable targetException = e.getCause();
441 if (targetException instanceof NullPointerException)
442 {
443 throw (NullPointerException) targetException;
444 }
445 else if (targetException instanceof FacesException)
446 {
447 throw (FacesException) targetException;
448 }
449 else if (targetException instanceof IllegalArgumentException)
450 {
451 throw (IllegalArgumentException) targetException;
452 }
453 else if (targetException == null)
454 {
455 throw new FacesException(e);
456 }
457 else
458 {
459 throw new FacesException(targetException);
460 }
461 }
462 catch (Exception e)
463 {
464
465 throw new FacesException(e);
466 }
467
468 }
469 }
470
471 private static void _setFactory(String factoryName, String implName)
472 {
473 checkFactoryName(factoryName);
474
475 ClassLoader classLoader = getClassLoader();
476 Map<String, List<String>> factoryClassNames = null;
477 synchronized (registeredFactoryNames)
478 {
479 Map<String, Object> factories = FactoryFinder.factories.get(classLoader);
480
481 if (factories != null && factories.containsKey(factoryName))
482 {
483
484
485 return;
486 }
487
488 factoryClassNames = registeredFactoryNames.get(classLoader);
489
490 if (factoryClassNames == null)
491 {
492 factoryClassNames = new HashMap<String, List<String>>();
493 registeredFactoryNames.put(classLoader, factoryClassNames);
494 }
495 }
496
497 synchronized (factoryClassNames)
498 {
499 List<String> classNameList = factoryClassNames.get(factoryName);
500
501 if (classNameList == null)
502 {
503 classNameList = new ArrayList<String>();
504 factoryClassNames.put(factoryName, classNameList);
505 }
506
507 classNameList.add(implName);
508 }
509 }
510
511 public static void releaseFactories() throws FacesException
512 {
513 initializeFactoryFinderProviderFactory();
514
515 if (factoryFinderProviderFactoryInstance == null)
516 {
517
518 _releaseFactories();
519 }
520 else
521 {
522 try
523 {
524
525 Object ffp = _FactoryFinderProviderFactory
526 .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
527 .invoke(factoryFinderProviderFactoryInstance, null);
528
529
530 _FactoryFinderProviderFactory.FACTORY_FINDER_PROVIDER_RELEASE_FACTORIES_METHOD.invoke(ffp, null);
531 }
532 catch (InvocationTargetException e)
533 {
534 Throwable targetException = e.getCause();
535 if (targetException instanceof FacesException)
536 {
537 throw (FacesException) targetException;
538 }
539 else if (targetException == null)
540 {
541 throw new FacesException(e);
542 }
543 else
544 {
545 throw new FacesException(targetException);
546 }
547 }
548 catch (Exception e)
549 {
550
551 throw new FacesException(e);
552 }
553
554 }
555 }
556
557 private static void _releaseFactories() throws FacesException
558 {
559 ClassLoader classLoader = getClassLoader();
560
561
562 synchronized (registeredFactoryNames)
563 {
564 factories.remove(classLoader);
565
566
567
568 Map<String, List<String>> factoryClassNames = registeredFactoryNames.get(classLoader);
569 if (factoryClassNames != null)
570 {
571 factoryClassNames.clear();
572 }
573
574 registeredFactoryNames.remove(classLoader);
575 }
576 }
577
578 private static void checkFactoryName(String factoryName)
579 {
580 if (!VALID_FACTORY_NAMES.contains(factoryName))
581 {
582 throw new IllegalArgumentException("factoryName '" + factoryName + "'");
583 }
584 }
585
586 private static ClassLoader getClassLoader()
587 {
588 try
589 {
590 ClassLoader classLoader = null;
591 if (System.getSecurityManager() != null)
592 {
593 classLoader = (ClassLoader) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction()
594 {
595 public Object run()
596 {
597 return Thread.currentThread().getContextClassLoader();
598 }
599 });
600 }
601 else
602 {
603 classLoader = Thread.currentThread().getContextClassLoader();
604 }
605
606 if (classLoader == null)
607 {
608 throw new FacesException("web application class loader cannot be identified", null);
609 }
610 return classLoader;
611 }
612 catch (Exception e)
613 {
614 throw new FacesException("web application class loader cannot be identified", e);
615 }
616 }
617 }