1 /* $Id: FromXmlRuleSet.java 471661 2006-11-06 08:09:25Z skitching $
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19
20 package org.apache.commons.digester.xmlrules;
21
22
23 import java.net.URL;
24
25 import org.apache.commons.digester.Digester;
26 import org.apache.commons.digester.RuleSetBase;
27
28 import org.xml.sax.InputSource;
29
30 /**
31 * A Digester rule set where the rules come from an XML file.
32 *
33 * @since 1.2
34 */
35 public class FromXmlRuleSet extends RuleSetBase {
36
37 public static final String DIGESTER_DTD_PATH = "org/apache/commons/digester/xmlrules/digester-rules.dtd";
38
39 /**
40 * The file containing the Digester rules, in XML.
41 */
42 private XMLRulesLoader rulesLoader;
43
44 /**
45 * The rule set for parsing the Digester rules
46 */
47 private DigesterRuleParser parser;
48
49 /**
50 * The digester for loading the rules xml.
51 */
52 private Digester rulesDigester;
53
54 /**
55 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
56 * rulesDigester.
57 * @param rulesXml the path to the XML document defining the Digester rules
58 */
59 public FromXmlRuleSet(URL rulesXml) {
60 this(rulesXml, new DigesterRuleParser(), new Digester());
61 }
62
63 /**
64 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
65 * a ruleDigester for loading the rules xml.
66 * @param rulesXml the path to the XML document defining the Digester rules
67 * @param rulesDigester the digester to read the rules xml.
68 */
69 public FromXmlRuleSet(URL rulesXml, Digester rulesDigester) {
70 this(rulesXml, new DigesterRuleParser(), rulesDigester);
71 }
72
73 /**
74 * @param rulesXml the path to the XML document defining the Digester rules
75 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
76 */
77 public FromXmlRuleSet(URL rulesXml, DigesterRuleParser parser) {
78 this(rulesXml, parser, new Digester());
79 }
80
81 /**
82 * @param rulesXml the path to the XML document defining the Digester rules
83 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
84 * @param rulesDigester the digester used to load the Xml rules.
85 */
86 public FromXmlRuleSet(URL rulesXml, DigesterRuleParser parser, Digester rulesDigester) {
87 init(new URLXMLRulesLoader(rulesXml), parser, rulesDigester);
88 }
89
90 /**
91 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
92 * rulesDigester.
93 * @param inputSource load the xml rules from this InputSource
94 */
95 public FromXmlRuleSet(InputSource inputSource) {
96 this(inputSource, new DigesterRuleParser(), new Digester());
97 }
98
99 /**
100 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
101 * a ruleDigester for loading the rules xml.
102 * @param inputSource load the xml rules from this InputSource
103 * @param rulesDigester the digester to read the rules xml.
104 */
105 public FromXmlRuleSet(InputSource inputSource, Digester rulesDigester) {
106 this(inputSource, new DigesterRuleParser(), rulesDigester);
107 }
108
109 /**
110 * @param inputSource load the xml rules from this InputSource
111 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
112 */
113 public FromXmlRuleSet(InputSource inputSource, DigesterRuleParser parser) {
114 this(inputSource, parser, new Digester());
115 }
116
117 /**
118 * @param inputSource load the xml rules from this InputSource
119 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
120 * @param rulesDigester the digester used to load the Xml rules.
121 */
122 public FromXmlRuleSet(InputSource inputSource, DigesterRuleParser parser, Digester rulesDigester) {
123 init(new InputSourceXMLRulesLoader(inputSource), parser, rulesDigester);
124 }
125
126 /**
127 * Base constructor
128 */
129 private void init(XMLRulesLoader rulesLoader, DigesterRuleParser parser, Digester rulesDigester) {
130 this.rulesLoader = rulesLoader;
131 this.parser = parser;
132 this.rulesDigester = rulesDigester;
133 }
134
135 /**
136 * Adds to the digester the set of Rule instances defined in the
137 * XML file for this rule set.
138 * @see org.apache.commons.digester.RuleSetBase
139 */
140 public void addRuleInstances(org.apache.commons.digester.Digester digester) throws XmlLoadException {
141 addRuleInstances(digester, null);
142 }
143
144 /**
145 * Adds to the digester the set of Rule instances defined in the
146 * XML file for this rule set.
147 * <p>
148 * Note that this method doesn't have a matching one on the DigesterLoader
149 * class, because it is not expected to be widely used, and DigesterLoader's
150 * load method is already heavily overloaded.
151 *
152 * @param digester is the digester that rules will be added to.
153 * @param basePath is a path that will be prefixed to every
154 * pattern string defined in the xmlrules input file.
155 *
156 * @see org.apache.commons.digester.RuleSetBase
157 * @since 1.6
158 */
159 public void addRuleInstances(
160 org.apache.commons.digester.Digester digester,
161 String basePath)
162 throws XmlLoadException {
163
164 URL dtdURL = getClass().getClassLoader().getResource(DIGESTER_DTD_PATH);
165 if (dtdURL == null) {
166 throw new XmlLoadException("Cannot find resource \"" +
167 DIGESTER_DTD_PATH + "\"");
168 }
169 parser.setDigesterRulesDTD(dtdURL.toString());
170 parser.setTarget(digester);
171 parser.setBasePath(basePath);
172
173 rulesDigester.addRuleSet(parser);
174 rulesDigester.push(parser);
175
176 rulesLoader.loadRules();
177 }
178
179 /**
180 * Worker class encapsulates loading mechanisms.
181 * Private until some reason is found to make it public.
182 */
183 private abstract static class XMLRulesLoader {
184 /** Load rules now */
185 public abstract void loadRules() throws XmlLoadException;
186 }
187
188 /** Loads XMLRules from an URL */
189 private class URLXMLRulesLoader extends XMLRulesLoader {
190 private URL url;
191 public URLXMLRulesLoader(URL url) {
192 this.url = url;
193 }
194
195 public void loadRules() throws XmlLoadException {
196 try {
197 rulesDigester.parse(url.openStream());
198 } catch (Exception ex) {
199 throw new XmlLoadException(ex);
200 }
201 }
202 }
203
204 /** Loads XMLRules from an InputSource */
205 private class InputSourceXMLRulesLoader extends XMLRulesLoader {
206 private InputSource inputSource;
207 public InputSourceXMLRulesLoader(InputSource inputSource) {
208 this.inputSource = inputSource;
209 }
210
211 public void loadRules() throws XmlLoadException {
212 try {
213 rulesDigester.parse(inputSource);
214 } catch (Exception ex) {
215 throw new XmlLoadException(ex);
216 }
217 }
218 }
219 }
220