Class DemuxServlet
- java.lang.Object
-
- javax.servlet.GenericServlet
-
- javax.servlet.http.HttpServlet
-
- de.aristaflow.adept2.base.servletcontainer.demux.DemuxServlet
-
- All Implemented Interfaces:
DynamicServlet
,Serializable
,javax.servlet.Servlet
,javax.servlet.ServletConfig
public class DemuxServlet extends javax.servlet.http.HttpServlet implements DynamicServlet
This servlet allows to register sub servlets at runtime, i. e. even after the servlet context has been initialised. It is closely coupled with a corresponding servlet context. This servlet demultiplexes requests to the registered sub servlets, i. e. it resolves paths and forwards the requests to the corresponding sub servlet.This servlet can be used in two ways:
- Let the servlet container instantiate it (or a subclass) via
web.xml
.
The servlet will then instantiate the correspondingDeferredServletContext
ininit(ServletConfig)
providing the servlet config (and context). This allows theDeferredServletContext
to parse the URL mapping of this servlet as defined inweb.xml
. - The
DeferredServletContext
is created programmatically.
This requires init parameters for the URL mapping and optionally async support for this servlet. TheDeferredServletContext
will then create and register this servlet. Async support will be required if any sub servlets should use async behaviour.
/*
to allow for the paths of sub servlets to be handled correctly. That is, the sub servlets are "registered" below this servlet at theDeferredServletContext
. However, the parent servlet context and the servlet container do not know about them. So requests need to be handled by this demultiplexing servlet which forwards them appropriately.Subclasses needing to perform their HTTP request handling, i. e.
HttpServlet.doGet(HttpServletRequest, javax.servlet.http.HttpServletResponse)
,HttpServlet.doPost(HttpServletRequest, javax.servlet.http.HttpServletResponse)
, ..., simply need toregister themselves
with the corresponding path mapping. If the demultiplexing target isthis
, the request will be forwarded toHttpServlet.service(ServletRequest, ServletResponse)
. Just make sure not to use/*
for the mapping since this is required for demultiplexing sub servlets.The implementation is heavily inspired by
ServletHandler
.- See Also:
- Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description protected javax.servlet.ServletConfig
config
The config of this servlet.protected String
contextPath
The (inner) context path, i. e. the path of the deferred servlet context.protected DynamicServlet
default404
The default 404 servlet used in case no other servlet has been found for a specific path/target.protected DeferredServletContext
dsc
TheDeferredServletContext
, i. e. the inner servlet context used by the sub servlets.protected org.eclipse.jetty.http.pathmap.PathMappings<DynamicServlet>
pathMappings
All path mappings known by this demultiplexing servlet.protected Map<String,Collection<String>>
paths
The paths for each servlet; key is the corresponding servlet name.protected String
servletName
The name of this demultiplexing servlet for logging purpose.protected Map<String,Pair<DynamicServlet,String>>
servlets
All sub servlets registered at this servlet (or rather the corresponding servlet context).
-
Constructor Summary
Constructors Modifier Constructor Description DemuxServlet()
Creates a newDemuxServlet
usually called by a servlet container directly.protected
DemuxServlet(String servletName, DeferredServletContext dsc)
Creates a newDemuxServlet
usually called by the designatedDeferredServletContext
which is explicitly created by some code.
The callingDeferredServletContext
is responsible for registering this servlet (in the outer servlet context).
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description protected Collection<String>
addServletWithMapping(DynamicServlet servlet, Collection<String> pathSpec)
Adds the designated servlet with the designated path specifications.void
destroy()
Removes the mapping for and callsdestroy()
on all known sub servlets.static String
getDefaultDemuxServletName()
Gets a default name for this demultiplexing servlet.protected Collection<String>
getPaths(String name)
Gets the paths for the servlet with the designated name ornull
if no corresponding paths are known.javax.servlet.ServletConfig
getServletConfig()
protected Pair<DynamicServlet,String>
getServletForTarget(String target)
Gets the servlet for the designated (request) target.String
getServletInfo()
void
init(javax.servlet.ServletConfig initConfig)
Sets the designated config.protected void
removeServletWithMapping(DynamicServlet servlet)
Remove all previously added URL mappings for the designated servlet.void
service(javax.servlet.ServletRequest req, javax.servlet.ServletResponse res)
Determines the target servlet for the designated request, wraps the request (to adapt the context and servlet paths appropriately, i. e. hide this servlet) and forward/demultiplex the request to the corresponding sub servlet.void
servletDeployed(javax.servlet.ServletContext context, String urlPattern)
Notifies the servlet that it has been deployed with the designated context and the designated pattern.void
servletUndeployed(javax.servlet.ServletContext context)
Notifies the servlet that it has been undeployed.protected void
subServletDeployed(DynamicServlet servlet, String servletContext)
Signals that the designated sub servlet has been deployed now.-
Methods inherited from class javax.servlet.http.HttpServlet
doDelete, doGet, doHead, doOptions, doPost, doPut, doTrace, getLastModified, service
-
Methods inherited from class javax.servlet.GenericServlet
getInitParameter, getInitParameterNames, getServletContext, getServletName, init, log, log
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface de.aristaflow.adept2.base.servletcontainer.DynamicServlet
getServletName, servletDeployed
-
-
-
-
Field Detail
-
default404
protected final DynamicServlet default404
The default 404 servlet used in case no other servlet has been found for a specific path/target.
-
servletName
protected String servletName
The name of this demultiplexing servlet for logging purpose.
-
config
protected javax.servlet.ServletConfig config
The config of this servlet. This is the outer servlet config. It will not be used directly by sub servlets.
-
dsc
protected DeferredServletContext dsc
TheDeferredServletContext
, i. e. the inner servlet context used by the sub servlets.
-
contextPath
protected String contextPath
The (inner) context path, i. e. the path of the deferred servlet context. This is required to adapt the paths of incoming requests for the sub servlets. The demultiplexing servlet has to be hidden from them.
-
servlets
protected final Map<String,Pair<DynamicServlet,String>> servlets
All sub servlets registered at this servlet (or rather the corresponding servlet context). Key of the map is the corresponding servlet name, values are the servlet as well as the hierarchical servlet context, i. e. more or less the main URL mapping of the servlet. The servlet hierchical servlet context is required to resolve the servlet path correctly within the demultiplexing request.
This map only contains fully initialised servlets. Before this,paths
andpathMappings
may already contain the mappings for a servlet.When accessing
servlets
orpaths
synchronise on the field. If both locks are required, make sure to getservlets
beforepaths
! This is especially critical when calling methods internally.
-
paths
protected final Map<String,Collection<String>> paths
The paths for each servlet; key is the corresponding servlet name. Each servlet mapping may contain several paths, i. e. each servlet may have several URL mappings.
Paths are added before initialising a servlet so this map may contain a servlet path for which no servlet is inservlets
.When accessing
servlets
orpaths
synchronise on the field. If both locks are required, make sure to getservlets
beforepaths
! This is especially critical when calling methods internally.
-
pathMappings
protected final org.eclipse.jetty.http.pathmap.PathMappings<DynamicServlet> pathMappings
All path mappings known by this demultiplexing servlet. This allows to demultiplex incoming requests to the corresponding servlet. It also allows to track already known paths and prevents several servlets having the same mapping. The first registered path/servlet wins, later servlets will be refused.
Access to this map is synchronised viapaths
.- See Also:
ServletRegistration.addMapping(String...)
-
-
Constructor Detail
-
DemuxServlet
public DemuxServlet()
Creates a newDemuxServlet
usually called by a servlet container directly. The missing field values will be set when initialising. Also the accompanyingDeferredServletContext
will be created there.
-
DemuxServlet
protected DemuxServlet(String servletName, DeferredServletContext dsc)
Creates a newDemuxServlet
usually called by the designatedDeferredServletContext
which is explicitly created by some code.
The callingDeferredServletContext
is responsible for registering this servlet (in the outer servlet context).- Parameters:
servletName
- The name of this demultiplexing servlet for logging purpose.dsc
- TheDeferredServletContext
to be used with this servlet.
-
-
Method Detail
-
init
public void init(javax.servlet.ServletConfig initConfig) throws javax.servlet.ServletException
Sets the designated config. If this servlet has been created by the servlet container (viaweb.xml
), theDeferredServletContext
will be created here. Subclasses should usually call this method first!- Specified by:
init
in interfacejavax.servlet.Servlet
- Overrides:
init
in classjavax.servlet.GenericServlet
- Throws:
javax.servlet.ServletException
-
getServletConfig
public javax.servlet.ServletConfig getServletConfig()
- Specified by:
getServletConfig
in interfacejavax.servlet.Servlet
- Overrides:
getServletConfig
in classjavax.servlet.GenericServlet
-
service
public void service(javax.servlet.ServletRequest req, javax.servlet.ServletResponse res) throws javax.servlet.ServletException, IOException
Determines the target servlet for the designated request, wraps the request (to adapt the context and servlet paths appropriately, i. e. hide this servlet) and forward/demultiplex the request to the corresponding sub servlet.If the target servlet is
this
, the complete request will be forwarded toHttpServlet.service(ServletRequest, ServletResponse)
thus using the normal HTTP request handling.- Specified by:
service
in interfacejavax.servlet.Servlet
- Overrides:
service
in classjavax.servlet.http.HttpServlet
- Throws:
javax.servlet.ServletException
IOException
-
getServletInfo
public String getServletInfo()
- Specified by:
getServletInfo
in interfacejavax.servlet.Servlet
- Overrides:
getServletInfo
in classjavax.servlet.GenericServlet
-
destroy
public void destroy()
Removes the mapping for and callsdestroy()
on all known sub servlets.- Specified by:
destroy
in interfacejavax.servlet.Servlet
- Overrides:
destroy
in classjavax.servlet.GenericServlet
-
getPaths
protected Collection<String> getPaths(String name)
Gets the paths for the servlet with the designated name ornull
if no corresponding paths are known.- Parameters:
name
- The name of the servlet for which to get the paths.- Returns:
- The (unmodifiable) paths for the servlet with the designated name or an empty collection if no corresponding paths are known.
-
getServletForTarget
protected Pair<DynamicServlet,String> getServletForTarget(String target)
Gets the servlet for the designated (request) target. This tries to match the path mappings with the designated target. If the target is relative (does not start with/
), the target will be interpreted as servlet name.- Parameters:
target
- The path within the context of this servlet or the servlet name.- Returns:
- A pair with the servlet and its hierarchical context or the 404 servlet for the designated target if no other servlet can be found.
-
addServletWithMapping
protected Collection<String> addServletWithMapping(DynamicServlet servlet, Collection<String> pathSpec)
Adds the designated servlet with the designated path specifications. The paths will be checked so that already existing paths will not be used for different servlets. If such paths exist, they will be removed. So check the returned paths for the actually used path specifications. If the designated servlet (name) has already been added with paths, the corresponding paths will be removed before adding the current ones.
It there is already a servlet of the same name and this has been initialised, anIllegalStateException
will be thrown. You cannot change the paths after a servlet has been initialised.- Parameters:
servlet
- The servlet (for) which to add (the designated paths).pathSpec
- The paths which to add for the designated servlet.- Returns:
- The (unmodifiable) paths created for the designated servlet and the designated paths. If there are already different servlets registered for some of the designated paths, these paths will be removed and will therefore not be in the returned paths.
- Throws:
IllegalStateException
- If a servlet with the name of the designated servlet already exists and has already been initialised, anIllegalStateException
will be thrown.
-
removeServletWithMapping
protected void removeServletWithMapping(DynamicServlet servlet)
Remove all previously added URL mappings for the designated servlet.- Parameters:
servlet
- The servlet which to remove including all its mappings.
-
subServletDeployed
protected void subServletDeployed(DynamicServlet servlet, String servletContext)
Signals that the designated sub servlet has been deployed now. This adds the servlet to the internal servlet map.- Parameters:
servlet
- The servlet which to add to the internal servlet map.servletContext
- The hierarchical servlet context, i. e. more or less the main URL mapping of the servlet.
-
getDefaultDemuxServletName
public static String getDefaultDemuxServletName()
Gets a default name for this demultiplexing servlet. This is theGlobalMessagesLoader.GLOBAL_COMPANY_NAME
followed byDemuxServlet
.- Returns:
- A default name for this demultiplexing servlet.
-
servletDeployed
public final void servletDeployed(javax.servlet.ServletContext context, String urlPattern)
Description copied from interface:DynamicServlet
Notifies the servlet that it has been deployed with the designated context and the designated pattern. Note that the servlet usually will not have been initialised yet.- Specified by:
servletDeployed
in interfaceDynamicServlet
- Parameters:
context
- The servlet context of this servlet.urlPattern
- The URL pattern (mapping) this servlet has been deployed with.
-
servletUndeployed
public final void servletUndeployed(javax.servlet.ServletContext context)
Description copied from interface:DynamicServlet
Notifies the servlet that it has been undeployed.- Specified by:
servletUndeployed
in interfaceDynamicServlet
- Parameters:
context
- The servlet context of this servlet.
-
-