001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.chain.config;
018    
019    
020    import java.net.URL;
021    import org.apache.commons.chain.Catalog;
022    import org.apache.commons.digester.Digester;
023    import org.apache.commons.digester.RuleSet;
024    
025    
026    /**
027     * <p>Class to parse the contents of an XML configuration file (using
028     * Commons Digester) that defines and configures commands and command chains
029     * to be registered in a {@link Catalog}.  Advanced users can configure the
030     * detailed parsing behavior by configuring the properties of an instance
031     * of this class prior to calling the <code>parse()</code> method.  It
032     * is legal to call the <code>parse()</code> method more than once, in order
033     * to parse more than one configuration document.</p>
034     *
035     * @author Craig R. McClanahan
036     * @version $Revision: 482967 $ $Date: 2006-12-06 08:43:48 +0000 (Wed, 06 Dec 2006) $
037     */
038    public class ConfigParser {
039    
040    
041        // ----------------------------------------------------- Instance Variables
042    
043    
044        /**
045         * <p>The <code>Digester</code> to be used for parsing.</p>
046         */
047        private Digester digester = null;
048    
049    
050        /**
051         * <p>The <code>RuleSet</code> to be used for configuring our Digester
052         * parsing rules.</p>
053         */
054        private RuleSet ruleSet = null;
055    
056    
057        /**
058         * <p>Should Digester use the context class loader?
059         */
060        private boolean useContextClassLoader = true;
061    
062    
063        // ------------------------------------------------------------- Properties
064    
065    
066        /**
067         * <p>Return the <code>Digester</code> instance to be used for
068         * parsing, creating one if necessary.</p>
069         * @return A Digester instance.
070         */
071        public Digester getDigester() {
072    
073            if (digester == null) {
074                digester = new Digester();
075                RuleSet ruleSet = getRuleSet();
076                digester.setNamespaceAware(ruleSet.getNamespaceURI() != null);
077                digester.setUseContextClassLoader(getUseContextClassLoader());
078                digester.setValidating(false);
079                digester.addRuleSet(ruleSet);
080            }
081            return (digester);
082    
083        }
084    
085    
086        /**
087         * <p>Return the <code>RuleSet</code> to be used for configuring
088         * our <code>Digester</code> parsing rules, creating one if necessary.</p>
089         * @return The RuleSet for configuring a Digester instance.
090         */
091        public RuleSet getRuleSet() {
092    
093            if (ruleSet == null) {
094                ruleSet = new ConfigRuleSet();
095            }
096            return (ruleSet);
097    
098        }
099    
100    
101        /**
102         * <p>Set the <code>RuleSet</code> to be used for configuring
103         * our <code>Digester</code> parsing rules.</p>
104         *
105         * @param ruleSet The new RuleSet to use
106         */
107        public void setRuleSet(RuleSet ruleSet) {
108    
109            this.digester = null;
110            this.ruleSet = ruleSet;
111    
112        }
113    
114    
115        /**
116         * <p>Return the "use context class loader" flag.  If set to
117         * <code>true</code>, Digester will attempt to instantiate new
118         * command and chain instances from the context class loader.</p>
119         * @return <code>true</code> if Digester should use the context class loader.
120         */
121        public boolean getUseContextClassLoader() {
122    
123            return (this.useContextClassLoader);
124    
125        }
126    
127    
128        /**
129         * <p>Set the "use context class loader" flag.</p>
130         *
131         * @param useContextClassLoader The new flag value
132         */
133        public void setUseContextClassLoader(boolean useContextClassLoader) {
134    
135            this.useContextClassLoader = useContextClassLoader;
136    
137        }
138    
139    
140        // --------------------------------------------------------- Public Methods
141    
142    
143        /**
144         * <p>Parse the XML document at the specified URL, using the configured
145         * <code>RuleSet</code>, registering top level commands into the specified
146         * {@link Catalog}.  Use this method <strong>only</strong> if you have
147         * <strong>NOT</strong> included any <code>factory</code> element in your
148         * configuration resource, and wish to supply the catalog explictly.</p>
149         *
150         * @param catalog {@link Catalog} into which configured chains are
151         *  to be registered
152         * @param url <code>URL</code> of the XML document to be parsed
153         *
154         * @exception Exception if a parsing error occurs
155         *
156         * @deprecated Use parse(URL) on a configuration resource with "factory"
157         *  element(s) embedded
158         */
159        public void parse(Catalog catalog, URL url) throws Exception {
160    
161            // Prepare our Digester instance
162            Digester digester = getDigester();
163            digester.clear();
164            digester.push(catalog);
165    
166            // Parse the configuration document
167            digester.parse(url);
168    
169        }
170    
171    
172        /**
173         * <p>Parse the XML document at the specified URL using the configured
174         * <code>RuleSet</code>, registering catalogs with nested chains and
175         * commands as they are encountered.  Use this method <strong>only</strong>
176         * if you have included one or more <code>factory</code> elements in your
177         * configuration resource.</p>
178         *
179         * @param url <code>URL</code> of the XML document to be parsed
180         *
181         * @exception Exception if a parsing error occurs
182         */
183        public void parse(URL url) throws Exception {
184    
185            // Prepare our Digester instance
186            Digester digester = getDigester();
187            digester.clear();
188    
189            // Parse the configuration document
190            digester.parse(url);
191    
192        }
193    
194    
195    }