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