The overall architecture
Although this pictures shows only two backends, their number is of course only limited by your system. XMLServ is the part where clients requests are decoded and submitted to a Backend for processing. The XML output of the Backend is then transformed by the XSL processor and sent back to the client.
The central part is a servlet named XMLServ. Upon initialization (i.e. the servlet container calling its init() method) it instantiates BackendRepository, which reads the config file and creates a BackendHandle for each backend definition in the configuration file. The BackendRepository is responsible for mapping a URI to a Backend.
The BackendHandle holds Meta-information on a backend (such as the implementing classname, the SecurityManager regulating access to this Backend as well as the XSL mappings.
The Backend implementation is instantiated by BackendHandle during this load process. Any instantiation error leads to the deactivation of this backend, the load process continues with the next configuration entry.
The BackendRepository keeps a cache of the SecurityManager Implementations already instantiated so that only one instance is used for all Backends configured to use the same SecurityManager Implementation.
Stylesheet options are processed and set in the BackendHandle object. Before adding the BackendHandle to the repository, the handles validate() method is called to ensure integrity (i.e. a Backend classname, a default stylesheet etc.).
The incoming client request is received by the only servlet in this framework, XMLServ. It uses the BackendRepository instantiated at startup to map the requested URI (relative to its own base URI as mapped in the servlet container configuration web.xml) to a Backend. The Backends process() method receives the original HttpServletRequest object plus a reference to the ServletContext for the XMLServ servlet. Its return value is a javax.xml.transform.Source object.
This returned javax.xml.transform.Source object is used as the input document for the XSL processor, applying the stylesheet configured for this type of client request. The result is then written to the output stream (obtained from the HttpServletResponse object).
There are two additional ways for a Backend to produce output by throwing exceptions:
The shutdown procedure is initiated by the servlet container calling the servlets destroy() method, which in turn calls destroy() in BackendRepository. Iterating over all registered (i.e. actually loaded) Backends, BackendRepository calls each BackendHandles destroy(), which calls the Backends destroy() method.