1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.webapp;
20
21 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
22 import org.apache.myfaces.config.FacesConfigValidator;
23 import org.apache.myfaces.config.FacesConfigurator;
24 import org.apache.myfaces.config.ManagedBeanBuilder;
25 import org.apache.myfaces.config.RuntimeConfig;
26 import org.apache.myfaces.config.element.ManagedBean;
27 import org.apache.myfaces.context.ReleaseableExternalContext;
28 import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
29 import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
30 import org.apache.myfaces.shared.util.StateUtils;
31 import org.apache.myfaces.shared.util.WebConfigParamUtils;
32 import org.apache.myfaces.cdi.dependent.BeanEntry;
33 import org.apache.myfaces.spi.InjectionProvider;
34 import org.apache.myfaces.spi.InjectionProviderException;
35 import org.apache.myfaces.spi.InjectionProviderFactory;
36 import org.apache.myfaces.spi.ViewScopeProvider;
37 import org.apache.myfaces.spi.ViewScopeProviderFactory;
38 import org.apache.myfaces.spi.WebConfigProvider;
39 import org.apache.myfaces.spi.WebConfigProviderFactory;
40 import org.apache.myfaces.util.ExternalSpecifications;
41 import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
42
43 import javax.el.ExpressionFactory;
44 import javax.faces.application.Application;
45 import javax.faces.application.ProjectStage;
46 import javax.faces.component.UIViewRoot;
47 import javax.faces.context.ExceptionHandler;
48 import javax.faces.context.ExternalContext;
49 import javax.faces.context.FacesContext;
50 import javax.faces.event.PostConstructApplicationEvent;
51 import javax.faces.event.PreDestroyApplicationEvent;
52 import javax.faces.event.SystemEvent;
53 import javax.servlet.ServletContext;
54 import java.lang.reflect.InvocationTargetException;
55 import java.lang.reflect.Method;
56 import java.util.ArrayList;
57 import java.util.List;
58 import java.util.Locale;
59 import java.util.Map;
60 import java.util.logging.Level;
61 import java.util.logging.Logger;
62 import org.apache.myfaces.shared.context.ExceptionHandlerImpl;
63 import org.apache.myfaces.shared.util.ClassUtils;
64 import org.apache.myfaces.spi.ServiceProviderFinder;
65 import org.apache.myfaces.spi.ServiceProviderFinderFactory;
66 import org.apache.myfaces.view.facelets.ViewPoolProcessor;
67
68
69
70
71 public abstract class AbstractFacesInitializer implements FacesInitializer
72 {
73
74
75
76
77 private static final Logger log = Logger.getLogger(AbstractFacesInitializer.class.getName());
78
79
80
81
82
83
84 private static final String FACES_SERVLET_ADDED_ATTRIBUTE = "org.apache.myfaces.DYNAMICALLY_ADDED_FACES_SERVLET";
85
86
87
88
89
90
91 private static final String FACES_SERVLET_FOUND = "org.apache.myfaces.FACES_SERVLET_FOUND";
92
93
94
95
96 @JSFWebConfigParam(since="1.2.7", group="EL")
97 protected static final String EXPRESSION_FACTORY = "org.apache.myfaces.EXPRESSION_FACTORY";
98
99
100
101
102 @JSFWebConfigParam(since="2.0.3", defaultValue="false")
103 protected static final String INITIALIZE_ALWAYS_STANDALONE = "org.apache.myfaces.INITIALIZE_ALWAYS_STANDALONE";
104
105
106
107
108
109
110
111 @JSFWebConfigParam(expectedValues="true, auto, false", defaultValue="auto")
112 public static final String INIT_PARAM_LOG_WEB_CONTEXT_PARAMS = "org.apache.myfaces.LOG_WEB_CONTEXT_PARAMS";
113 public static final String INIT_PARAM_LOG_WEB_CONTEXT_PARAMS_DEFAULT ="auto";
114
115 public static final String CDI_BEAN_MANAGER_INSTANCE = "oam.cdi.BEAN_MANAGER_INSTANCE";
116
117 private static final String CDI_SERVLET_CONTEXT_BEAN_MANAGER_ATTRIBUTE =
118 "javax.enterprise.inject.spi.BeanManager";
119
120 private static final String INJECTED_BEAN_STORAGE_KEY = "org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";
121
122
123
124
125
126 public void initFaces(ServletContext servletContext)
127 {
128 try
129 {
130 if (log.isLoggable(Level.FINEST))
131 {
132 log.finest("Initializing MyFaces");
133 }
134
135
136
137
138
139
140
141 FacesContext facesContext = FacesContext.getCurrentInstance();
142 ExternalContext externalContext = facesContext.getExternalContext();
143
144
145 ServiceProviderFinder spf = ServiceProviderFinderFactory.getServiceProviderFinder(
146 externalContext);
147 Map<String, List<String>> spfConfig = spf.calculateKnownServiceProviderMapInfo(
148 externalContext, ServiceProviderFinder.KNOWN_SERVICES);
149 if (spfConfig != null)
150 {
151 spf.initKnownServiceProviderMapInfo(externalContext, spfConfig);
152 }
153
154
155
156 if (!WebConfigParamUtils.getBooleanInitParameter(externalContext, INITIALIZE_ALWAYS_STANDALONE, false))
157 {
158 WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
159 facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
160
161 if (webConfigProvider.getFacesServletMappings(facesContext.getExternalContext()).isEmpty())
162 {
163
164 Boolean mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_FOUND);
165
166 if (mappingAdded == null || !mappingAdded)
167 {
168
169
170 mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_ADDED_ATTRIBUTE);
171
172 if (mappingAdded == null || !mappingAdded)
173 {
174 if (log.isLoggable(Level.WARNING))
175 {
176 log.warning("No mappings of FacesServlet found. Abort initializing MyFaces.");
177 }
178 return;
179 }
180 }
181 }
182 }
183
184 initCDIIntegration(servletContext, externalContext);
185
186 initContainerIntegration(servletContext, externalContext);
187
188 ViewScopeProviderFactory factory = ViewScopeProviderFactory.getViewScopeHandlerFactory(
189 externalContext);
190
191 ViewScopeProvider viewScopeHandler = factory.getViewScopeHandler(
192 externalContext);
193
194 ManagedBeanDestroyerListener listener = (ManagedBeanDestroyerListener)
195 externalContext.getApplicationMap().get(
196 ManagedBeanDestroyerListener.APPLICATION_MAP_KEY);
197
198 listener.setViewScopeHandler(viewScopeHandler);
199
200 String useEncryption = servletContext.getInitParameter(StateUtils.USE_ENCRYPTION);
201 if (!"false".equals(useEncryption))
202 {
203 StateUtils.initSecret(servletContext);
204 }
205
206
207 _createEagerBeans(facesContext);
208
209 _dispatchApplicationEvent(servletContext, PostConstructApplicationEvent.class);
210
211 if ( (facesContext.isProjectStage(ProjectStage.Development) ||
212 facesContext.isProjectStage(ProjectStage.Production)) &&
213 log.isLoggable(Level.INFO))
214 {
215 log.info("ServletContext initialized.");
216 }
217
218 WebConfigParamsLogger.logWebContextParams(facesContext);
219
220
221 ExternalSpecifications.isUnifiedELAvailable();
222 ExternalSpecifications.isBeanValidationAvailable();
223
224
225 ViewPoolProcessor.initialize(facesContext);
226
227
228 if (!facesContext.isProjectStage(ProjectStage.Production) &&
229 !facesContext.isProjectStage(ProjectStage.UnitTest))
230 {
231 ProjectStage projectStage = facesContext.getApplication().getProjectStage();
232 StringBuilder message = new StringBuilder("\n\n");
233 message.append("*******************************************************************\n");
234 message.append("*** WARNING: Apache MyFaces-2 is running in ");
235 message.append(projectStage.name().toUpperCase());
236 message.append(" mode.");
237 int length = projectStage.name().length();
238 for (int i = 0; i < 11 - length; i++)
239 {
240 message.append(" ");
241 }
242 message.append(" ***\n");
243 message.append("*** ");
244 for (int i = 0; i < length; i++)
245 {
246 message.append("^");
247 }
248 for (int i = 0; i < 20 - length; i++)
249 {
250 message.append(" ");
251 }
252 message.append("***\n");
253 message.append("*** Do NOT deploy to your live server(s) without changing this. ***\n");
254 message.append("*** See Application#getProjectStage() for more information. ***\n");
255 message.append("*******************************************************************\n");
256 log.log(Level.WARNING, message.toString());
257 }
258
259 }
260 catch (Exception ex)
261 {
262 log.log(Level.SEVERE, "An error occured while initializing MyFaces: "
263 + ex.getMessage(), ex);
264 }
265 }
266
267
268
269
270
271
272 private void _createEagerBeans(FacesContext facesContext)
273 {
274 ExternalContext externalContext = facesContext.getExternalContext();
275 RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
276 List<ManagedBean> eagerBeans = new ArrayList<ManagedBean>();
277
278
279 for (ManagedBean bean : runtimeConfig.getManagedBeans().values())
280 {
281 String eager = bean.getEager();
282 if (eager != null && "true".equals(eager))
283 {
284
285 if (ManagedBeanBuilder.APPLICATION.equals(bean.getManagedBeanScope()))
286 {
287
288 eagerBeans.add(bean);
289 }
290 else
291 {
292
293 log.log(Level.WARNING, "The managed-bean with name "
294 + bean.getManagedBeanName()
295 + " must be application scoped to support eager=true.");
296 }
297 }
298 }
299
300
301 if (!eagerBeans.isEmpty())
302 {
303 ManagedBeanBuilder managedBeanBuilder = new ManagedBeanBuilder();
304 Map<String, Object> applicationMap = externalContext.getApplicationMap();
305
306 for (ManagedBean bean : eagerBeans)
307 {
308
309 if (applicationMap.containsKey(bean.getManagedBeanName()))
310 {
311
312
313 continue;
314 }
315
316
317 Object beanInstance = managedBeanBuilder.buildManagedBean(facesContext, bean);
318
319
320 applicationMap.put(bean.getManagedBeanName(), beanInstance);
321 }
322 }
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340 private void _dispatchApplicationEvent(ServletContext servletContext, Class<? extends SystemEvent> eventClass)
341 {
342 FacesContext facesContext = FacesContext.getCurrentInstance();
343 Application application = facesContext.getApplication();
344 application.publishEvent(facesContext, eventClass, Application.class, application);
345 }
346
347
348
349
350 public void destroyFaces(ServletContext servletContext)
351 {
352
353 FacesContext facesContext = FacesContext.getCurrentInstance();
354
355 if (!WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
356 INITIALIZE_ALWAYS_STANDALONE, false))
357 {
358
359 WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
360 facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
361
362 if (webConfigProvider.getFacesServletMappings(facesContext.getExternalContext()).isEmpty())
363 {
364
365 Boolean mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_FOUND);
366
367 if (mappingAdded == null || !mappingAdded)
368 {
369
370
371 mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_ADDED_ATTRIBUTE);
372
373 if (mappingAdded == null || !mappingAdded)
374 {
375 if (log.isLoggable(Level.WARNING))
376 {
377 log.warning("No mappings of FacesServlet found. Abort destroy MyFaces.");
378 }
379 return;
380 }
381 }
382 }
383 }
384
385 _dispatchApplicationEvent(servletContext, PreDestroyApplicationEvent.class);
386
387 _callPreDestroyOnInjectedJSFArtifacts(facesContext);
388
389
390 MetaRulesetImpl.clearMetadataTargetCache();
391
392
393 try
394 {
395 Class<?> c = Class.forName("javax.faces.component.UIViewParameter");
396 Method m = c.getDeclaredMethod("releaseRenderer");
397 m.setAccessible(true);
398 m.invoke(null);
399 }
400 catch(ClassNotFoundException e)
401 {
402 log.log(Level.SEVERE, e.getMessage(), e);
403 }
404 catch(NoSuchMethodException e)
405 {
406 log.log(Level.SEVERE, e.getMessage(), e);
407 }
408 catch(IllegalAccessException e)
409 {
410 log.log(Level.SEVERE, e.getMessage(), e);
411 }
412 catch(InvocationTargetException e)
413 {
414 log.log(Level.SEVERE, e.getMessage(), e);
415 }
416
417
418 }
419
420
421
422
423
424
425
426
427
428
429
430 protected RuntimeConfig buildConfiguration(ServletContext servletContext,
431 ExternalContext externalContext, ExpressionFactory expressionFactory)
432 {
433 RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
434 runtimeConfig.setExpressionFactory(expressionFactory);
435
436
437 new FacesConfigurator(externalContext).configure();
438
439 validateFacesConfig(servletContext, externalContext);
440
441 return runtimeConfig;
442 }
443
444 protected void validateFacesConfig(ServletContext servletContext, ExternalContext externalContext)
445 {
446 String validate = servletContext.getInitParameter(FacesConfigValidator.VALIDATE_CONTEXT_PARAM);
447 if ("true".equals(validate) && log.isLoggable(Level.WARNING))
448 {
449 List<String> warnings = FacesConfigValidator.validate(
450 externalContext);
451
452 for (String warning : warnings)
453 {
454 log.warning(warning);
455 }
456 }
457 }
458
459
460
461
462
463
464
465
466
467 protected static ExpressionFactory getUserDefinedExpressionFactory(ExternalContext externalContext)
468 {
469 String expressionFactoryClassName
470 = WebConfigParamUtils.getStringInitParameter(externalContext, EXPRESSION_FACTORY);
471 if (expressionFactoryClassName != null
472 && expressionFactoryClassName.trim().length() > 0)
473 {
474 if (log.isLoggable(Level.FINE))
475 {
476 log.fine("Attempting to load the ExpressionFactory implementation "
477 + "you've specified: '" + expressionFactoryClassName + "'.");
478 }
479
480 return loadExpressionFactory(expressionFactoryClassName);
481 }
482
483 return null;
484 }
485
486
487
488
489
490
491
492
493 protected static ExpressionFactory loadExpressionFactory(String expressionFactoryClassName)
494 {
495 try
496 {
497 ClassLoader cl = ClassUtils.getContextClassLoader();
498 if (cl == null)
499 {
500 cl = AbstractFacesInitializer.class.getClassLoader();
501 }
502
503 Class<?> expressionFactoryClass = cl.loadClass(expressionFactoryClassName);
504 return (ExpressionFactory) expressionFactoryClass.newInstance();
505 }
506 catch (Exception ex)
507 {
508 if (log.isLoggable(Level.FINE))
509 {
510 log.log(Level.FINE, "An error occured while instantiating a new ExpressionFactory. "
511 + "Attempted to load class '" + expressionFactoryClassName + "'.", ex);
512 }
513 }
514
515 return null;
516 }
517
518 public FacesContext initStartupFacesContext(ServletContext servletContext)
519 {
520
521
522 return _createFacesContext(servletContext, true);
523 }
524
525 public void destroyStartupFacesContext(FacesContext facesContext)
526 {
527 _releaseFacesContext(facesContext);
528 }
529
530 public FacesContext initShutdownFacesContext(ServletContext servletContext)
531 {
532 return _createFacesContext(servletContext, false);
533 }
534
535 public void destroyShutdownFacesContext(FacesContext facesContext)
536 {
537 _releaseFacesContext(facesContext);
538 }
539
540 private FacesContext _createFacesContext(ServletContext servletContext, boolean startup)
541 {
542 ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, startup);
543 ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
544 FacesContext facesContext = new StartupFacesContextImpl(externalContext,
545 (ReleaseableExternalContext) externalContext, exceptionHandler, startup);
546
547
548
549 UIViewRoot startupViewRoot = new UIViewRoot();
550 startupViewRoot.setLocale(Locale.getDefault());
551 facesContext.setViewRoot(startupViewRoot);
552
553 return facesContext;
554 }
555
556 private void _releaseFacesContext(FacesContext facesContext)
557 {
558
559
560 if (facesContext != null)
561 {
562 facesContext.release();
563 }
564 }
565
566
567
568
569
570
571
572 protected abstract void initContainerIntegration(
573 ServletContext servletContext, ExternalContext externalContext);
574
575
576
577
578
579
580
581
582
583
584
585 protected void initCDIIntegration(
586 ServletContext servletContext, ExternalContext externalContext)
587 {
588
589
590
591
592
593 Object beanManager = servletContext.getAttribute(
594 CDI_SERVLET_CONTEXT_BEAN_MANAGER_ATTRIBUTE);
595 if (beanManager == null)
596 {
597 beanManager = lookupBeanManagerFromCDI();
598 }
599 if (beanManager == null)
600 {
601 beanManager = lookupBeanManagerFromJndi();
602 }
603 if (beanManager != null)
604 {
605 externalContext.getApplicationMap().put(CDI_BEAN_MANAGER_INSTANCE,
606 beanManager);
607 }
608 }
609
610
611
612
613
614
615
616 private Object lookupBeanManagerFromCDI()
617 {
618 try
619 {
620 Class cdiClass = null;
621 Method cdiCurrentMethod = null;
622 Method cdiGetBeanManagerMethod = null;
623 cdiClass = simpleClassForNameNoException("javax.enterprise.inject.spi.CDI");
624 if (cdiClass != null)
625 {
626 cdiCurrentMethod = cdiClass.getMethod("current");
627
628 Object cdiInstance = cdiCurrentMethod.invoke(null);
629
630 cdiGetBeanManagerMethod = cdiClass.getMethod("getBeanManager");
631 return cdiGetBeanManagerMethod.invoke(cdiInstance);
632 }
633 }
634 catch (Exception e)
635 {
636
637 }
638 return null;
639 }
640
641 private static Class simpleClassForNameNoException(String type)
642 {
643 try
644 {
645 return ClassUtils.classForName(type);
646 }
647 catch (ClassNotFoundException e)
648 {
649
650
651 return null;
652 }
653 }
654
655
656
657
658
659 private Object lookupBeanManagerFromJndi()
660 {
661 Object beanManager = null;
662
663 Class icclazz = null;
664 Method lookupMethod = null;
665 try
666 {
667 icclazz = ClassUtils.simpleClassForName("javax.naming.InitialContext");
668 if (icclazz != null)
669 {
670 lookupMethod = icclazz.getMethod("doLookup", String.class);
671 }
672 }
673 catch (Throwable t)
674 {
675
676 }
677 if (lookupMethod != null)
678 {
679
680 try
681 {
682
683
684 beanManager = lookupMethod.invoke(icclazz, "java:comp/BeanManager");
685 }
686 catch (Exception e)
687 {
688
689 }
690 catch (NoClassDefFoundError e)
691 {
692
693
694
695 }
696
697 if (beanManager == null)
698 {
699 try
700 {
701
702
703 beanManager = lookupMethod.invoke(icclazz, "java:comp/env/BeanManager");
704 }
705 catch (Exception e)
706 {
707
708 }
709 catch (NoClassDefFoundError e)
710 {
711
712
713
714 }
715 }
716 }
717
718 return beanManager;
719 }
720
721 public void _callPreDestroyOnInjectedJSFArtifacts(FacesContext facesContext)
722 {
723 InjectionProvider injectionProvider = InjectionProviderFactory.getInjectionProviderFactory(
724 facesContext.getExternalContext()).getInjectionProvider(facesContext.getExternalContext());
725 List<BeanEntry> injectedBeanStorage =
726 (List<BeanEntry>)facesContext.getExternalContext().getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
727
728 if (injectedBeanStorage != null)
729 {
730 for (BeanEntry entry : injectedBeanStorage)
731 {
732 try
733 {
734 injectionProvider.preDestroy(entry.getInstance(), entry.getCreationMetaData());
735 }
736 catch (InjectionProviderException ex)
737 {
738 log.log(Level.INFO, "Exception on PreDestroy", ex);
739 }
740 }
741 injectedBeanStorage.clear();
742 }
743 }
744 }