001 /* $Id: FromXmlRuleSet.java 471661 2006-11-06 08:09:25Z skitching $
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019
020 package org.apache.commons.digester.xmlrules;
021
022
023 import java.net.URL;
024
025 import org.apache.commons.digester.Digester;
026 import org.apache.commons.digester.RuleSetBase;
027
028 import org.xml.sax.InputSource;
029
030 /**
031 * A Digester rule set where the rules come from an XML file.
032 *
033 * @since 1.2
034 */
035 public class FromXmlRuleSet extends RuleSetBase {
036
037 public static final String DIGESTER_DTD_PATH = "org/apache/commons/digester/xmlrules/digester-rules.dtd";
038
039 /**
040 * The file containing the Digester rules, in XML.
041 */
042 private XMLRulesLoader rulesLoader;
043
044 /**
045 * The rule set for parsing the Digester rules
046 */
047 private DigesterRuleParser parser;
048
049 /**
050 * The digester for loading the rules xml.
051 */
052 private Digester rulesDigester;
053
054 /**
055 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
056 * rulesDigester.
057 * @param rulesXml the path to the XML document defining the Digester rules
058 */
059 public FromXmlRuleSet(URL rulesXml) {
060 this(rulesXml, new DigesterRuleParser(), new Digester());
061 }
062
063 /**
064 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
065 * a ruleDigester for loading the rules xml.
066 * @param rulesXml the path to the XML document defining the Digester rules
067 * @param rulesDigester the digester to read the rules xml.
068 */
069 public FromXmlRuleSet(URL rulesXml, Digester rulesDigester) {
070 this(rulesXml, new DigesterRuleParser(), rulesDigester);
071 }
072
073 /**
074 * @param rulesXml the path to the XML document defining the Digester rules
075 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
076 */
077 public FromXmlRuleSet(URL rulesXml, DigesterRuleParser parser) {
078 this(rulesXml, parser, new Digester());
079 }
080
081 /**
082 * @param rulesXml the path to the XML document defining the Digester rules
083 * @param parser an instance of DigesterRuleParser, for parsing the rules from XML
084 * @param rulesDigester the digester used to load the Xml rules.
085 */
086 public FromXmlRuleSet(URL rulesXml, DigesterRuleParser parser, Digester rulesDigester) {
087 init(new URLXMLRulesLoader(rulesXml), parser, rulesDigester);
088 }
089
090 /**
091 * Constructs a FromXmlRuleSet using the default DigesterRuleParser and
092 * rulesDigester.
093 * @param inputSource load the xml rules from this InputSource
094 */
095 public FromXmlRuleSet(InputSource inputSource) {
096 this(inputSource, new DigesterRuleParser(), new Digester());
097 }
098
099 /**
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