    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