io.undertow.servlet.api.DeploymentInfo Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.undertow.servlet.api;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.descriptor.JspConfigDescriptor;
import io.undertow.security.api.AuthenticationMechanism;
import io.undertow.security.api.AuthenticationMechanismFactory;
import io.undertow.security.api.AuthenticationMode;
import io.undertow.security.api.NotificationReceiver;
import io.undertow.security.api.SecurityContextFactory;
import io.undertow.security.idm.IdentityManager;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.handlers.resource.ResourceManager;
import io.undertow.server.session.SecureRandomSessionIdGenerator;
import io.undertow.server.session.SessionIdGenerator;
import io.undertow.server.session.SessionListener;
import io.undertow.servlet.ServletExtension;
import io.undertow.servlet.UndertowServletMessages;
import io.undertow.servlet.core.DefaultAuthorizationManager;
import io.undertow.servlet.core.InMemorySessionManagerFactory;
import io.undertow.servlet.util.DefaultClassIntrospector;
import io.undertow.util.ImmediateAuthenticationMechanismFactory;
/**
* Represents a servlet deployment.
*
* @author Stuart Douglas
*/
public class DeploymentInfo implements Cloneable {
private static final int DEFAULT_MAJOR_VERSION = 6;
private String deploymentName;
private String displayName;
private String contextPath;
private ClassLoader classLoader;
private ResourceManager resourceManager = ResourceManager.EMPTY_RESOURCE_MANAGER;
private ClassIntrospecter classIntrospecter = DefaultClassIntrospector.INSTANCE;
private int majorVersion = DEFAULT_MAJOR_VERSION;
private int minorVersion = 0;
private int containerMajorVersion = DEFAULT_MAJOR_VERSION;
private int containerMinorVersion = 0;
private Executor executor;
private Executor asyncExecutor;
private Path tempDir;
private JspConfigDescriptor jspConfigDescriptor;
private DefaultServletConfig defaultServletConfig;
private SessionManagerFactory sessionManagerFactory = new InMemorySessionManagerFactory();
private LoginConfig loginConfig;
private IdentityManager identityManager;
private ConfidentialPortManager confidentialPortManager;
private boolean allowNonStandardWrappers = false;
private int defaultSessionTimeout = 60 * 30;
private ConcurrentMap servletContextAttributeBackingMap;
private ServletSessionConfig servletSessionConfig;
private String hostName = "localhost";
private boolean denyUncoveredHttpMethods = false;
private ServletStackTraces servletStackTraces = ServletStackTraces.LOCAL_ONLY;
private boolean invalidateSessionOnLogout = false;
private int defaultCookieVersion = 0;
private SessionPersistenceManager sessionPersistenceManager;
private String defaultEncoding;
private String defaultRequestEncoding;
private String defaultResponseEncoding;
private String urlEncoding = null;
private boolean ignoreFlush = false;
private AuthorizationManager authorizationManager = DefaultAuthorizationManager.INSTANCE;
private AuthenticationMechanism jaspiAuthenticationMechanism;
private SecurityContextFactory securityContextFactory;
private String serverName = "Undertow";
private MetricsCollector metricsCollector = null;
private SessionConfigWrapper sessionConfigWrapper = null;
private boolean eagerFilterInit = false;
private boolean disableCachingForSecuredPages = true;
private boolean escapeErrorMessage = true;
private boolean sendCustomReasonPhraseOnError = false;
private boolean useCachedAuthenticationMechanism = true;
private boolean preservePathOnForward = true;
private boolean allowOrphanSession = false;
private AuthenticationMode authenticationMode = AuthenticationMode.PRO_ACTIVE;
private ExceptionHandler exceptionHandler;
private final Map servlets = new HashMap<>();
private final Map filters = new HashMap<>();
private final List filterServletNameMappings = new ArrayList<>();
private final List filterUrlMappings = new ArrayList<>();
private final List listeners = new ArrayList<>();
private final List servletContainerInitializers = new ArrayList<>();
private final List threadSetupActions = new ArrayList<>();
private final Map initParameters = new HashMap<>();
private final Map servletContextAttributes = new HashMap<>();
private final Map localeCharsetMapping = new HashMap<>();
private final List welcomePages = new ArrayList<>();
private final List errorPages = new ArrayList<>();
private final List mimeMappings = new ArrayList<>();
private final List securityConstraints = new ArrayList<>();
private final Set securityRoles = new HashSet<>();
private final List notificationReceivers = new ArrayList<>();
private final Map authenticationMechanisms = new HashMap<>();
private final List lifecycleInterceptors = new ArrayList<>();
private final List sessionListeners = new ArrayList<>();
/**
* additional servlet extensions
*/
private final List servletExtensions = new ArrayList<>();
/**
* map of additional roles that should be applied to the given principal.
*/
private final Map> principalVersusRolesMap = new HashMap<>();
/**
* Wrappers that are applied before the servlet initial handler, and before any servlet related object have been
* created. If a wrapper wants to bypass servlet entirely it should register itself here.
*/
private final List initialHandlerChainWrappers = new ArrayList<>();
/**
* Handler chain wrappers that are applied outside all other handlers, including security but after the initial
* servlet handler.
*/
private final List outerHandlerChainWrappers = new ArrayList<>();
/**
* Handler chain wrappers that are applied just before the servlet request is dispatched. At this point the security
* handlers have run, and any security information is attached to the request.
*/
private final List innerHandlerChainWrappers = new ArrayList<>();
/**
* A handler chain wrapper to wrap the initial stages of the security handlers, if this is set it is assumed it
* is taking over the responsibility of setting the {@link io.undertow.security.api.SecurityContext} that can handle authentication and the
* remaining Undertow handlers specific to authentication will be skipped.
*/
private HandlerWrapper initialSecurityWrapper = null;
/**
* Handler chain wrappers that are applied just before the authentication mechanism is called. Theses handlers are
* always called, even if authentication is not required
*/
private final List securityWrappers = new ArrayList<>();
/**
* Multipart config that will be applied to all servlets that do not have an explicit config
*/
private MultipartConfigElement defaultMultipartConfig;
/**
* Cache of common content types, to prevent allocations when parsing the charset
*/
private int contentTypeCacheSize = 100;
private boolean changeSessionIdOnLogin = true;
private SessionIdGenerator sessionIdGenerator = new SecureRandomSessionIdGenerator();
/**
* Config for the {@link io.undertow.servlet.handlers.CrawlerSessionManagerHandler}
*/
private CrawlerSessionManagerConfig crawlerSessionManagerConfig;
private boolean securityDisabled;
private boolean checkOtherSessionManagers = true;
private final List deploymentCompleteListeners = new ArrayList<>();
/**
* A map of content encoding to file extension for pre compressed resource (e.g. gzip -> .gz)
*/
private final Map preCompressedResources = new HashMap<>();
public void validate() {
if (deploymentName == null) {
throw UndertowServletMessages.MESSAGES.paramCannotBeNull("deploymentName");
}
if (contextPath == null) {
throw UndertowServletMessages.MESSAGES.paramCannotBeNull("contextName");
}
if (classLoader == null) {
throw UndertowServletMessages.MESSAGES.paramCannotBeNull("classLoader");
}
if (resourceManager == null) {
throw UndertowServletMessages.MESSAGES.paramCannotBeNull("resourceManager");
}
if (classIntrospecter == null) {
throw UndertowServletMessages.MESSAGES.paramCannotBeNull("classIntrospecter");
}
for (final ServletInfo servlet : this.servlets.values()) {
servlet.validate();
}
for (final FilterInfo filter : this.filters.values()) {
filter.validate();
}
for (FilterMappingInfo mapping : this.filterServletNameMappings) {
if (!this.filters.containsKey(mapping.getFilterName())) {
throw UndertowServletMessages.MESSAGES.filterNotFound(mapping.getFilterName(), mapping.getMappingType() + " - " + mapping.getMapping());
}
}
for (FilterMappingInfo mapping : this.filterUrlMappings) {
if (!this.filters.containsKey(mapping.getFilterName())) {
throw UndertowServletMessages.MESSAGES.filterNotFound(mapping.getFilterName(), mapping.getMappingType() + " - " + mapping.getMapping());
}
}
}
public String getDeploymentName() {
return deploymentName;
}
public DeploymentInfo setDeploymentName(final String deploymentName) {
this.deploymentName = deploymentName;
return this;
}
public String getDisplayName() {
return displayName;
}
public DeploymentInfo setDisplayName(final String displayName) {
this.displayName = displayName;
return this;
}
public String getContextPath() {
return contextPath;
}
public DeploymentInfo setContextPath(final String contextPath) {
if(contextPath != null && contextPath.isEmpty()) {
this.contextPath = "/"; //we represent the root context as / instead of "", but both work
} else {
this.contextPath = contextPath;
}
return this;
}
public ClassLoader getClassLoader() {
return classLoader;
}
public DeploymentInfo setClassLoader(final ClassLoader classLoader) {
this.classLoader = classLoader;
return this;
}
public ResourceManager getResourceManager() {
return resourceManager;
}
public DeploymentInfo setResourceManager(final ResourceManager resourceManager) {
this.resourceManager = resourceManager;
return this;
}
public ClassIntrospecter getClassIntrospecter() {
return classIntrospecter;
}
public DeploymentInfo setClassIntrospecter(final ClassIntrospecter classIntrospecter) {
this.classIntrospecter = classIntrospecter;
return this;
}
public boolean isAllowNonStandardWrappers() {
return allowNonStandardWrappers;
}
public DeploymentInfo setAllowNonStandardWrappers(final boolean allowNonStandardWrappers) {
this.allowNonStandardWrappers = allowNonStandardWrappers;
return this;
}
public int getDefaultSessionTimeout() {
return defaultSessionTimeout;
}
/**
* @param defaultSessionTimeout The default session timeout, in seconds
*/
public DeploymentInfo setDefaultSessionTimeout(final int defaultSessionTimeout) {
this.defaultSessionTimeout = defaultSessionTimeout;
return this;
}
public String getDefaultEncoding() {
return defaultEncoding;
}
/**
* Sets the default encoding that will be used for servlet responses
*
* @param defaultEncoding The default encoding
*/
public DeploymentInfo setDefaultEncoding(String defaultEncoding) {
this.defaultEncoding = defaultEncoding;
return this;
}
public String getUrlEncoding() {
return urlEncoding;
}
/**
* Sets the URL encoding. This will only take effect if the {@link io.undertow.UndertowOptions#DECODE_URL}
* parameter has been set to false. This allows multiple deployments in the same server to use a different URL encoding
*
* @param urlEncoding The encoding to use
*/
public DeploymentInfo setUrlEncoding(String urlEncoding) {
this.urlEncoding = urlEncoding;
return this;
}
public DeploymentInfo addServlet(final ServletInfo servlet) {
servlets.put(servlet.getName(), servlet);
return this;
}
public DeploymentInfo addServlets(final ServletInfo... servlets) {
for (final ServletInfo servlet : servlets) {
addServlet(servlet);
}
return this;
}
public DeploymentInfo addServlets(final Collection servlets) {
for (final ServletInfo servlet : servlets) {
addServlet(servlet);
}
return this;
}
public Map getServlets() {
return servlets;
}
public DeploymentInfo addFilter(final FilterInfo filter) {
filters.put(filter.getName(), filter);
return this;
}
public DeploymentInfo addFilters(final FilterInfo... filters) {
for (final FilterInfo filter : filters) {
addFilter(filter);
}
return this;
}
public DeploymentInfo addFilters(final Collection filters) {
for (final FilterInfo filter : filters) {
addFilter(filter);
}
return this;
}
public Map getFilters() {
return filters;
}
public DeploymentInfo addFilterUrlMapping(final String filterName, final String mapping, DispatcherType dispatcher) {
filterUrlMappings.add(new FilterMappingInfo(filterName, FilterMappingInfo.MappingType.URL, mapping, dispatcher));
return this;
}
public DeploymentInfo addFilterServletNameMapping(final String filterName, final String mapping, DispatcherType dispatcher) {
filterServletNameMappings.add(new FilterMappingInfo(filterName, FilterMappingInfo.MappingType.SERVLET, mapping, dispatcher));
return this;
}
public DeploymentInfo insertFilterUrlMapping(final int pos, final String filterName, final String mapping, DispatcherType dispatcher) {
filterUrlMappings.add(pos, new FilterMappingInfo(filterName, FilterMappingInfo.MappingType.URL, mapping, dispatcher));
return this;
}
public DeploymentInfo insertFilterServletNameMapping(final int pos, final String filterName, final String mapping, DispatcherType dispatcher) {
filterServletNameMappings.add(pos, new FilterMappingInfo(filterName, FilterMappingInfo.MappingType.SERVLET, mapping, dispatcher));
return this;
}
public List getFilterMappings() {
final ArrayList ret = new ArrayList<>(filterUrlMappings);
ret.addAll(filterServletNameMappings);
return ret;
}
public DeploymentInfo addListener(final ListenerInfo listener) {
listeners.add(listener);
return this;
}
public DeploymentInfo addListeners(final ListenerInfo... listeners) {
this.listeners.addAll(Arrays.asList(listeners));
return this;
}
public DeploymentInfo addListeners(final Collection listeners) {
this.listeners.addAll(listeners);
return this;
}
public List getListeners() {
return listeners;
}
public int getMajorVersion() {
return majorVersion;
}
public DeploymentInfo setMajorVersion(final int majorVersion) {
this.majorVersion = majorVersion;
return this;
}
public int getMinorVersion() {
return minorVersion;
}
public DeploymentInfo setMinorVersion(final int minorVersion) {
this.minorVersion = minorVersion;
return this;
}
public DeploymentInfo addServletContainerInitializer(final ServletContainerInitializerInfo servletContainerInitializer) {
servletContainerInitializers.add(servletContainerInitializer);
return this;
}
@Deprecated // UNDERTOW-1375 Method name is misspelled
public DeploymentInfo addServletContainerInitalizer(final ServletContainerInitializerInfo servletContainerInitializer) {
return addServletContainerInitializer(servletContainerInitializer);
}
public DeploymentInfo addServletContainerInitializers(final ServletContainerInitializerInfo... servletContainerInitializer) {
servletContainerInitializers.addAll(Arrays.asList(servletContainerInitializer));
return this;
}
@Deprecated // UNDERTOW-1375 Method name is misspelled
public DeploymentInfo addServletContainerInitalizers(final ServletContainerInitializerInfo... servletContainerInitializer) {
return addServletContainerInitializers(servletContainerInitializer);
}
public DeploymentInfo addServletContainerInitializers(final List servletContainerInitializer) {
servletContainerInitializers.addAll(servletContainerInitializer);
return this;
}
@Deprecated // UNDERTOW-1375 Method name is misspelled
public DeploymentInfo addServletContainerInitalizers(final List servletContainerInitializers) {
return addServletContainerInitializers(servletContainerInitializers);
}
public List getServletContainerInitializers() {
return servletContainerInitializers;
}
@Deprecated
public DeploymentInfo addThreadSetupAction(final ThreadSetupAction action) {
threadSetupActions.add(new LegacyThreadSetupActionWrapper(action));
return this;
}
public DeploymentInfo addThreadSetupAction(final ThreadSetupHandler action) {
threadSetupActions.add(action);
return this;
}
public List getThreadSetupActions() {
return threadSetupActions;
}
public boolean isEagerFilterInit() {
return eagerFilterInit;
}
public DeploymentInfo setEagerFilterInit(boolean eagerFilterInit) {
this.eagerFilterInit = eagerFilterInit;
return this;
}
public DeploymentInfo addInitParameter(final String name, final String value) {
initParameters.put(name, value);
return this;
}
public Map getInitParameters() {
return initParameters;
}
public DeploymentInfo addServletContextAttribute(final String name, final Object value) {
servletContextAttributes.put(name, value);
return this;
}
public Map getServletContextAttributes() {
return servletContextAttributes;
}
public DeploymentInfo addWelcomePage(final String welcomePage) {
this.welcomePages.add(welcomePage);
return this;
}
public DeploymentInfo addWelcomePages(final String... welcomePages) {
this.welcomePages.addAll(Arrays.asList(welcomePages));
return this;
}
public DeploymentInfo addWelcomePages(final Collection welcomePages) {
this.welcomePages.addAll(welcomePages);
return this;
}
public List getWelcomePages() {
return welcomePages;
}
public DeploymentInfo addErrorPage(final ErrorPage errorPage) {
this.errorPages.add(errorPage);
return this;
}
public DeploymentInfo addErrorPages(final ErrorPage... errorPages) {
this.errorPages.addAll(Arrays.asList(errorPages));
return this;
}
public DeploymentInfo addErrorPages(final Collection errorPages) {
this.errorPages.addAll(errorPages);
return this;
}
public List getErrorPages() {
return errorPages;
}
public DeploymentInfo addMimeMapping(final MimeMapping mimeMappings) {
this.mimeMappings.add(mimeMappings);
return this;
}
public DeploymentInfo addMimeMappings(final MimeMapping... mimeMappings) {
this.mimeMappings.addAll(Arrays.asList(mimeMappings));
return this;
}
public DeploymentInfo addMimeMappings(final Collection mimeMappings) {
this.mimeMappings.addAll(mimeMappings);
return this;
}
public List getMimeMappings() {
return mimeMappings;
}
public DeploymentInfo addSecurityConstraint(final SecurityConstraint securityConstraint) {
this.securityConstraints.add(securityConstraint);
return this;
}
public DeploymentInfo addSecurityConstraints(final SecurityConstraint... securityConstraints) {
this.securityConstraints.addAll(Arrays.asList(securityConstraints));
return this;
}
public DeploymentInfo addSecurityConstraints(final Collection securityConstraints) {
this.securityConstraints.addAll(securityConstraints);
return this;
}
public List getSecurityConstraints() {
return securityConstraints;
}
public Executor getExecutor() {
return executor;
}
/**
* Sets the executor that will be used to run servlet invocations. If this is null then the XNIO worker pool will be
* used.
*
* Individual servlets may use a different executor
*
* If this is null then the current executor is used, which is generally the XNIO worker pool
*
* @param executor The executor
* @see ServletInfo#executor
*/
public DeploymentInfo setExecutor(final Executor executor) {
this.executor = executor;
return this;
}
public Executor getAsyncExecutor() {
return asyncExecutor;
}
/**
* Sets the executor that is used to run async tasks.
*
* If this is null then {@link #executor} is used, if this is also null then the default is used
*
* @param asyncExecutor The executor
*/
public DeploymentInfo setAsyncExecutor(final Executor asyncExecutor) {
this.asyncExecutor = asyncExecutor;
return this;
}
public File getTempDir() {
if(tempDir == null) {
return null;
}
return tempDir.toFile();
}
public Path getTempPath() {
return tempDir;
}
/**
* @return Returns the {@link #getTempDir() temp directory path} if it's
* not null, else returns the system level temporary directory path
* pointed to by the Java system property {@code java.io.tmpdir}
*/
public Path requireTempPath() {
if (tempDir != null) {
return tempDir;
}
return Paths.get(SecurityActions.getSystemProperty("java.io.tmpdir"));
}
public DeploymentInfo setTempDir(final File tempDir) {
this.tempDir = tempDir != null ? tempDir.toPath() : null;
return this;
}
public DeploymentInfo setTempDir(final Path tempDir) {
this.tempDir = tempDir;
return this;
}
public boolean isIgnoreFlush() {
return ignoreFlush;
}
public DeploymentInfo setIgnoreFlush(boolean ignoreFlush) {
this.ignoreFlush = ignoreFlush;
return this;
}
public JspConfigDescriptor getJspConfigDescriptor() {
return jspConfigDescriptor;
}
public DeploymentInfo setJspConfigDescriptor(JspConfigDescriptor jspConfigDescriptor) {
this.jspConfigDescriptor = jspConfigDescriptor;
return this;
}
public DefaultServletConfig getDefaultServletConfig() {
return defaultServletConfig;
}
public DeploymentInfo setDefaultServletConfig(final DefaultServletConfig defaultServletConfig) {
this.defaultServletConfig = defaultServletConfig;
return this;
}
public DeploymentInfo addLocaleCharsetMapping(final String locale, final String charset) {
localeCharsetMapping.put(locale, charset);
return this;
}
public Map getLocaleCharsetMapping() {
return localeCharsetMapping;
}
public SessionManagerFactory getSessionManagerFactory() {
return sessionManagerFactory;
}
public DeploymentInfo setSessionManagerFactory(final SessionManagerFactory sessionManagerFactory) {
this.sessionManagerFactory = sessionManagerFactory;
return this;
}
public LoginConfig getLoginConfig() {
return loginConfig;
}
public DeploymentInfo setLoginConfig(LoginConfig loginConfig) {
this.loginConfig = loginConfig;
return this;
}
public IdentityManager getIdentityManager() {
return identityManager;
}
public DeploymentInfo setIdentityManager(IdentityManager identityManager) {
this.identityManager = identityManager;
return this;
}
public ConfidentialPortManager getConfidentialPortManager() {
return confidentialPortManager;
}
public DeploymentInfo setConfidentialPortManager(ConfidentialPortManager confidentialPortManager) {
this.confidentialPortManager = confidentialPortManager;
return this;
}
public DeploymentInfo addSecurityRole(final String role) {
this.securityRoles.add(role);
return this;
}
public DeploymentInfo addSecurityRoles(final String... roles) {
this.securityRoles.addAll(Arrays.asList(roles));
return this;
}
public DeploymentInfo addSecurityRoles(final Collection roles) {
this.securityRoles.addAll(roles);
return this;
}
public Set getSecurityRoles() {
return securityRoles;
}
/**
* Adds an outer handler wrapper. This handler will be run after the servlet initial handler,
* but before any other handlers. These are only run on REQUEST invocations, they
* are not invoked on a FORWARD or INCLUDE.
*
* @param wrapper The wrapper
*/
public DeploymentInfo addOuterHandlerChainWrapper(final HandlerWrapper wrapper) {
outerHandlerChainWrappers.add(wrapper);
return this;
}
public List getOuterHandlerChainWrappers() {
return outerHandlerChainWrappers;
}
/**
* Adds an inner handler chain wrapper. This handler will be run after the security handler,
* but before any other servlet handlers, and will be run for every request
*
* @param wrapper The wrapper
*/
public DeploymentInfo addInnerHandlerChainWrapper(final HandlerWrapper wrapper) {
innerHandlerChainWrappers.add(wrapper);
return this;
}
public List getInnerHandlerChainWrappers() {
return innerHandlerChainWrappers;
}
public DeploymentInfo addInitialHandlerChainWrapper(final HandlerWrapper wrapper) {
initialHandlerChainWrappers.add(wrapper);
return this;
}
public List getInitialHandlerChainWrappers() {
return initialHandlerChainWrappers;
}
/**
* Sets the initial handler wrapper that will take over responsibility for establishing
* a security context that will handle authentication for the request.
*
* Undertow specific authentication mechanisms will not be installed but Undertow handlers will
* still make the decision as to if authentication is required and will subsequently
* call {@link io.undertow.security.api.SecurityContext#authenticate()} as required.
*
* @param wrapper the {@link HandlerWrapper} to handle the initial security context installation.
* @return {@code this} to allow chaining.
*/
public DeploymentInfo setInitialSecurityWrapper(final HandlerWrapper wrapper) {
this.initialSecurityWrapper = wrapper;
return this;
}
public HandlerWrapper getInitialSecurityWrapper() {
return initialSecurityWrapper;
}
/**
* Adds a security handler. These are invoked before the authentication mechanism, and are always invoked
* even if authentication is not required.
* @param wrapper
* @return
*/
public DeploymentInfo addSecurityWrapper(final HandlerWrapper wrapper) {
securityWrappers.add(wrapper);
return this;
}
public List getSecurityWrappers() {
return securityWrappers;
}
public DeploymentInfo addNotificationReceiver(final NotificationReceiver notificationReceiver) {
this.notificationReceivers.add(notificationReceiver);
return this;
}
public DeploymentInfo addNotificactionReceivers(final NotificationReceiver... notificationReceivers) {
this.notificationReceivers.addAll(Arrays.asList(notificationReceivers));
return this;
}
public DeploymentInfo addNotificationReceivers(final Collection notificationReceivers) {
this.notificationReceivers.addAll(notificationReceivers);
return this;
}
public List getNotificationReceivers() {
return notificationReceivers;
}
public ConcurrentMap getServletContextAttributeBackingMap() {
return servletContextAttributeBackingMap;
}
/**
* Sets the map that will be used by the ServletContext implementation to store attributes.
*
* This should usuablly be null, in which case Undertow will create a new map. This is only
* used in situations where you want multiple deployments to share the same servlet context
* attributes.
*
* @param servletContextAttributeBackingMap
* The backing map
*/
public DeploymentInfo setServletContextAttributeBackingMap(final ConcurrentMap servletContextAttributeBackingMap) {
this.servletContextAttributeBackingMap = servletContextAttributeBackingMap;
return this;
}
public ServletSessionConfig getServletSessionConfig() {
return servletSessionConfig;
}
public DeploymentInfo setServletSessionConfig(final ServletSessionConfig servletSessionConfig) {
this.servletSessionConfig = servletSessionConfig;
return this;
}
/**
* @return the host name
*/
public String getHostName() {
return hostName;
}
public DeploymentInfo setHostName(final String hostName) {
this.hostName = hostName;
return this;
}
public boolean isDenyUncoveredHttpMethods() {
return denyUncoveredHttpMethods;
}
public DeploymentInfo setDenyUncoveredHttpMethods(final boolean denyUncoveredHttpMethods) {
this.denyUncoveredHttpMethods = denyUncoveredHttpMethods;
return this;
}
public ServletStackTraces getServletStackTraces() {
return servletStackTraces;
}
public DeploymentInfo setServletStackTraces(ServletStackTraces servletStackTraces) {
this.servletStackTraces = servletStackTraces;
return this;
}
public boolean isInvalidateSessionOnLogout() {
return invalidateSessionOnLogout;
}
public DeploymentInfo setInvalidateSessionOnLogout(boolean invalidateSessionOnLogout) {
this.invalidateSessionOnLogout = invalidateSessionOnLogout;
return this;
}
public int getDefaultCookieVersion() {
return defaultCookieVersion;
}
public DeploymentInfo setDefaultCookieVersion(int defaultCookieVersion) {
this.defaultCookieVersion = defaultCookieVersion;
return this;
}
public SessionPersistenceManager getSessionPersistenceManager() {
return sessionPersistenceManager;
}
public DeploymentInfo setSessionPersistenceManager(SessionPersistenceManager sessionPersistenceManager) {
this.sessionPersistenceManager = sessionPersistenceManager;
return this;
}
public AuthorizationManager getAuthorizationManager() {
return authorizationManager;
}
public DeploymentInfo setAuthorizationManager(AuthorizationManager authorizationManager) {
this.authorizationManager = authorizationManager;
return this;
}
public DeploymentInfo addPrincipalVsRoleMapping(final String principal, final String mapping) {
Set set = principalVersusRolesMap.get(principal);
if (set == null) {
principalVersusRolesMap.put(principal, set = new HashSet<>());
}
set.add(mapping);
return this;
}
public DeploymentInfo addPrincipalVsRoleMappings(final String principal, final String... mappings) {
Set set = principalVersusRolesMap.get(principal);
if (set == null) {
principalVersusRolesMap.put(principal, set = new HashSet<>());
}
set.addAll(Arrays.asList(mappings));
return this;
}
public DeploymentInfo addPrincipalVsRoleMappings(final String principal, final Collection mappings) {
Set set = principalVersusRolesMap.get(principal);
if (set == null) {
principalVersusRolesMap.put(principal, set = new HashSet<>());
}
set.addAll(mappings);
return this;
}
public Map> getPrincipalVersusRolesMap() {
return principalVersusRolesMap;
}
/**
* Removes all configured authentication mechanisms from the deployment.
*
* @return this deployment info
*/
public DeploymentInfo clearLoginMethods() {
if(loginConfig != null) {
loginConfig.getAuthMethods().clear();
}
return this;
}
/**
* Adds an authentication mechanism directly to the deployment. This mechanism will be first in the list.
*
* In general you should just use {@link #addAuthenticationMechanism(String, io.undertow.security.api.AuthenticationMechanismFactory)}
* and allow the user to configure the methods they want by name.
*
* This method is essentially a convenience method, if is the same as registering a factory under the provided name that returns
* and authentication mechanism, and then adding it to the login config list.
*
* If you want your mechanism to be the only one in the deployment you should first invoke {@link #clearLoginMethods()}.
*
* @param name The authentication mechanism name
* @param mechanism The mechanism
* @return this deployment info
*/
public DeploymentInfo addFirstAuthenticationMechanism(final String name, final AuthenticationMechanism mechanism) {
authenticationMechanisms.put(name, new ImmediateAuthenticationMechanismFactory(mechanism));
if(loginConfig == null) {
loginConfig = new LoginConfig(null);
}
loginConfig.addFirstAuthMethod(new AuthMethodConfig(name));
return this;
}
/**
* Adds an authentication mechanism directly to the deployment. This mechanism will be last in the list.
*
* In general you should just use {@link #addAuthenticationMechanism(String, io.undertow.security.api.AuthenticationMechanismFactory)}
* and allow the user to configure the methods they want by name.
*
* This method is essentially a convenience method, if is the same as registering a factory under the provided name that returns
* and authentication mechanism, and then adding it to the login config list.
*
* If you want your mechanism to be the only one in the deployment you should first invoke {@link #clearLoginMethods()}.
*
* @param name The authentication mechanism name
* @param mechanism The mechanism
* @return
*/
public DeploymentInfo addLastAuthenticationMechanism(final String name, final AuthenticationMechanism mechanism) {
authenticationMechanisms.put(name, new ImmediateAuthenticationMechanismFactory(mechanism));
if(loginConfig == null) {
loginConfig = new LoginConfig(null);
}
loginConfig.addLastAuthMethod(new AuthMethodConfig(name));
return this;
}
/**
* Adds an authentication mechanism. The name is case insenstive, and will be converted to uppercase internally.
*
* @param name The name
* @param factory The factory
* @return
*/
public DeploymentInfo addAuthenticationMechanism(final String name, final AuthenticationMechanismFactory factory) {
authenticationMechanisms.put(name.toUpperCase(Locale.US), factory);
return this;
}
public Map getAuthenticationMechanisms() {
return authenticationMechanisms;
}
/**
* Returns true if the specified mechanism is present in the login config
* @param mechanismName The mechanism name
* @return true if the mechanism is enabled
*/
public boolean isAuthenticationMechanismPresent(final String mechanismName) {
if(loginConfig != null) {
for(AuthMethodConfig method : loginConfig.getAuthMethods()) {
if(method.getName().equalsIgnoreCase(mechanismName)) {
return true;
}
}
}
return false;
}
/**
* Adds an additional servlet extension to the deployment. Servlet extensions are generally discovered
* using META-INF/services entries, however this may not be practical in all environments.
* @param servletExtension The servlet extension
* @return this
*/
public DeploymentInfo addServletExtension(final ServletExtension servletExtension) {
this.servletExtensions.add(servletExtension);
return this;
}
public List getServletExtensions() {
return servletExtensions;
}
public AuthenticationMechanism getJaspiAuthenticationMechanism() {
return jaspiAuthenticationMechanism;
}
public DeploymentInfo setJaspiAuthenticationMechanism(AuthenticationMechanism jaspiAuthenticationMechanism) {
this.jaspiAuthenticationMechanism = jaspiAuthenticationMechanism;
return this;
}
public SecurityContextFactory getSecurityContextFactory() {
return this.securityContextFactory;
}
public DeploymentInfo setSecurityContextFactory(final SecurityContextFactory securityContextFactory) {
this.securityContextFactory = securityContextFactory;
return this;
}
public String getServerName() {
return serverName;
}
public DeploymentInfo setServerName(String serverName) {
this.serverName = serverName;
return this;
}
public DeploymentInfo setMetricsCollector(MetricsCollector metricsCollector){
this.metricsCollector = metricsCollector;
return this;
}
public MetricsCollector getMetricsCollector() {
return metricsCollector;
}
public SessionConfigWrapper getSessionConfigWrapper() {
return sessionConfigWrapper;
}
public DeploymentInfo setSessionConfigWrapper(SessionConfigWrapper sessionConfigWrapper) {
this.sessionConfigWrapper = sessionConfigWrapper;
return this;
}
public boolean isDisableCachingForSecuredPages() {
return disableCachingForSecuredPages;
}
public DeploymentInfo setDisableCachingForSecuredPages(boolean disableCachingForSecuredPages) {
this.disableCachingForSecuredPages = disableCachingForSecuredPages;
return this;
}
public DeploymentInfo addLifecycleInterceptor(final LifecycleInterceptor interceptor) {
lifecycleInterceptors.add(interceptor);
return this;
}
public List getLifecycleInterceptors() {
return lifecycleInterceptors;
}
/**
* Returns the exception handler that is used by this deployment. By default this will simply
* log unhandled exceptions
*/
public ExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
/**
* Sets the default exception handler for this deployment
* @param exceptionHandler The exception handler
* @return
*/
public DeploymentInfo setExceptionHandler(ExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
return this;
}
public boolean isEscapeErrorMessage() {
return escapeErrorMessage;
}
/**
* Set if if the message passed to {@link jakarta.servlet.http.HttpServletResponse#sendError(int, String)} should be escaped.
*
* If this is false applications must be careful not to use user provided data (such as the URI) in the message
*
* @param escapeErrorMessage If the error message should be escaped
*/
public DeploymentInfo setEscapeErrorMessage(boolean escapeErrorMessage) {
this.escapeErrorMessage = escapeErrorMessage;
return this;
}
public DeploymentInfo addSessionListener(SessionListener sessionListener) {
this.sessionListeners.add(sessionListener);
return this;
}
public List getSessionListeners() {
return sessionListeners;
}
public AuthenticationMode getAuthenticationMode() {
return authenticationMode;
}
/**
* Sets if this deployment should use pro-active authentication and always authenticate if the credentials are present
* or constraint driven auth which will only call the authentication mechanisms for protected resources.
*
* Pro active auth means that requests for unprotected resources will still be associated with a user, which may be
* useful for access logging.
*
*
* @param authenticationMode The authentication mode to use
* @return
*/
public DeploymentInfo setAuthenticationMode(AuthenticationMode authenticationMode) {
this.authenticationMode = authenticationMode;
return this;
}
public MultipartConfigElement getDefaultMultipartConfig() {
return defaultMultipartConfig;
}
public DeploymentInfo setDefaultMultipartConfig(MultipartConfigElement defaultMultipartConfig) {
this.defaultMultipartConfig = defaultMultipartConfig;
return this;
}
public int getContentTypeCacheSize() {
return contentTypeCacheSize;
}
public DeploymentInfo setContentTypeCacheSize(int contentTypeCacheSize) {
this.contentTypeCacheSize = contentTypeCacheSize;
return this;
}
public SessionIdGenerator getSessionIdGenerator() {
return sessionIdGenerator;
}
public DeploymentInfo setSessionIdGenerator(SessionIdGenerator sessionIdGenerator) {
this.sessionIdGenerator = sessionIdGenerator;
return this;
}
public boolean isSendCustomReasonPhraseOnError() {
return sendCustomReasonPhraseOnError;
}
public CrawlerSessionManagerConfig getCrawlerSessionManagerConfig() {
return crawlerSessionManagerConfig;
}
public DeploymentInfo setCrawlerSessionManagerConfig(CrawlerSessionManagerConfig crawlerSessionManagerConfig) {
this.crawlerSessionManagerConfig = crawlerSessionManagerConfig;
return this;
}
/**
* If this is true then the message parameter of {@link jakarta.servlet.http.HttpServletResponse#sendError(int, String)} and
* {@link jakarta.servlet.http.HttpServletResponse#setStatus(int, String)} will be used as the HTTP reason phrase in
* the response.
*
* @param sendCustomReasonPhraseOnError If the parameter to sendError should be used as a HTTP reason phrase
* @return this
*/
public DeploymentInfo setSendCustomReasonPhraseOnError(boolean sendCustomReasonPhraseOnError) {
this.sendCustomReasonPhraseOnError = sendCustomReasonPhraseOnError;
return this;
}
public boolean isChangeSessionIdOnLogin() {
return changeSessionIdOnLogin;
}
public DeploymentInfo setChangeSessionIdOnLogin(boolean changeSessionIdOnLogin) {
this.changeSessionIdOnLogin = changeSessionIdOnLogin;
return this;
}
public boolean isUseCachedAuthenticationMechanism() {
return useCachedAuthenticationMechanism;
}
/**
* If this is set to false the the cached authenticated session mechanism won't be installed. If you want FORM and
* other auth methods that require caching to work then you need to install another caching based auth method (such
* as SSO).
* @param useCachedAuthenticationMechanism If Undertow should use its internal authentication cache mechanism
* @return this
*/
public DeploymentInfo setUseCachedAuthenticationMechanism(boolean useCachedAuthenticationMechanism) {
this.useCachedAuthenticationMechanism = useCachedAuthenticationMechanism;
return this;
}
public boolean isSecurityDisabled() {
return securityDisabled;
}
public DeploymentInfo setSecurityDisabled(boolean securityDisabled) {
this.securityDisabled = securityDisabled;
return this;
}
public boolean isCheckOtherSessionManagers() {
return checkOtherSessionManagers;
}
/**
* If this is true then when an existing invalid session id is found all other deployments in the container will have their
* session managers checked to see if it represents a valid session. If it does then the session id will be re-used.
*/
public DeploymentInfo setCheckOtherSessionManagers(boolean checkOtherSessionManagers) {
this.checkOtherSessionManagers = checkOtherSessionManagers;
return this;
}
public String getDefaultRequestEncoding() {
return defaultRequestEncoding;
}
public DeploymentInfo setDefaultRequestEncoding(String defaultRequestEncoding) {
this.defaultRequestEncoding = defaultRequestEncoding;
return this;
}
public String getDefaultResponseEncoding() {
return defaultResponseEncoding;
}
public DeploymentInfo setDefaultResponseEncoding(String defaultResponseEncoding) {
this.defaultResponseEncoding = defaultResponseEncoding;
return this;
}
/**
* Adds a pre compressed resource encoding and maps it to a file extension
*
*
* @param encoding The content encoding
* @param extension The file extension
* @return this builder
*/
public DeploymentInfo addPreCompressedResourceEncoding(String encoding, String extension) {
preCompressedResources.put(encoding, extension);
return this;
}
public Map getPreCompressedResources() {
return preCompressedResources;
}
public int getContainerMajorVersion() {
return containerMajorVersion;
}
public DeploymentInfo setContainerMajorVersion(int containerMajorVersion) {
this.containerMajorVersion = containerMajorVersion;
return this;
}
public int getContainerMinorVersion() {
return containerMinorVersion;
}
public DeploymentInfo setContainerMinorVersion(int containerMinorVersion) {
this.containerMinorVersion = containerMinorVersion;
return this;
}
public boolean isPreservePathOnForward() {
return preservePathOnForward;
}
public void setPreservePathOnForward(boolean preservePathOnForward) {
this.preservePathOnForward = preservePathOnForward;
}
/**
* Add's a listener that is only invoked once all other deployment steps have been completed
*
* The listeners contextDestroyed
method will be called after all undeployment steps are undertaken
*
* @param servletContextListener
* @return
*/
public DeploymentInfo addDeploymentCompleteListener(ServletContextListener servletContextListener) {
deploymentCompleteListeners.add(servletContextListener);
return this;
}
public List getDeploymentCompleteListeners() {
return deploymentCompleteListeners;
}
public boolean isOrphanSessionAllowed() {
return this.allowOrphanSession;
}
public void setOrphanSessionAllowed(boolean allowOrphanSession) {
this.allowOrphanSession = allowOrphanSession;
}
@Override
public DeploymentInfo clone() {
final DeploymentInfo info = new DeploymentInfo()
.setClassLoader(classLoader)
.setContextPath(contextPath)
.setResourceManager(resourceManager)
.setMajorVersion(majorVersion)
.setMinorVersion(minorVersion)
.setDeploymentName(deploymentName)
.setClassIntrospecter(classIntrospecter);
for (Map.Entry e : servlets.entrySet()) {
info.addServlet(e.getValue().clone());
}
for (Map.Entry e : filters.entrySet()) {
info.addFilter(e.getValue().clone());
}
info.displayName = displayName;
info.filterUrlMappings.addAll(filterUrlMappings);
info.filterServletNameMappings.addAll(filterServletNameMappings);
info.listeners.addAll(listeners);
info.servletContainerInitializers.addAll(servletContainerInitializers);
info.threadSetupActions.addAll(threadSetupActions);
info.initParameters.putAll(initParameters);
info.servletContextAttributes.putAll(servletContextAttributes);
info.welcomePages.addAll(welcomePages);
info.errorPages.addAll(errorPages);
info.mimeMappings.addAll(mimeMappings);
info.executor = executor;
info.asyncExecutor = asyncExecutor;
info.tempDir = tempDir;
info.jspConfigDescriptor = jspConfigDescriptor;
info.defaultServletConfig = defaultServletConfig;
info.localeCharsetMapping.putAll(localeCharsetMapping);
info.sessionManagerFactory = sessionManagerFactory;
if (loginConfig != null) {
info.loginConfig = loginConfig.clone();
}
info.identityManager = identityManager;
info.confidentialPortManager = confidentialPortManager;
info.defaultEncoding = defaultEncoding;
info.urlEncoding = urlEncoding;
info.securityConstraints.addAll(securityConstraints);
info.outerHandlerChainWrappers.addAll(outerHandlerChainWrappers);
info.innerHandlerChainWrappers.addAll(innerHandlerChainWrappers);
info.initialSecurityWrapper = initialSecurityWrapper;
info.securityWrappers.addAll(securityWrappers);
info.initialHandlerChainWrappers.addAll(initialHandlerChainWrappers);
info.securityRoles.addAll(securityRoles);
info.notificationReceivers.addAll(notificationReceivers);
info.allowNonStandardWrappers = allowNonStandardWrappers;
info.defaultSessionTimeout = defaultSessionTimeout;
info.servletContextAttributeBackingMap = servletContextAttributeBackingMap;
info.servletSessionConfig = servletSessionConfig;
info.hostName = hostName;
info.denyUncoveredHttpMethods = denyUncoveredHttpMethods;
info.servletStackTraces = servletStackTraces;
info.invalidateSessionOnLogout = invalidateSessionOnLogout;
info.defaultCookieVersion = defaultCookieVersion;
info.sessionPersistenceManager = sessionPersistenceManager;
for (Map.Entry> e : principalVersusRolesMap.entrySet()) {
info.principalVersusRolesMap.put(e.getKey(), new HashSet<>(e.getValue()));
}
info.ignoreFlush = ignoreFlush;
info.authorizationManager = authorizationManager;
info.authenticationMechanisms.putAll(authenticationMechanisms);
info.servletExtensions.addAll(servletExtensions);
info.jaspiAuthenticationMechanism = jaspiAuthenticationMechanism;
info.securityContextFactory = securityContextFactory;
info.serverName = serverName;
info.metricsCollector = metricsCollector;
info.sessionConfigWrapper = sessionConfigWrapper;
info.eagerFilterInit = eagerFilterInit;
info.disableCachingForSecuredPages = disableCachingForSecuredPages;
info.exceptionHandler = exceptionHandler;
info.escapeErrorMessage = escapeErrorMessage;
info.sessionListeners.addAll(sessionListeners);
info.lifecycleInterceptors.addAll(lifecycleInterceptors);
info.authenticationMode = authenticationMode;
info.defaultMultipartConfig = defaultMultipartConfig;
info.contentTypeCacheSize = contentTypeCacheSize;
info.sessionIdGenerator = sessionIdGenerator;
info.sendCustomReasonPhraseOnError = sendCustomReasonPhraseOnError;
info.changeSessionIdOnLogin = changeSessionIdOnLogin;
info.crawlerSessionManagerConfig = crawlerSessionManagerConfig;
info.securityDisabled = securityDisabled;
info.useCachedAuthenticationMechanism = useCachedAuthenticationMechanism;
info.checkOtherSessionManagers = checkOtherSessionManagers;
info.defaultRequestEncoding = defaultRequestEncoding;
info.defaultResponseEncoding = defaultResponseEncoding;
info.preCompressedResources.putAll(preCompressedResources);
info.containerMajorVersion = containerMajorVersion;
info.containerMinorVersion = containerMinorVersion;
info.deploymentCompleteListeners.addAll(deploymentCompleteListeners);
info.preservePathOnForward = preservePathOnForward;
info.allowOrphanSession = allowOrphanSession;
return info;
}
}