1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.chain.config;
18
19 import java.net.URL;
20
21 import org.apache.commons.chain.Catalog;
22 import org.apache.commons.digester.Digester;
23 import org.apache.commons.digester.RuleSet;
24
25 /**
26 * Class to parse the contents of an XML configuration file (using
27 * Commons Digester) that defines and configures commands and command chains
28 * to be registered in a {@link Catalog}. Advanced users can configure the
29 * detailed parsing behavior by configuring the properties of an instance
30 * of this class prior to calling the {@code parse()} method. It
31 * is legal to call the {@code parse()} method more than once, in order
32 * to parse more than one configuration document.
33 *
34 * @author Craig R. McClanahan
35 * @version $Revision$ $Date$
36 */
37 public class ConfigParser {
38
39 // ----------------------------------------------------- Instance Variables
40
41 /**
42 * The {@code Digester} to be used for parsing.
43 */
44 private Digester digester = null;
45
46 /**
47 * The {@code RuleSet} to be used for configuring our Digester
48 * parsing rules.
49 */
50 private RuleSet ruleSet = null;
51
52 /**
53 * Should Digester use the context class loader?
54 */
55 private boolean useContextClassLoader = true;
56
57 // ----------------------------------------------------------- Constructors
58
59 /**
60 * The Default-Constructor for this class.
61 */
62 public ConfigParser() {
63 }
64
65 // ------------------------------------------------------------- Properties
66
67 /**
68 * Return the {@code Digester} instance to be used for
69 * parsing, creating one if necessary.
70 *
71 * @return A Digester instance.
72 */
73 public Digester getDigester() {
74 if (digester == null) {
75 digester = new Digester();
76 RuleSet ruleSet = getRuleSet();
77 digester.setNamespaceAware(ruleSet.getNamespaceURI() != null);
78 digester.setUseContextClassLoader(getUseContextClassLoader());
79 digester.setValidating(false);
80 digester.addRuleSet(ruleSet);
81 }
82 return digester;
83 }
84
85 /**
86 * Return the {@code RuleSet} to be used for configuring
87 * our {@code Digester} parsing rules, creating one if necessary.
88 *
89 * @return The RuleSet for configuring a Digester instance.
90 */
91 public RuleSet getRuleSet() {
92 if (ruleSet == null) {
93 ruleSet = new ConfigRuleSet();
94 }
95 return ruleSet;
96 }
97
98 /**
99 * Set the {@code RuleSet} to be used for configuring
100 * our {@code Digester} parsing rules.
101 *
102 * @param ruleSet The new RuleSet to use
103 */
104 public void setRuleSet(RuleSet ruleSet) {
105 this.digester = null;
106 this.ruleSet = ruleSet;
107 }
108
109 /**
110 * Return the "use context class loader" flag. If set to
111 * {@code true}, Digester will attempt to instantiate new
112 * command and chain instances from the context class loader.
113 *
114 * @return {@code true} if Digester should use the context class loader.
115 */
116 public boolean getUseContextClassLoader() {
117 return this.useContextClassLoader;
118 }
119
120 /**
121 * Set the "use context class loader" flag.
122 *
123 * @param useContextClassLoader The new flag value
124 */
125 public void setUseContextClassLoader(boolean useContextClassLoader) {
126 this.useContextClassLoader = useContextClassLoader;
127 }
128
129 // --------------------------------------------------------- Public Methods
130
131 /**
132 * Parse the XML document at the specified URL, using the configured
133 * {@code RuleSet}, 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} element in your
136 * configuration resource, and wish to supply the catalog explicitly.
137 *
138 * @param catalog {@link Catalog} into which configured chains are
139 * to be registered
140 * @param url {@code URL} of the XML document to be parsed
141 *
142 * @throws Exception if a parsing error occurs
143 *
144 * @deprecated Use parse(URL) on a configuration resource with "factory"
145 * element(s) embedded
146 */
147 @Deprecated
148 public void parse(Catalog<?> catalog, URL url) throws Exception {
149 // Prepare our Digester instance
150 Digester digester = getDigester();
151 digester.clear();
152 digester.push(catalog);
153
154 // Parse the configuration document
155 digester.parse(url);
156 }
157
158 /**
159 * Parse the XML document at the specified URL using the configured
160 * {@code RuleSet}, registering catalogs with nested chains and
161 * commands as they are encountered. Use this method <strong>only</strong>
162 * if you have included one or more {@code factory} elements in your
163 * configuration resource.
164 *
165 * @param url {@code URL} of the XML document to be parsed
166 *
167 * @throws Exception if a parsing error occurs
168 */
169 public void parse(URL url) throws Exception {
170 // Prepare our Digester instance
171 Digester digester = getDigester();
172 digester.clear();
173
174 // Parse the configuration document
175 digester.parse(url);
176 }
177 }