1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.ee;
20
21 import java.net.URL;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29
30 import javax.faces.application.ResourceDependencies;
31 import javax.faces.application.ResourceDependency;
32 import javax.faces.bean.ApplicationScoped;
33 import javax.faces.bean.CustomScoped;
34 import javax.faces.bean.ManagedBean;
35 import javax.faces.bean.ManagedProperty;
36 import javax.faces.bean.NoneScoped;
37 import javax.faces.bean.ReferencedBean;
38 import javax.faces.bean.RequestScoped;
39 import javax.faces.bean.SessionScoped;
40 import javax.faces.bean.ViewScoped;
41 import javax.faces.component.FacesComponent;
42 import javax.faces.component.UIComponent;
43 import javax.faces.component.behavior.FacesBehavior;
44 import javax.faces.context.ExternalContext;
45 import javax.faces.convert.Converter;
46 import javax.faces.convert.FacesConverter;
47 import javax.faces.event.ListenerFor;
48 import javax.faces.event.ListenersFor;
49 import javax.faces.event.NamedEvent;
50 import javax.faces.model.FacesDataModel;
51 import javax.faces.render.FacesBehaviorRenderer;
52 import javax.faces.render.FacesRenderer;
53 import javax.faces.render.Renderer;
54 import javax.faces.validator.FacesValidator;
55 import javax.faces.validator.Validator;
56 import javax.faces.webapp.FacesServlet;
57 import javax.servlet.Servlet;
58 import javax.servlet.ServletContainerInitializer;
59 import javax.servlet.ServletContext;
60 import javax.servlet.ServletException;
61 import javax.servlet.ServletRegistration;
62 import javax.servlet.annotation.HandlesTypes;
63 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
64
65 import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
66 import org.apache.myfaces.shared.config.MyfacesConfig;
67 import org.apache.myfaces.shared_impl.webapp.webxml.DelegatedFacesServlet;
68 import org.apache.myfaces.spi.FacesConfigResourceProvider;
69 import org.apache.myfaces.spi.FacesConfigResourceProviderFactory;
70 import org.apache.myfaces.webapp.ManagedBeanDestroyerListener;
71
72
73
74
75
76
77
78
79
80
81
82
83 @HandlesTypes({
84 ApplicationScoped.class,
85 CustomScoped.class,
86 FacesBehavior.class,
87 FacesBehaviorRenderer.class,
88 FacesComponent.class,
89 FacesConverter.class,
90 FacesRenderer.class,
91 FacesValidator.class,
92 FacesDataModel.class,
93 ListenerFor.class,
94 ListenersFor.class,
95 ManagedBean.class,
96 ManagedProperty.class,
97 NamedEvent.class,
98 NoneScoped.class,
99 ReferencedBean.class,
100 RequestScoped.class,
101 ResourceDependencies.class,
102 ResourceDependency.class,
103 SessionScoped.class,
104 ViewScoped.class,
105 UIComponent.class,
106 Converter.class,
107 Renderer.class,
108 Validator.class
109 })
110 public class MyFacesContainerInitializer implements ServletContainerInitializer
111 {
112
113
114
115
116
117 public static final String FACES_SERVLET_ADDED_ATTRIBUTE = "org.apache.myfaces.DYNAMICALLY_ADDED_FACES_SERVLET";
118
119
120
121
122
123 public static final String FACES_SERVLET_FOUND = "org.apache.myfaces.FACES_SERVLET_FOUND";
124
125 private static final String INITIALIZE_ALWAYS_STANDALONE = "org.apache.myfaces.INITIALIZE_ALWAYS_STANDALONE";
126
127
128
129
130
131
132 @JSFWebConfigParam(since="2.2.10", expectedValues = "true, false", defaultValue = "false",
133 tags = "performance")
134 private static final String INITIALIZE_SKIP_JAR_FACES_CONFIG_SCAN =
135 "org.apache.myfaces.INITIALIZE_SKIP_JAR_FACES_CONFIG_SCAN";
136
137 private static final String FACES_CONFIG_RESOURCE = "/WEB-INF/faces-config.xml";
138 private static final Logger log = Logger.getLogger(MyFacesContainerInitializer.class.getName());
139 private static final String[] FACES_SERVLET_MAPPINGS = { "/faces/*", "*.jsf", "*.faces" };
140 private static final String[] FACES_SERVLET_FULL_MAPPINGS = { "/faces/*", "*.jsf", "*.faces", "*.xhtml" };
141 private static final String FACES_SERVLET_NAME = "FacesServlet";
142 private static final Class<? extends Servlet> FACES_SERVLET_CLASS = FacesServlet.class;
143 private static final Class<?> DELEGATED_FACES_SERVLET_CLASS = DelegatedFacesServlet.class;
144
145 @Override
146 public void onStartup(Set<Class<?>> clazzes, ServletContext servletContext) throws ServletException
147 {
148 log.log(Level.INFO, "Using " + MyFacesContainerInitializer.class.getName());
149
150
151 String supportManagedBeans =
152 servletContext.getInitParameter(MyfacesConfig.INIT_PARAM_SUPPORT_MANAGED_BEANS);
153 if (supportManagedBeans == null || Boolean.TRUE.toString().equals(supportManagedBeans))
154 {
155 ManagedBeanDestroyerListener destroyListener = new ManagedBeanDestroyerListener();
156 servletContext.addListener(destroyListener);
157
158
159
160
161
162 servletContext.setAttribute(ManagedBeanDestroyerListener.APPLICATION_MAP_KEY, destroyListener);
163 }
164
165 boolean startDireclty = shouldStartupRegardless(servletContext);
166 if (startDireclty)
167 {
168
169
170
171 return;
172 }
173
174
175
176
177
178
179
180
181
182 if ((clazzes != null && !clazzes.isEmpty()) || isFacesConfigPresent(servletContext))
183 {
184
185 Map<String, ? extends ServletRegistration> servlets = servletContext.getServletRegistrations();
186 for (Map.Entry<String, ? extends ServletRegistration> servletEntry : servlets.entrySet())
187 {
188 String className = servletEntry.getValue().getClassName();
189 if (FACES_SERVLET_CLASS.getName().equals(className)
190 || isDelegatedFacesServlet(className))
191 {
192
193 servletContext.setAttribute(FACES_SERVLET_FOUND, Boolean.TRUE);
194 return;
195 }
196 }
197
198
199 ServletRegistration.Dynamic servlet = servletContext.addServlet(FACES_SERVLET_NAME, FACES_SERVLET_CLASS);
200
201
202 String[] mappings = isAutomaticXhtmlMappingDisabled(servletContext) ?
203 FACES_SERVLET_MAPPINGS : FACES_SERVLET_FULL_MAPPINGS;
204 Set<String> conflictMappings = servlet.addMapping(mappings);
205 if (conflictMappings != null && !conflictMappings.isEmpty())
206 {
207
208 Set<String> newMappings = new HashSet<String>(Arrays.asList(mappings));
209 newMappings.removeAll(conflictMappings);
210 mappings = newMappings.toArray(new String[newMappings.size()]);
211 servlet.addMapping(mappings);
212 }
213
214 if (mappings != null && mappings.length > 0)
215 {
216
217
218
219
220 servletContext.setAttribute(FACES_SERVLET_ADDED_ATTRIBUTE, Boolean.TRUE);
221
222
223 log.log(Level.INFO, "Added FacesServlet with mappings="
224 + Arrays.toString(mappings));
225 }
226 }
227 }
228
229
230
231
232
233
234 private boolean shouldStartupRegardless(ServletContext servletContext)
235 {
236 try
237 {
238 String standaloneStartup = servletContext.getInitParameter(INITIALIZE_ALWAYS_STANDALONE);
239
240
241 return "true".equalsIgnoreCase(standaloneStartup);
242 }
243 catch (Exception e)
244 {
245 return false;
246 }
247 }
248
249
250
251
252
253
254 private boolean shouldSkipJarFacesConfigScan(ServletContext servletContext)
255 {
256 try
257 {
258 String skipJarScan = servletContext.getInitParameter(INITIALIZE_SKIP_JAR_FACES_CONFIG_SCAN);
259
260 if (skipJarScan == null)
261 {
262 skipJarScan = System.getProperty(INITIALIZE_SKIP_JAR_FACES_CONFIG_SCAN);
263 }
264 return "true".equalsIgnoreCase(skipJarScan);
265 }
266 catch (Exception e)
267 {
268 return false;
269 }
270 }
271
272 private boolean isAutomaticXhtmlMappingDisabled(ServletContext servletContext)
273 {
274 try
275 {
276 String xhtmlMappingDisabled = servletContext.getInitParameter(
277 FacesServlet.DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME);
278
279 if (xhtmlMappingDisabled == null)
280 {
281 xhtmlMappingDisabled = "false";
282 }
283 return "true".equalsIgnoreCase(xhtmlMappingDisabled);
284 }
285 catch (Exception e)
286 {
287 return false;
288 }
289 }
290
291
292
293
294
295 private boolean isFacesConfigPresent(ServletContext servletContext)
296 {
297 try
298 {
299
300 if (servletContext.getResource(FACES_CONFIG_RESOURCE) != null)
301 {
302 return true;
303 }
304
305
306
307 String configFilesAttrValue = servletContext.getInitParameter(FacesServlet.CONFIG_FILES_ATTR);
308 if (configFilesAttrValue != null)
309 {
310 String[] configFiles = configFilesAttrValue.split(",");
311 for (String file : configFiles)
312 {
313 if (servletContext.getResource(file.trim()) != null)
314 {
315 return true;
316 }
317 }
318 }
319
320
321
322
323
324
325
326
327
328 if (!shouldSkipJarFacesConfigScan(servletContext))
329 {
330 ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, true);
331 FacesConfigResourceProviderFactory factory = FacesConfigResourceProviderFactory.
332 getFacesConfigResourceProviderFactory(externalContext);
333 FacesConfigResourceProvider provider = factory.createFacesConfigResourceProvider(externalContext);
334 Collection<URL> metaInfFacesConfigUrls = provider.getMetaInfConfigurationResources(externalContext);
335
336 if (metaInfFacesConfigUrls != null && !metaInfFacesConfigUrls.isEmpty())
337 {
338 return true;
339 }
340 }
341 return false;
342 }
343 catch (Exception e)
344 {
345 return false;
346 }
347 }
348
349
350
351
352
353
354 private boolean isDelegatedFacesServlet(String className)
355 {
356 if (className == null)
357 {
358
359
360
361 return false;
362 }
363 try
364 {
365 Class<?> clazz = Class.forName(className);
366 return DELEGATED_FACES_SERVLET_CLASS.isAssignableFrom(clazz);
367 }
368 catch (ClassNotFoundException cnfe)
369 {
370 return false;
371 }
372 }
373 }