Detailed understanding of Catalina.createDgester method

This method mainly sets up (this method is very important and important to understand, although I haven’t learned design patterns yet.)

1. Create a StandardServer instance when encountering the tag

Set related properties inside the StandardServer class

and call the Catalina.setServer() method to set the server

2. When encountering the sub-tag ==> of the tag corresponding to the matching pattern “Server/Listener”

Create a Listener instance and create a class name by getting the value of the attribute className through .

Call StandardServer’s addLifecycleListener() to add a listener to the server

3. When the tag is used, the matching mode is: “Server/Service”. Create a StandardService instance, put it in the Stack stack, and call the addSetProperties method to set relevant properties for the StandardService.

digester.addSetNext("Server/Service",
                            "addService",
                            "org.apache.catalina.Service");

Call the parent=stack.peek(1) of Service, that is, the addService method of the Server object is associated with the Server.

4. Set the listener for Service as in 2.

5. The tag matches the pattern: “Server/Service/Executor” to generate a StandardThreadExecutor instance.

Set the properties of StandardThreadExecutor

Call the addExecutor method of its parent class Service to associate with Service

6. Call the addRule method as above,

pattern:”Server/Service/Connector”==>Create a Connector instance, set properties, and call StandardService.addConnector(). Set a listener for the Connector

7. Call the addRuleSet() method

digester.addRuleSet(new NamingRuleSet(“Server/GlobalNamingResources/”));
digester.addRuleSet(new EngineRuleSet(“Server/Service/”));
digester.addRuleSet(new HostRuleSet(“Server/Service/Engine/”));
digester.addRuleSet(new ContextRuleSet(“Server/Service/Engine/Host/”));
addClusterRuleSet(digester, “Server/Service/Engine/Host/Cluster/”);
digester.addRuleSet(new NamingRuleSet(“Server/Service/Engine/Host/Context/”));

Same as 6

,, Setting Engine

,EngineRuleSet(String prefix) will be called inside EngineRuleSet.addRuleInstances() when it encounters the mode prefix + “Engine”, that is, “Server/Service/Engine”

The three methods addObjectCreate, addSetProperties, and addRule create StandardEngine instances, set properties, and call Service. setContainer() method.

Create a SimpleTcpCluster instance and call the Engine.setCluster() method

Add a listener to Engine,

Create a realm object instance and call the corresponding method to associate with Engine.

Create an AccessLogValve log object (output the log to a .txt file), set properties, and associate it with the engine.

,, set host

Create StandardHost, set properties, and set listeners: HostConfig

Call Container. addChild() where Container is associated with Engine

,, set context

Create StandardContext, set properties, and set listeners: ContextConfig

Call Container. addChild() where Container is associated with Host

Create WebappLoader and associate it with StandardContext

Create StandardManager and associate it with StandardContext

Create a store storage class and associate it with StandardContext

Create StandardSessionIdGenerator and associate it with StandardManager

Create ApplicationParameter and associate it with StandardContext

Create a realm object instance and associate it with StandardContext

Create StandardRoot and associate it with StandardContext

?context==》WebResourceRoot==StandardRoot settings

org.apache.catalina.webresources.StandardRoot provides various resources implementation classes

Create a WebResourceSet and associate it with StandardRoot

(The implementation classes of WebResourceSet include WarResourceSet, JarResourceSet, JarWarResourceSet, DirResourceSet, FileResourceSet, etc.)

Mainly set the instances of the three variables preResources, jarResources, and postResources of StandardRoot.

Create ContextResourceLink and associate it with StandardContext

Create AccessLogValve and associate it with StandardContext

Create StandardJarScanner, Associate with StandardContext

Create StandardJarScanFilter and associate it with StandardJarScanner

Create LegacyCookieProcessor, associated with StandardContext

Note: The entire process of creating a specific object has been explained above. The following is an understanding of some methods of Digester. Can be ignored!

protected Digester createStartDgester() {
        long t1=System.currentTimeMillis();
        // Initialize the digester
        Digester digester = new Digester();
        digester.setValidating(false);
        digester.setRulesValidation(true);
        HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
        ArrayList<String> attrs = new ArrayList<>();
        attrs.add("className");
        fakeAttributes.put(Object.class, attrs);
        digester.setFakeAttributes(fakeAttributes);
        digester.setUseContextClassLoader(true);

        // Configure the actions we will be using
        digester.addObjectCreate("Server",
                                 "org.apache.catalina.core.StandardServer",
                                 "className");
        digester.addSetProperties("Server");
        digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");

        digester.addObjectCreate("Server/GlobalNamingResources",
                                 "org.apache.catalina.deploy.NamingResourcesImpl");
        digester.addSetProperties("Server/GlobalNamingResources");
        digester.addSetNext("Server/GlobalNamingResources",
                            "setGlobalNamingResources",
                            "org.apache.catalina.deploy.NamingResourcesImpl");

        digester.addObjectCreate("Server/Listener",
                                 null, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Listener");
        digester.addSetNext("Server/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");

        digester.addObjectCreate("Server/Service",
                                 "org.apache.catalina.core.StandardService",
                                 "className");
        digester.addSetProperties("Server/Service");
        digester.addSetNext("Server/Service",
                            "addService",
                            "org.apache.catalina.Service");

        digester.addObjectCreate("Server/Service/Listener",
                                 null, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Service/Listener");
        digester.addSetNext("Server/Service/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");

        //Executor
        digester.addObjectCreate("Server/Service/Executor",
                         "org.apache.catalina.core.StandardThreadExecutor",
                         "className");
        digester.addSetProperties("Server/Service/Executor");

        digester.addSetNext("Server/Service/Executor",
                            "addExecutor",
                            "org.apache.catalina.Executor");


        digester.addRule("Server/Service/Connector",
                         new ConnectorCreateRule());
        digester.addRule("Server/Service/Connector",
                         new SetAllPropertiesRule(new String[]{"executor"}));
        digester.addSetNext("Server/Service/Connector",
                            "addConnector",
                            "org.apache.catalina.connector.Connector");


        digester.addObjectCreate("Server/Service/Connector/Listener",
                                 null, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Service/Connector/Listener");
        digester.addSetNext("Server/Service/Connector/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");

        // Add RuleSets for nested elements
        digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
        digester.addRuleSet(new EngineRuleSet("Server/Service/"));
        digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
        digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
        addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
        digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));

        // When the 'engine' is found, set the parentClassLoader.
        digester.addRule("Server/Service/Engine",
                         new SetParentClassLoaderRule(parentClassLoader));
        addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");

        long t2=System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("Digester for server.xml created " + ( t2-t1 ));
        }
        return (digester);

    }

addObjectCreate()//Add an “object create” rule for the specified parameters. Add an object creation rule. When encountering an element with a starting tag, initialize an instance object and push it onto the stack

addSetProperties()//Add a “set properties” rule for the specified parameters. Add a set property rule. When encountering a certain property name, use setter to assign the value

like

digester.addSetProperties("Server");

Corresponding label

The matching pattern encountered is: Server. The addSetProperties method will reflect and call the setPort(int) and setShutdown(String) methods of the StandardServer object to set properties

Digester.addSetNext(
String pattern,
String methodName,
String paramType)

//Add a “set next” rule for the specified parameters. Add set next rule. Action when encountering the next label.

That is, reflection calls the method named methodName.

digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");<br>Called when the next tag of the <Server> tag is encountered

The addSetNext method will call the SetNextRule.end() method and the setServer() method of the parent object of the current top object (the next element of the top object) will be called

When the StandardServer object is pushed onto the stack, the Catalina object already exists in the stack ===> Set in the Catalina.load() method

So the parent object of StandardServer is Catalina, that is, the Catalina.setServer() method is called to set the server attribute.

addRule: Call the rule’s begin, body, end, and finish methods to parse xml, push and pop the stack to assign values to the object

addRuleSet: Call addRuleInstances to parse xml tags

addObjectCreate(pattern, className, attributeName)

1,

Add an “object create” rule for the specified parameters to add an object creation rule for the specified parameters.

Parameters:

pattern Element matching patternElement matching pattern
className Default Java class name to be createdThe name of the java class to be created
attributeName Attribute name that optionally overrides the default Java class name to be created Attribute name can override the default Java class name to be created
Get the attributes attribute name in the xml file: className and replace the second parameter with the corresponding value
begin(String namespace, String name, Attributes attributes) method of ObjectCreateRule.java class,<br>This method will load Class by class name and then call class.newInstance() to generate a class instance, and finally put it on the top of the digest object stack digester.push(instance);<br>String realClassName = className;
        if (attributeName != null) {
            String value = attributes.getValue(attributeName);
            if (value != null) {
                realClassName = value;
            }
        }

Digester.addObjectCreate(String pattern, String className, String attributeName)

This addObjectCreate() method in turn calls the addRule() method

2,

Register a new Rule matching the specified pattern. This method sets the Digester property on the rule.

Parameters:

pattern Element matching pattern
rule Rule to be registered The rule here uses ObjectCreateRule

Digester.addRule(String pattern, Rule rule)

addRule(pattern, new ObjectCreateRule(className, attributeName));

public void addRule(String pattern, Rule rule) {

        rule.setDgester(this); Setting digester will save the instance of the created object
        <strong>getRules().add(pattern, rule); This will return the implementation class of the Rules interface. Then call Rules.add() to add a Rule instance</strong>

    }<br>Note: Rules: is an interface public interface Rules<br>The public interface defines a collection of rule instances (and corresponding matching patterns) and the implementation of matching strategies.<br>This strategy selects rules that match a specific pattern of nested elements found during parsing.<br>Rule: It is an abstract class public abstract class Rule

Explanation of ObjectCreateRule class

Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the object will be popped

The Rule implementation class creates a new object and pushes it onto the object stack. When the element is completed, the object will be popped

3. RuleBase.add(pattern, rule)

public void add(String pattern, Rule rule) {
        // to help users who accidentally add '/' to the end of their patterns
        int patternLength = pattern.length();
        if (patternLength>1 & amp; & amp; pattern.endsWith("/")) {
            pattern = pattern.substring(0, patternLength-1);
        }


        List<Rule> list = cache.get(pattern);
        if (list == null) {
            list = new ArrayList<>();
            cache.put(pattern, list);
        }
        list.add(rule);
        rules.add(rule);
        if (this.digester != null) {
            rule.setDigester(this.digester);
        }
        if (this.namespaceURI != null) {
            rule.setNamespaceURI(this.namespaceURI);
        }

    }

The above method uses the HashMap> type variable cache to store the pattern and Rule collections, and uses the rules collection to store the newly added rules rules.add(rule)

Digester.addSetProperties(String pattern)

This method is similar to the addObjectCreate method in the following order:

1addRule(pattern, new SetPropertiesRule());

2getRules().add(pattern, rule);

3RulesBase.add(pattern, rule)

Digester.addSetNext(String pattern, String methodName, String paramType)

1addRule(pattern, new SetNextRule(methodName, paramType));

2getRules().add(pattern, rule);

3RulesBase.add(pattern, rule)

Note:

Only when the closing tag of the element is encountered, the object instance represented by the tag will be popped from the stack.