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