





















































As we saw earlier, Bootstrap is simply a convenience class that is used to run the Embedded class, or rather to run Catalina, which subclasses Embedded. The Catalina class is intended to add the ability to process a server.xml file to its parent class. It even exposes a main() method, so you can invoke it directly with appropriate command-line arguments.
Bootstrap uses its newly constructed serverLoader to load the Catalina class, which is then instantiated.
It delegates the loading process to this Catalina instance's load() method. This method updates the catalina.base and catalina.home system properties to absolute references, verifies that the working directory is set appropriately, and initializes the naming system, which is Tomcat's implementation of the JNDI API. For now, all we need to note is that it indicates that JNDI is enabled by setting the catalina.useNaming system property to true, and prefixing the Context.URL_PKG_PREFIXES system property with the package org.apache.naming using a colon delimiter.
The Context.URL_PKG_PREFIXES property indicates a list of fully qualified package prefixes for URL context factories. Setting org.apache.naming as the first entry makes it the first URL context factory implementation that will be located.
For the java:comp/env Environment Naming Context (ENC), the actual class name for the URL context factory implementation is generated as org.apache.naming.java.javaURLContextFactory. If the Context.INITIAL_CONTEXT_FACTORY is currently not set for this environment, then this is set as the default INITIAL_CONTEXT_FACTORY to be used.
The configuration for a Tomcat instance is found in the confserver.xml file. This file is now processed, converting each element found into a Java object. The net result at the end of this processing is a Java object tree that mirrors this configuration file.
This conversion process is facilitated by the use of the Apache Commons Digester project (http://commons.apache.org/digester/), an open source Commons project that allows you to harness the power of a SAX parser while at the same time avoiding the complexity that comes with event driven parsing.
The Digester project was originally devised as a way of unmarshalling the struts-config.xml configuration file for Struts, but was moved out to a Commons project due to its general purpose usefulness.
The basic principle behind the Digester is very simple. It takes an XML document and a RuleSet document as inputs, and generates a graph of Java objects that represents the structure that is defined in the XML instance document.
There are three key concepts that come into play when using the Digester—a pattern, a rule, and an object stack.
As the digester parses the input XML instance document, it keeps track of the elements it visits. Each element is identified by its parent's name followed by a forward slash ('/') and then by its name.
For instance, in the example document below, the root element is represented by the pattern rolodex. Two <contact> elements are represented by the pattern rolodex/contact, the <company> elements are represented by the pattern rolodex/contact/company, and so on.
<rolodex type=paperSales>
<contact id="1">
<firstname>Damodar</firstname>
<lastname>Chetty</lastname>
<company>Software Engineering Solutions, Inc.</company>
</contact>
<contact id="2">
<firstname>John</firstname>
<lastname>Smith</lastname>
<company>Ingenuitix, Inc.</company>
</contact>
</rolodex>
A rule specifies the action(s) that the Digester should take when a particular pattern is encountered.
The common rules you will encounter are:
As objects are created, using the creational actions discussed above, Digester pushes them to the top of its internal stack. All actions typically affect the object at the top of the stack.
A creational action will automatically pop the element on the top of the stack when the end tag for the pattern is detected.
The typical sequence of actions is to create an object using a creational action, set its properties using a property setting action, and once the object is fully formed, to pop it off the top of the stack by linking it to its parent, which is usually just below it on the stack. Once the child has been popped off, the parent is once again at the top of the stack. This repeats as additional children objects are created, initialized, linked, and popped. Once all the children are processed and the parent object is fully initialized, the parent itself is popped off the stack, and we are done.
You instantiate an org.apache.commons.digester.Digester by invoking the createDigester() method of org.apache.commons.digester.xmlrules.DigesterLoader and passing it the URL for the file containing the patterns and rules.
Patterns and rules can also be specified programmatically by calling methods directly on the digester instance. However, defining them in a separate XML RuleSet instance document is much more modular, as it extracts rule configuration out of program code, making the code more readable and maintainable.
Then, you invoke the parse() method of a Digester instance and pass it the actual XML instance document. The digester uses its configured rules to convert elements in the instance document into Java objects.
The Catalina instance creates a Digester to process the server.xml file. Every element in this file is converted into an instance of the appropriate class, its properties are set based on configuration information in this file, and connections between the objects are set up, until what you are left with is a functioning framework of classes.
This ability to configure the structure of cooperating classes using a declarative approach makes it easy to customize a Tomcat installation with very little effort.
The createStartDigester() method in Catalina does the work of instantiating a new Digester and registering patterns and rules with it. The Catalina instance is then pushed to the top of the Digester stack, making it the root ancestor for all the elements parsed from the server.xml document.
The rules can be described as follows:
Pattern |
Rule |
Server |
Creational action: Instantiates an org.apache.catalina.core.StandardServer Set properties action: Copies attribute values over to the topmost object of the stack using mutator methods that are named similarly to the attribute Object linking action: Invokes setServer()to set this newly minted Server instance on the Catalina instance found on the stack. |
Server/ GlobalNamingResources |
Creational action: Instantiate an org.apache.catalina.deploy.NamingResources Set properties action: Copies attribute values from this element over to the topmost object on the stack Object linking action: Sets this newly instantiated object on the StandardServer instance at the top of the stack, by invoking its setGlobalNamingResources(). |
Server/Listener |
Creational action: Instantiate the class specified by the fully qualified class name provided as an attribute. Set properties action: Copy attributes from this element. Object linking action: Sets this instance on the StandardServer instance at the top of the stack, by invoking its addLifecycleListener() method with this new instance. |
Server/Service |
Creational action: Instantiates an org.apache.catalina.core.StandardService. Set properties action: Copy attributes from this element Object linking action: Invokes addService()on the StandardServer instance at the top of the stack passing in this newly minted instance |
Server/Service/Listener |
Creational action: Instantiate the class specified by the fully qualified class name provided as the className attribute Set properties action: Copy attributes from this element Object linking action: Invokes addLifecycleListener() on the StandardService instance at the top of the stack, passing in this listener instance |
Server/Service/Executor
|
Creational action: Instantiate the class org.apache.catalina.core.StandardThreadExecutor Set properties action: Copy attributes for this element Object linking action: Invokes addExecutor() with this instance, on the StandardService instance at the top of the stack |
Server/Service/Connector
|
Creational action: Instantiate the class org.apache.catalina.startup.ConnectorCreateRule Set properties action: Copy all attributes for this element except for the executor property Object linking action: Invokes addConnector(), passing in this instance, on the StandardService instance at the top of the stack |
Server/Service/Connector/Listener
|
Creational action: Instantiate the class specified by the fully qualified class name provided as the className attribute Set properties action: Copy attributes from this element Object linking action: Invokes addLifecycleListener(), passing in this instance, on the Connector instance at the top of the stack |
Server/Service/Engine
|
Set the Engine instance's parent class loader to the serverLoader |