com.dotosoft.dot4command.config.xml.XmlConfigParser.java Source code

Java tutorial

Introduction

Here is the source code for com.dotosoft.dot4command.config.xml.XmlConfigParser.java

Source

/*
   Copyright 2015 Denis Prasetio
       
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
       
   http://www.apache.org/licenses/LICENSE-2.0
       
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package com.dotosoft.dot4command.config.xml;

import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.RuleSet;

import com.dotosoft.dot4command.chain.CatalogFactory;
import com.dotosoft.dot4command.config.ChainConfigurationException;
import com.dotosoft.dot4command.config.ConfigParser;
import com.dotosoft.dot4command.impl.CatalogFactoryBase;

import java.net.URL;
import java.util.Map;

/**
 * <p>Class to parse the contents of an XML configuration file (using
 * Commons Digester) that defines and configures commands and command chains
 * to be registered in a {@link com.dotosoft.dot4command.chain.Catalog}.  Advanced users can configure the
 * detailed parsing behavior by configuring the properties of an instance
 * of this class prior to calling the <code>parse()</code> method.  It
 * is legal to call the <code>parse()</code> method more than once, in order
 * to parse more than one configuration document.</p>
 *
 * @version $Id: ConfigParser.java 1364104 2012-07-21 14:25:54Z elijah $
 */
public class XmlConfigParser implements ConfigParser {
    // ----------------------------------------------------- Instance Variables

    /**
     * <p>The <code>RuleSet</code> to be used for configuring our Digester
     * parsing rules.</p>
     */
    private RuleSet ruleSet = new ConfigRuleSet();

    /**
     * <p>Should Digester use the context class loader?
     */
    private boolean useContextClassLoader = true;

    // ------------------------------------------------------------- Constructor

    public XmlConfigParser() {
    }

    public XmlConfigParser(String ruleSet, ClassLoader loader) {
        if (ruleSet == null) {
            throw new IllegalArgumentException(
                    "ConfigParser can't be " + "instantiated with a null ruleSet class name");
        }
        if (loader == null) {
            throw new IllegalArgumentException(
                    "ConfigParser can't be " + "instantiated with a null class loader reference");
        }

        try {
            Class<?> clazz = loader.loadClass(ruleSet);
            setRuleSet((RuleSet) clazz.newInstance());
        } catch (Exception e) {
            throw new RuntimeException(
                    "Exception initializing RuleSet '" + ruleSet + "' instance: " + e.getMessage());
        }
    }

    // ------------------------------------------------------------- Properties

    /**
     * <p>Return the <code>Digester</code> instance to be used for
     * parsing, creating one if necessary.</p>
     * @return A Digester instance.
     */
    public Digester getDigester() {
        Digester digester = new Digester();
        RuleSet ruleSet = getRuleSet();
        digester.setNamespaceAware(ruleSet.getNamespaceURI() != null);
        digester.setUseContextClassLoader(getUseContextClassLoader());
        digester.setValidating(false);
        digester.addRuleSet(ruleSet);
        return digester;
    }

    /**
     * <p>Return the <code>RuleSet</code> to be used for configuring
     * our <code>Digester</code> parsing rules, creating one if necessary.</p>
     * @return The RuleSet for configuring a Digester instance.
     */
    public RuleSet getRuleSet() {
        return ruleSet;
    }

    /**
     * <p>Set the <code>RuleSet</code> to be used for configuring
     * our <code>Digester</code> parsing rules.</p>
     *
     * @param ruleSet The new RuleSet to use
     */
    public void setRuleSet(RuleSet ruleSet) {
        this.ruleSet = ruleSet;
    }

    /**
     * <p>Return the "use context class loader" flag.  If set to
     * <code>true</code>, Digester will attempt to instantiate new
     * command and chain instances from the context class loader.</p>
     * @return <code>true</code> if Digester should use the context class loader.
     */
    public boolean getUseContextClassLoader() {
        return this.useContextClassLoader;
    }

    /**
     * <p>Set the "use context class loader" flag.</p>
     *
     * @param useContextClassLoader The new flag value
     */
    public void setUseContextClassLoader(boolean useContextClassLoader) {
        this.useContextClassLoader = useContextClassLoader;
    }

    // --------------------------------------------------------- Public Methods

    /**
     * <p>Parse the XML document at the specified URL using the configured
     * <code>RuleSet</code>, registering catalogs with nested chains and
     * commands as they are encountered.  Use this method <strong>only</strong>
     * if you have included one or more <code>factory</code> elements in your
     * configuration resource.</p>
     *
     * @param <K> the type of keys maintained by the context associated with this command
     * @param <V> the type of mapped values
     * @param <C> Type of the context associated with this command
     * @param url <code>URL</code> of the XML document to be parsed
     * @return a CatalogFactory instance parsed from the given location
     * @exception ChainConfigurationException if a parsing error occurs
     */
    public <K extends String, V extends Object, C extends Map<K, V>> CatalogFactory<K, V, C> parse(URL url) {
        // Prepare our Digester instance
        Digester digester = getDigester();
        digester.clear();

        // Parse the configuration document
        try {
            digester.parse(url);
        } catch (Exception e) {
            String msg = String.format("Error parsing digester configuration at url: %s", url);
            throw new ChainConfigurationException(msg, e);
        }
        // FIXME get rid of singleton pattern and create a new instance here
        return CatalogFactoryBase.getInstance();
    }

}