Class 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 corresponding DeferredServletContext in init(ServletConfig) providing the servlet config (and context). This allows the DeferredServletContext to parse the URL mapping of this servlet as defined in web.xml.
    • The DeferredServletContext is created programmatically.
      This requires init parameters for the URL mapping and optionally async support for this servlet. The DeferredServletContext will then create and register this servlet. Async support will be required if any sub servlets should use async behaviour.
    In both cases the URL mapping needs to end with /* to allow for the paths of sub servlets to be handled correctly. That is, the sub servlets are "registered" below this servlet at the DeferredServletContext. 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 to register themselves with the corresponding path mapping. If the demultiplexing target is this, the request will be forwarded to HttpServlet.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 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
        The DeferredServletContext, 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 and pathMappings may already contain the mappings for a servlet.

        When accessing servlets or paths synchronise on the field. If both locks are required, make sure to get servlets before paths! 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 in servlets.

        When accessing servlets or paths synchronise on the field. If both locks are required, make sure to get servlets before paths! 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 via paths.
        See Also:
        ServletRegistration.addMapping(String...)
    • Constructor Detail

      • DemuxServlet

        public DemuxServlet()
        Creates a new DemuxServlet usually called by a servlet container directly. The missing field values will be set when initialising. Also the accompanying DeferredServletContext will be created there.
      • DemuxServlet

        protected DemuxServlet​(String servletName,
                               DeferredServletContext dsc)
        Creates a new DemuxServlet usually called by the designated DeferredServletContext which is explicitly created by some code.
        The calling DeferredServletContext is responsible for registering this servlet (in the outer servlet context).
        Parameters:
        servletName - The name of this demultiplexing servlet for logging purpose.
        dsc - The DeferredServletContext 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 (via web.xml), the DeferredServletContext will be created here. Subclasses should usually call this method first!
        Specified by:
        init in interface javax.servlet.Servlet
        Overrides:
        init in class javax.servlet.GenericServlet
        Throws:
        javax.servlet.ServletException
      • getServletConfig

        public javax.servlet.ServletConfig getServletConfig()
        Specified by:
        getServletConfig in interface javax.servlet.Servlet
        Overrides:
        getServletConfig in class javax.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 to HttpServlet.service(ServletRequest, ServletResponse) thus using the normal HTTP request handling.

        Specified by:
        service in interface javax.servlet.Servlet
        Overrides:
        service in class javax.servlet.http.HttpServlet
        Throws:
        javax.servlet.ServletException
        IOException
      • getServletInfo

        public String getServletInfo()
        Specified by:
        getServletInfo in interface javax.servlet.Servlet
        Overrides:
        getServletInfo in class javax.servlet.GenericServlet
      • destroy

        public void destroy()
        Removes the mapping for and calls destroy() on all known sub servlets.
        Specified by:
        destroy in interface javax.servlet.Servlet
        Overrides:
        destroy in class javax.servlet.GenericServlet
      • getPaths

        protected Collection<String> getPaths​(String name)
        Gets the paths for the servlet with the designated name or null 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, an IllegalStateException 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, an IllegalStateException 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 the GlobalMessagesLoader.GLOBAL_COMPANY_NAME followed by DemuxServlet.
        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 interface DynamicServlet
        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 interface DynamicServlet
        Parameters:
        context - The servlet context of this servlet.