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 }