1
18
19 package io.undertow.servlet.core;
20
21 import io.undertow.Handlers;
22 import io.undertow.predicate.Predicates;
23 import io.undertow.security.api.AuthenticationMechanism;
24 import io.undertow.security.api.AuthenticationMechanismFactory;
25 import io.undertow.security.api.NotificationReceiver;
26 import io.undertow.security.api.SecurityContextFactory;
27 import io.undertow.security.handlers.AuthenticationMechanismsHandler;
28 import io.undertow.security.handlers.NotificationReceiverHandler;
29 import io.undertow.security.handlers.SecurityInitialHandler;
30 import io.undertow.security.idm.IdentityManager;
31 import io.undertow.security.impl.BasicAuthenticationMechanism;
32 import io.undertow.security.impl.CachedAuthenticatedSessionMechanism;
33 import io.undertow.security.impl.ClientCertAuthenticationMechanism;
34 import io.undertow.security.impl.DigestAuthenticationMechanism;
35 import io.undertow.security.impl.ExternalAuthenticationMechanism;
36 import io.undertow.security.impl.GenericHeaderAuthenticationMechanism;
37 import io.undertow.security.impl.SecurityContextFactoryImpl;
38 import io.undertow.server.HandlerWrapper;
39 import io.undertow.server.HttpHandler;
40 import io.undertow.server.HttpServerExchange;
41 import io.undertow.server.handlers.HttpContinueReadHandler;
42 import io.undertow.server.handlers.PredicateHandler;
43 import io.undertow.server.handlers.form.FormEncodedDataDefinition;
44 import io.undertow.server.handlers.form.FormParserFactory;
45 import io.undertow.server.session.SessionListener;
46 import io.undertow.server.session.SessionManager;
47 import io.undertow.servlet.ServletExtension;
48 import io.undertow.servlet.UndertowServletLogger;
49 import io.undertow.servlet.UndertowServletMessages;
50 import io.undertow.servlet.api.AuthMethodConfig;
51 import io.undertow.servlet.api.Deployment;
52 import io.undertow.servlet.api.DeploymentInfo;
53 import io.undertow.servlet.api.DeploymentManager;
54 import io.undertow.servlet.api.ErrorPage;
55 import io.undertow.servlet.api.FilterInfo;
56 import io.undertow.servlet.api.HttpMethodSecurityInfo;
57 import io.undertow.servlet.api.InstanceHandle;
58 import io.undertow.servlet.api.ListenerInfo;
59 import io.undertow.servlet.api.LoginConfig;
60 import io.undertow.servlet.api.MetricsCollector;
61 import io.undertow.servlet.api.MimeMapping;
62 import io.undertow.servlet.api.SecurityConstraint;
63 import io.undertow.servlet.api.SecurityInfo.EmptyRoleSemantic;
64 import io.undertow.servlet.api.ServletContainer;
65 import io.undertow.servlet.api.ServletContainerInitializerInfo;
66 import io.undertow.servlet.api.ServletInfo;
67 import io.undertow.servlet.api.ServletSecurityInfo;
68 import io.undertow.servlet.api.ServletSessionConfig;
69 import io.undertow.servlet.api.ServletStackTraces;
70 import io.undertow.servlet.api.SessionPersistenceManager;
71 import io.undertow.servlet.api.ThreadSetupHandler;
72 import io.undertow.servlet.api.WebResourceCollection;
73 import io.undertow.servlet.handlers.CrawlerSessionManagerHandler;
74 import io.undertow.servlet.handlers.RedirectDirHandler;
75 import io.undertow.servlet.handlers.ServletDispatchingHandler;
76 import io.undertow.servlet.handlers.ServletHandler;
77 import io.undertow.servlet.handlers.ServletInitialHandler;
78 import io.undertow.servlet.handlers.SessionRestoringHandler;
79 import io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler;
80 import io.undertow.servlet.handlers.security.SSLInformationAssociationHandler;
81 import io.undertow.servlet.handlers.security.SecurityPathMatches;
82 import io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler;
83 import io.undertow.servlet.handlers.security.ServletAuthenticationConstraintHandler;
84 import io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler;
85 import io.undertow.servlet.handlers.security.ServletFormAuthenticationMechanism;
86 import io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler;
87 import io.undertow.servlet.predicate.DispatcherTypePredicate;
88 import io.undertow.servlet.spec.ServletContextImpl;
89 import io.undertow.servlet.spec.SessionCookieConfigImpl;
90 import io.undertow.util.MimeMappings;
91
92 import javax.servlet.ServletContainerInitializer;
93 import javax.servlet.ServletContext;
94 import javax.servlet.ServletContextEvent;
95 import javax.servlet.ServletContextListener;
96 import javax.servlet.ServletException;
97 import java.io.File;
98 import java.nio.charset.Charset;
99 import java.util.ArrayList;
100 import java.util.Collections;
101 import java.util.HashMap;
102 import java.util.HashSet;
103 import java.util.LinkedList;
104 import java.util.List;
105 import java.util.Locale;
106 import java.util.Map;
107 import java.util.ServiceLoader;
108 import java.util.Set;
109 import java.util.TreeMap;
110
111 import static javax.servlet.http.HttpServletRequest.BASIC_AUTH;
112 import static javax.servlet.http.HttpServletRequest.CLIENT_CERT_AUTH;
113 import static javax.servlet.http.HttpServletRequest.DIGEST_AUTH;
114 import static javax.servlet.http.HttpServletRequest.FORM_AUTH;
115
116
121 public class DeploymentManagerImpl implements DeploymentManager {
122
123
126 private final DeploymentInfo originalDeployment;
127
128 private final ServletContainer servletContainer;
129
130
133 private volatile DeploymentImpl deployment;
134 private volatile State state = State.UNDEPLOYED;
135
136 public DeploymentManagerImpl(final DeploymentInfo deployment, final ServletContainer servletContainer) {
137 this.originalDeployment = deployment;
138 this.servletContainer = servletContainer;
139 }
140
141 @Override
142 public void deploy() {
143 final DeploymentInfo deploymentInfo = originalDeployment.clone();
144
145 if (deploymentInfo.getServletStackTraces() == ServletStackTraces.ALL) {
146 UndertowServletLogger.REQUEST_LOGGER.servletStackTracesAll(deploymentInfo.getDeploymentName());
147 }
148
149 deploymentInfo.validate();
150 final DeploymentImpl deployment = new DeploymentImpl(this, deploymentInfo, servletContainer);
151 this.deployment = deployment;
152
153 final ServletContextImpl servletContext = new ServletContextImpl(servletContainer, deployment);
154 deployment.setServletContext(servletContext);
155 handleExtensions(deploymentInfo, servletContext);
156
157 final List<ThreadSetupHandler> setup = new ArrayList<>();
158 setup.add(ServletRequestContextThreadSetupAction.INSTANCE);
159 setup.add(new ContextClassLoaderSetupAction(deploymentInfo.getClassLoader()));
160 setup.addAll(deploymentInfo.getThreadSetupActions());
161 deployment.setThreadSetupActions(setup);
162
163 deployment.getServletPaths().setWelcomePages(deploymentInfo.getWelcomePages());
164
165 if (deploymentInfo.getDefaultEncoding() != null) {
166 deployment.setDefaultCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));
167 }
168 if(deploymentInfo.getDefaultRequestEncoding() != null) {
169 deployment.setDefaultRequestCharset(Charset.forName(deploymentInfo.getDefaultRequestEncoding()));
170 } else if (deploymentInfo.getDefaultEncoding() != null) {
171 deployment.setDefaultRequestCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));
172 }
173 if(deploymentInfo.getDefaultResponseEncoding() != null) {
174 deployment.setDefaultResponseCharset(Charset.forName(deploymentInfo.getDefaultResponseEncoding()));
175 } else if (deploymentInfo.getDefaultEncoding() != null) {
176 deployment.setDefaultResponseCharset(Charset.forName(deploymentInfo.getDefaultEncoding()));
177 }
178
179 handleDeploymentSessionConfig(deploymentInfo, servletContext);
180
181 deployment.setSessionManager(deploymentInfo.getSessionManagerFactory().createSessionManager(deployment));
182 deployment.getSessionManager().setDefaultSessionTimeout(deploymentInfo.getDefaultSessionTimeout());
183
184
185 try {
186 deployment.createThreadSetupAction(new ThreadSetupHandler.Action<Void, Object>() {
187 @Override
188 public Void call(HttpServerExchange exchange, Object ignore) throws Exception {
189 final ApplicationListeners listeners = createListeners();
190 listeners.start();
191
192 deployment.setApplicationListeners(listeners);
193
194
195 createServletsAndFilters(deployment, deploymentInfo);
196
197
198 initializeTempDir(servletContext, deploymentInfo);
199
200
201 for (final ServletContainerInitializerInfo sci : deploymentInfo.getServletContainerInitializers()) {
202 final InstanceHandle<? extends ServletContainerInitializer> instance = sci.getInstanceFactory().createInstance();
203 try {
204 instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext);
205 } finally {
206 instance.release();
207 }
208 }
209
210 deployment.getSessionManager().registerSessionListener(new SessionListenerBridge(deployment, listeners, servletContext));
211 for(SessionListener listener : deploymentInfo.getSessionListeners()) {
212 deployment.getSessionManager().registerSessionListener(listener);
213 }
214
215 initializeErrorPages(deployment, deploymentInfo);
216 initializeMimeMappings(deployment, deploymentInfo);
217 listeners.contextInitialized();
218
219
220 HttpHandler wrappedHandlers = ServletDispatchingHandler.INSTANCE;
221 wrappedHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getInnerHandlerChainWrappers());
222 wrappedHandlers = new RedirectDirHandler(wrappedHandlers, deployment.getServletPaths());
223 if(!deploymentInfo.isSecurityDisabled()) {
224 HttpHandler securityHandler = setupSecurityHandlers(wrappedHandlers);
225 wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, securityHandler, wrappedHandlers);
226 }
227 HttpHandler outerHandlers = wrapHandlers(wrappedHandlers, deploymentInfo.getOuterHandlerChainWrappers());
228 wrappedHandlers = new PredicateHandler(DispatcherTypePredicate.REQUEST, outerHandlers, wrappedHandlers);
229 wrappedHandlers = handleDevelopmentModePersistentSessions(wrappedHandlers, deploymentInfo, deployment.getSessionManager(), servletContext);
230
231 MetricsCollector metrics = deploymentInfo.getMetricsCollector();
232 if(metrics != null) {
233 wrappedHandlers = new MetricsChainHandler(wrappedHandlers, metrics, deployment);
234 }
235 if( deploymentInfo.getCrawlerSessionManagerConfig() != null ) {
236 wrappedHandlers = new CrawlerSessionManagerHandler(deploymentInfo.getCrawlerSessionManagerConfig(), wrappedHandlers);
237 }
238
239 final ServletInitialHandler servletInitialHandler = SecurityActions.createServletInitialHandler(deployment.getServletPaths(), wrappedHandlers, deployment, servletContext);
240
241 HttpHandler initialHandler = wrapHandlers(servletInitialHandler, deployment.getDeploymentInfo().getInitialHandlerChainWrappers());
242 initialHandler = new HttpContinueReadHandler(initialHandler);
243 if(deploymentInfo.getUrlEncoding() != null) {
244 initialHandler = Handlers.urlDecodingHandler(deploymentInfo.getUrlEncoding(), initialHandler);
245 }
246 deployment.setInitialHandler(initialHandler);
247 deployment.setServletHandler(servletInitialHandler);
248 deployment.getServletPaths().invalidate();
249 servletContext.initDone();
250 return null;
251 }
252 }).call(null, null);
253 } catch (Exception e) {
254 throw new RuntimeException(e);
255 }
256
257
258 deployment.getServletPaths().initData();
259 for(ServletContextListener listener : deploymentInfo.getDeploymentCompleteListeners()) {
260 listener.contextInitialized(new ServletContextEvent(servletContext));
261 }
262 state = State.DEPLOYED;
263 }
264
265 private void createServletsAndFilters(final DeploymentImpl deployment, final DeploymentInfo deploymentInfo) {
266 for (Map.Entry<String, ServletInfo> servlet : deploymentInfo.getServlets().entrySet()) {
267 deployment.getServlets().addServlet(servlet.getValue());
268 }
269 for (Map.Entry<String, FilterInfo> filter : deploymentInfo.getFilters().entrySet()) {
270 deployment.getFilters().addFilter(filter.getValue());
271 }
272 }
273
274 private void handleExtensions(final DeploymentInfo deploymentInfo, final ServletContextImpl servletContext) {
275 Set<String> loadedExtensions = new HashSet<>();
276
277 for (ServletExtension extension : ServiceLoader.load(ServletExtension.class, deploymentInfo.getClassLoader())) {
278 loadedExtensions.add(extension.getClass().getName());
279 extension.handleDeployment(deploymentInfo, servletContext);
280 }
281
282 if (ServletExtension.class.getClassLoader() != null && !ServletExtension.class.getClassLoader().equals(deploymentInfo.getClassLoader())) {
283 for (ServletExtension extension : ServiceLoader.load(ServletExtension.class)) {
284
285
286
287
288 if (!loadedExtensions.contains(extension.getClass().getName())) {
289 extension.handleDeployment(deploymentInfo, servletContext);
290 }
291 }
292 }
293
294 for (ServletExtension extension : ServletExtensionHolder.getServletExtensions()) {
295 if (!loadedExtensions.contains(extension.getClass().getName())) {
296 extension.handleDeployment(deploymentInfo, servletContext);
297 }
298 }
299
300 for(ServletExtension extension : deploymentInfo.getServletExtensions()) {
301 extension.handleDeployment(deploymentInfo, servletContext);
302 }
303 }
304
305
312 private HttpHandler setupSecurityHandlers(HttpHandler initialHandler) {
313 final DeploymentInfo deploymentInfo = deployment.getDeploymentInfo();
314 final LoginConfig loginConfig = deploymentInfo.getLoginConfig();
315
316 HttpHandler current = initialHandler;
317 current = new SSLInformationAssociationHandler(current);
318
319 final SecurityPathMatches securityPathMatches = buildSecurityConstraints();
320 securityPathMatches.logWarningsAboutUncoveredMethods();
321 current = new ServletAuthenticationCallHandler(current);
322
323 for(HandlerWrapper wrapper : deploymentInfo.getSecurityWrappers()) {
324 current = wrapper.wrap(current);
325 }
326
327 if(deploymentInfo.isDisableCachingForSecuredPages()) {
328 current = Handlers.predicate(Predicates.authRequired(), Handlers.disableCache(current), current);
329 }
330 if (!securityPathMatches.isEmpty()) {
331 current = new ServletAuthenticationConstraintHandler(current);
332 }
333 current = new ServletConfidentialityConstraintHandler(deploymentInfo.getConfidentialPortManager(), current);
334 if (!securityPathMatches.isEmpty()) {
335 current = new ServletSecurityConstraintHandler(securityPathMatches, current);
336 }
337
338 HandlerWrapper initialSecurityWrapper = deploymentInfo.getInitialSecurityWrapper();
339
340 String mechName = null;
341 if (initialSecurityWrapper == null) {
342 final Map<String, AuthenticationMechanismFactory> factoryMap = new HashMap<>(deploymentInfo.getAuthenticationMechanisms());
343 final IdentityManager identityManager = deploymentInfo.getIdentityManager();
344 if(!factoryMap.containsKey(BASIC_AUTH)) {
345 factoryMap.put(BASIC_AUTH, BasicAuthenticationMechanism.FACTORY);
346 }
347 if(!factoryMap.containsKey(FORM_AUTH)) {
348 factoryMap.put(FORM_AUTH, ServletFormAuthenticationMechanism.FACTORY);
349 }
350 if(!factoryMap.containsKey(DIGEST_AUTH)) {
351 factoryMap.put(DIGEST_AUTH, DigestAuthenticationMechanism.FACTORY);
352 }
353 if(!factoryMap.containsKey(CLIENT_CERT_AUTH)) {
354 factoryMap.put(CLIENT_CERT_AUTH, ClientCertAuthenticationMechanism.FACTORY);
355 }
356 if(!factoryMap.containsKey(ExternalAuthenticationMechanism.NAME)) {
357 factoryMap.put(ExternalAuthenticationMechanism.NAME, ExternalAuthenticationMechanism.FACTORY);
358 }
359 if(!factoryMap.containsKey(GenericHeaderAuthenticationMechanism.NAME)) {
360 factoryMap.put(GenericHeaderAuthenticationMechanism.NAME, GenericHeaderAuthenticationMechanism.FACTORY);
361 }
362 List<AuthenticationMechanism> authenticationMechanisms = new LinkedList<>();
363
364 if(deploymentInfo.isUseCachedAuthenticationMechanism()) {
365 authenticationMechanisms.add(new CachedAuthenticatedSessionMechanism(identityManager));
366 }
367 if (loginConfig != null || deploymentInfo.getJaspiAuthenticationMechanism() != null) {
368
369
370 FormEncodedDataDefinition formEncodedDataDefinition = new FormEncodedDataDefinition();
371 String reqEncoding = deploymentInfo.getDefaultRequestEncoding();
372 if(reqEncoding == null) {
373 reqEncoding = deploymentInfo.getDefaultEncoding();
374 }
375 if (reqEncoding != null) {
376 formEncodedDataDefinition.setDefaultEncoding(reqEncoding);
377 }
378 FormParserFactory parser = FormParserFactory.builder(false)
379 .addParser(formEncodedDataDefinition)
380 .build();
381
382 List<AuthMethodConfig> authMethods = Collections.<AuthMethodConfig>emptyList();
383 if(loginConfig != null) {
384 authMethods = loginConfig.getAuthMethods();
385 }
386
387 for(AuthMethodConfig method : authMethods) {
388 AuthenticationMechanismFactory factory = factoryMap.get(method.getName());
389 if(factory == null) {
390 throw UndertowServletMessages.MESSAGES.unknownAuthenticationMechanism(method.getName());
391 }
392 if(mechName == null) {
393 mechName = method.getName();
394 }
395
396 final Map<String, String> properties = new HashMap<>();
397 properties.put(AuthenticationMechanismFactory.CONTEXT_PATH, deploymentInfo.getContextPath());
398 properties.put(AuthenticationMechanismFactory.REALM, loginConfig.getRealmName());
399 properties.put(AuthenticationMechanismFactory.ERROR_PAGE, loginConfig.getErrorPage());
400 properties.put(AuthenticationMechanismFactory.LOGIN_PAGE, loginConfig.getLoginPage());
401 properties.putAll(method.getProperties());
402
403 String name = method.getName().toUpperCase(Locale.US);
404
405
406 name = name.equals(FORM_AUTH) ? FORM_AUTH : name;
407 name = name.equals(BASIC_AUTH) ? BASIC_AUTH : name;
408 name = name.equals(DIGEST_AUTH) ? DIGEST_AUTH : name;
409 name = name.equals(CLIENT_CERT_AUTH) ? CLIENT_CERT_AUTH : name;
410
411 authenticationMechanisms.add(factory.create(name, identityManager, parser, properties));
412 }
413 }
414
415
416 deployment.setAuthenticationMechanisms(authenticationMechanisms);
417
418 if(deploymentInfo.getJaspiAuthenticationMechanism() == null) {
419 current = new AuthenticationMechanismsHandler(current, authenticationMechanisms);
420 } else {
421 current = new AuthenticationMechanismsHandler(current, Collections.<AuthenticationMechanism>singletonList(deploymentInfo.getJaspiAuthenticationMechanism()));
422 }
423
424 current = new CachedAuthenticatedSessionHandler(current, this.deployment.getServletContext());
425 }
426
427 List<NotificationReceiver> notificationReceivers = deploymentInfo.getNotificationReceivers();
428 if (!notificationReceivers.isEmpty()) {
429 current = new NotificationReceiverHandler(current, notificationReceivers);
430 }
431
432 if (initialSecurityWrapper == null) {
433
434
435 SecurityContextFactory contextFactory = deploymentInfo.getSecurityContextFactory();
436 if (contextFactory == null) {
437 contextFactory = SecurityContextFactoryImpl.INSTANCE;
438 }
439 current = new SecurityInitialHandler(deploymentInfo.getAuthenticationMode(), deploymentInfo.getIdentityManager(), mechName,
440 contextFactory, current);
441 } else {
442 current = initialSecurityWrapper.wrap(current);
443 }
444
445 return current;
446 }
447
448 private SecurityPathMatches buildSecurityConstraints() {
449 SecurityPathMatches.Builder builder = SecurityPathMatches.builder(deployment.getDeploymentInfo());
450 final Set<String> urlPatterns = new HashSet<>();
451 for (SecurityConstraint constraint : deployment.getDeploymentInfo().getSecurityConstraints()) {
452 builder.addSecurityConstraint(constraint);
453 for (WebResourceCollection webResources : constraint.getWebResourceCollections()) {
454 urlPatterns.addAll(webResources.getUrlPatterns());
455 }
456 }
457
458 for (final ServletInfo servlet : deployment.getDeploymentInfo().getServlets().values()) {
459 final ServletSecurityInfo securityInfo = servlet.getServletSecurityInfo();
460 if (securityInfo != null) {
461 final Set<String> mappings = new HashSet<>(servlet.getMappings());
462 mappings.removeAll(urlPatterns);
463 if (!mappings.isEmpty()) {
464 final Set<String> methods = new HashSet<>();
465
466 for (HttpMethodSecurityInfo method : securityInfo.getHttpMethodSecurityInfo()) {
467 methods.add(method.getMethod());
468 if (method.getRolesAllowed().isEmpty() && method.getEmptyRoleSemantic() == EmptyRoleSemantic.PERMIT) {
469
470 continue;
471 }
472 SecurityConstraint newConstraint = new SecurityConstraint()
473 .addRolesAllowed(method.getRolesAllowed())
474 .setTransportGuaranteeType(method.getTransportGuaranteeType())
475 .addWebResourceCollection(new WebResourceCollection().addUrlPatterns(mappings)
476 .addHttpMethod(method.getMethod()));
477 builder.addSecurityConstraint(newConstraint);
478 }
479
480 if (!securityInfo.getRolesAllowed().isEmpty()
481 || securityInfo.getEmptyRoleSemantic() != EmptyRoleSemantic.PERMIT
482 || methods.isEmpty()) {
483 SecurityConstraint newConstraint = new SecurityConstraint()
484 .setEmptyRoleSemantic(securityInfo.getEmptyRoleSemantic())
485 .addRolesAllowed(securityInfo.getRolesAllowed())
486 .setTransportGuaranteeType(securityInfo.getTransportGuaranteeType())
487 .addWebResourceCollection(new WebResourceCollection().addUrlPatterns(mappings)
488 .addHttpMethodOmissions(methods));
489 builder.addSecurityConstraint(newConstraint);
490 }
491 }
492
493 }
494 }
495
496 return builder.build();
497 }
498
499 private void initializeTempDir(final ServletContextImpl servletContext, final DeploymentInfo deploymentInfo) {
500 if (deploymentInfo.getTempDir() != null) {
501 servletContext.setAttribute(ServletContext.TEMPDIR, deploymentInfo.getTempDir());
502 } else {
503 servletContext.setAttribute(ServletContext.TEMPDIR, new File(SecurityActions.getSystemProperty("java.io.tmpdir")));
504 }
505 }
506
507 private void initializeMimeMappings(final DeploymentImpl deployment, final DeploymentInfo deploymentInfo) {
508 final Map<String, String> mappings = new HashMap<>(MimeMappings.DEFAULT_MIME_MAPPINGS);
509 for (MimeMapping mapping : deploymentInfo.getMimeMappings()) {
510 mappings.put(mapping.getExtension().toLowerCase(Locale.ENGLISH), mapping.getMimeType());
511 }
512 deployment.setMimeExtensionMappings(mappings);
513 }
514
515 private void initializeErrorPages(final DeploymentImpl deployment, final DeploymentInfo deploymentInfo) {
516 final Map<Integer, String> codes = new HashMap<>();
517 final Map<Class<? extends Throwable>, String> exceptions = new HashMap<>();
518 String defaultErrorPage = null;
519 for (final ErrorPage page : deploymentInfo.getErrorPages()) {
520 if (page.getExceptionType() != null) {
521 exceptions.put(page.getExceptionType(), page.getLocation());
522 } else if (page.getErrorCode() != null) {
523 codes.put(page.getErrorCode(), page.getLocation());
524 } else {
525 if (defaultErrorPage != null) {
526 throw UndertowServletMessages.MESSAGES.moreThanOneDefaultErrorPage(defaultErrorPage, page.getLocation());
527 } else {
528 defaultErrorPage = page.getLocation();
529 }
530 }
531 }
532 deployment.setErrorPages(new ErrorPages(codes, exceptions, defaultErrorPage));
533 }
534
535
536 private ApplicationListeners createListeners() {
537 final List<ManagedListener> managedListeners = new ArrayList<>();
538 for (final ListenerInfo listener : deployment.getDeploymentInfo().getListeners()) {
539 managedListeners.add(new ManagedListener(listener, listener.isProgramatic()));
540 }
541 return new ApplicationListeners(managedListeners, deployment.getServletContext());
542 }
543
544
545 private static HttpHandler wrapHandlers(final HttpHandler wrapee, final List<HandlerWrapper> wrappers) {
546 HttpHandler current = wrapee;
547 for (HandlerWrapper wrapper : wrappers) {
548 current = wrapper.wrap(current);
549 }
550 return current;
551 }
552
553 @Override
554 public HttpHandler start() throws ServletException {
555 try {
556 return deployment.createThreadSetupAction(new ThreadSetupHandler.Action<HttpHandler, Object>() {
557 @Override
558 public HttpHandler call(HttpServerExchange exchange, Object ignore) throws ServletException {
559 deployment.getSessionManager().start();
560
561
562
563 ArrayList<Lifecycle> lifecycles = new ArrayList<>(deployment.getLifecycleObjects());
564 for (Lifecycle object : lifecycles) {
565 object.start();
566 }
567 HttpHandler root = deployment.getHandler();
568 final TreeMap<Integer, List<ManagedServlet>> loadOnStartup = new TreeMap<>();
569 for (Map.Entry<String, ServletHandler> entry : deployment.getServlets().getServletHandlers().entrySet()) {
570 ManagedServlet servlet = entry.getValue().getManagedServlet();
571 Integer loadOnStartupNumber = servlet.getServletInfo().getLoadOnStartup();
572 if (loadOnStartupNumber != null) {
573 if (loadOnStartupNumber < 0) {
574 continue;
575 }
576 List<ManagedServlet> list = loadOnStartup.get(loadOnStartupNumber);
577 if (list == null) {
578 loadOnStartup.put(loadOnStartupNumber, list = new ArrayList<>());
579 }
580 list.add(servlet);
581 }
582 }
583 for (Map.Entry<Integer, List<ManagedServlet>> load : loadOnStartup.entrySet()) {
584 for (ManagedServlet servlet : load.getValue()) {
585 servlet.createServlet();
586 }
587 }
588
589 if (deployment.getDeploymentInfo().isEagerFilterInit()) {
590 for (ManagedFilter filter : deployment.getFilters().getFilters().values()) {
591 filter.createFilter();
592 }
593 }
594
595 state = State.STARTED;
596 return root;
597 }
598 }).call(null, null);
599 } catch (ServletException|RuntimeException e) {
600 throw e;
601 } catch (Exception e) {
602 throw new RuntimeException(e);
603 }
604 }
605
606 @Override
607 public void stop() throws ServletException {
608 try {
609 deployment.createThreadSetupAction(new ThreadSetupHandler.Action<Void, Object>() {
610 @Override
611 public Void call(HttpServerExchange exchange, Object ignore) throws ServletException {
612 for (Lifecycle object : deployment.getLifecycleObjects()) {
613 try {
614 object.stop();
615 } catch (Throwable t) {
616 UndertowServletLogger.ROOT_LOGGER.failedToDestroy(object, t);
617 }
618 }
619 deployment.getSessionManager().stop();
620 state = State.DEPLOYED;
621 return null;
622 }
623 }).call(null, null);
624 } catch (ServletException|RuntimeException e) {
625 throw e;
626 } catch (Exception e) {
627 throw new RuntimeException(e);
628 }
629 }
630
631 private HttpHandler handleDevelopmentModePersistentSessions(HttpHandler next, final DeploymentInfo deploymentInfo, final SessionManager sessionManager, final ServletContextImpl servletContext) {
632 final SessionPersistenceManager sessionPersistenceManager = deploymentInfo.getSessionPersistenceManager();
633 if (sessionPersistenceManager != null) {
634 SessionRestoringHandler handler = new SessionRestoringHandler(deployment.getDeploymentInfo().getDeploymentName(), sessionManager, servletContext, next, sessionPersistenceManager);
635 deployment.addLifecycleObjects(handler);
636 return handler;
637 }
638 return next;
639 }
640
641 public void handleDeploymentSessionConfig(DeploymentInfo deploymentInfo, ServletContextImpl servletContext) {
642 SessionCookieConfigImpl sessionCookieConfig = servletContext.getSessionCookieConfig();
643 ServletSessionConfig sc = deploymentInfo.getServletSessionConfig();
644 if (sc != null) {
645 sessionCookieConfig.setName(sc.getName());
646 sessionCookieConfig.setComment(sc.getComment());
647 sessionCookieConfig.setDomain(sc.getDomain());
648 sessionCookieConfig.setHttpOnly(sc.isHttpOnly());
649 sessionCookieConfig.setMaxAge(sc.getMaxAge());
650 if(sc.getPath() != null) {
651 sessionCookieConfig.setPath(sc.getPath());
652 } else {
653 sessionCookieConfig.setPath(deploymentInfo.getContextPath());
654 }
655 sessionCookieConfig.setSecure(sc.isSecure());
656 if (sc.getSessionTrackingModes() != null) {
657 servletContext.setDefaultSessionTrackingModes(new HashSet<>(sc.getSessionTrackingModes()));
658 }
659 }
660 }
661
662
663 @Override
664 public void undeploy() {
665 try {
666 deployment.createThreadSetupAction(new ThreadSetupHandler.Action<Void, Object>() {
667 @Override
668 public Void call(HttpServerExchange exchange, Object ignore) throws ServletException {
669 for(ServletContextListener listener : deployment.getDeploymentInfo().getDeploymentCompleteListeners()) {
670 try {
671 listener.contextDestroyed(new ServletContextEvent(deployment.getServletContext()));
672 } catch (Throwable t) {
673 UndertowServletLogger.REQUEST_LOGGER.failedToDestroy(listener, t);
674 }
675 }
676 deployment.destroy();
677 deployment = null;
678 state = State.UNDEPLOYED;
679 return null;
680 }
681 }).call(null, null);
682 } catch (Exception e) {
683 throw new RuntimeException(e);
684 }
685
686 }
687
688 @Override
689 public State getState() {
690 return state;
691 }
692
693 @Override
694 public Deployment getDeployment() {
695 return deployment;
696 }
697
698 }
699