⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 digesterruleparser.java

📁 JAVA 文章管理系统源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* $Id: DigesterRuleParser.java,v 1.29.2.1 2004/07/30 20:11:01 rdonkin Exp $
 *
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 


package org.apache.commons.digester.xmlrules;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.commons.beanutils.ConvertUtils;

import org.apache.commons.collections.ArrayStack;

import org.apache.commons.digester.AbstractObjectCreationFactory;
import org.apache.commons.digester.BeanPropertySetterRule;
import org.apache.commons.digester.CallMethodRule;
import org.apache.commons.digester.CallParamRule;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.FactoryCreateRule;
import org.apache.commons.digester.ObjectCreateRule;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.RuleSetBase;
import org.apache.commons.digester.Rules;
import org.apache.commons.digester.SetNextRule;
import org.apache.commons.digester.SetPropertiesRule;
import org.apache.commons.digester.SetPropertyRule;
import org.apache.commons.digester.SetRootRule;
import org.apache.commons.digester.SetTopRule;
import org.apache.commons.digester.ObjectParamRule;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;


/**
 * This is a RuleSet that parses XML into Digester rules, and then
 * adds those rules to a 'target' Digester.
 *
 * @since 1.2
 */

public class DigesterRuleParser extends RuleSetBase {
    
    public static final String DIGESTER_PUBLIC_ID = "-//Jakarta Apache //DTD digester-rules XML V1.0//EN";
    
    /**
     * path to the DTD
     */
    private String digesterDtdUrl;
    
    /**
     * This is the digester to which we are adding the rules that we parse
     * from the Rules XML document.
     */
    protected Digester targetDigester;

    /** See {@link #setBasePath}. */
    protected String basePath = "";
    
    /**
     * A stack whose toString method returns a '/'-separated concatenation
     * of all the elements in the stack.
     */
    protected class PatternStack extends ArrayStack {
        public String toString() {
            StringBuffer str = new StringBuffer();
            for (int i = 0; i < size(); i++) {
                String elem = get(i).toString();
                if (elem.length() > 0) {
                    if (str.length() > 0) {
                        str.append('/');
                    }
                    str.append(elem);
                }
            }
            return str.toString();
        }
    }
    
    /**
     * A stack used to maintain the current pattern. The Rules XML document
     * type allows nesting of patterns. If an element defines a matching
     * pattern, the resulting pattern is a concatenation of that pattern with
     * all the ancestor elements' patterns. Hence the need for a stack.
     */
    protected PatternStack patternStack;
    
    /**
     * Used to detect circular includes
     */
    private Set includedFiles = new HashSet();
    
    /**
     * Constructs a DigesterRuleParser. This object will be inoperable
     * until the target digester is set, via <code>setTarget(Digester)</code>
     */
    public DigesterRuleParser() {
        patternStack = new PatternStack();
    }
    
    /**
     * Constructs a rule set for converting XML digester rule descriptions
     * into Rule objects, and adding them to the given Digester
     * @param targetDigester the Digester to add the rules to
     */
    public DigesterRuleParser(Digester targetDigester) {
        this.targetDigester = targetDigester;
        patternStack = new PatternStack();
    }
    
    /**
     * Constructs a rule set for parsing an XML digester rule file that
     * has been included within an outer XML digester rule file. In this
     * case, we must pass the pattern stack and the target digester
     * to the rule set, as well as the list of files that have already
     * been included, for cycle detection.
     * @param targetDigester the Digester to add the rules to
     * @param stack Stack containing the prefix pattern string to be prepended
     * to any pattern parsed by this rule set.
     */
    private DigesterRuleParser(Digester targetDigester,
                                PatternStack stack, Set includedFiles) {
        this.targetDigester = targetDigester;
        patternStack = stack;
        this.includedFiles = includedFiles;
    }
    
    /**
     * Sets the digester into which to add the parsed rules
     * @param d the Digester to add the rules to
     */
    public void setTarget(Digester d) {
        targetDigester = d;
    }
    
    /**
     * Set a base pattern beneath which all the rules loaded by this
     * object will be registered. If this string is not empty, and does
     * not end in a "/", then one will be added.
     *
     * @since 1.6
     */
    public void setBasePath(String path) {
        if (path == null) {
            basePath = "";
        }
        else if ((path.length() > 0) && !path.endsWith("/")) {
            basePath = path + "/";
        } else {
            basePath = path;
        }
    }

    /**
     * Sets the location of the digester rules DTD. This is the DTD used
     * to validate the rules XML file.
     */
    public void setDigesterRulesDTD(String dtdURL) {
        digesterDtdUrl = dtdURL;
    }
    
    /**
     * Returns the location of the DTD used to validate the digester rules
     * XML document.
     */
    protected String getDigesterRulesDTD() {
        //ClassLoader classLoader = getClass().getClassLoader();
        //URL url = classLoader.getResource(DIGESTER_DTD_PATH);
        //return url.toString();
        return digesterDtdUrl;
    }
    
    /**
     * Adds a rule the the target digester. After a rule has been created by
     * parsing the XML, it is added to the digester by calling this method.
     * Typically, this method is called via reflection, when executing
     * a SetNextRule, from the Digester that is parsing the rules XML.
     * @param rule a Rule to add to the target digester.
     */
    public void add(Rule rule) {
        targetDigester.addRule(
            basePath + patternStack.toString(), rule);
    }
    
    
    /**
     * Add to the given digester the set of Rule instances used to parse an XML
     * document defining Digester rules. When the digester parses an XML file,
     * it will add the resulting rules & patterns to the 'target digester'
     * that was passed in this RuleSet's constructor.<P>
     * If you extend this class to support additional rules, your implementation
     * should of this method should call this implementation first: i.e.
     * <code>super.addRuleInstances(digester);</code>
     */
    public void addRuleInstances(Digester digester) {
        final String ruleClassName = Rule.class.getName();
        digester.register(DIGESTER_PUBLIC_ID, getDigesterRulesDTD());
        
        digester.addRule("*/pattern", new PatternRule("value"));
        
        digester.addRule("*/include", new IncludeRule());
        
        digester.addFactoryCreate("*/bean-property-setter-rule", new BeanPropertySetterRuleFactory());
        digester.addRule("*/bean-property-setter-rule", new PatternRule("pattern"));
        digester.addSetNext("*/bean-property-setter-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/call-method-rule", new CallMethodRuleFactory());
        digester.addRule("*/call-method-rule", new PatternRule("pattern"));
        digester.addSetNext("*/call-method-rule", "add", ruleClassName);

        digester.addFactoryCreate("*/object-param-rule", new ObjectParamRuleFactory());
        digester.addRule("*/object-param-rule", new PatternRule("pattern"));
        digester.addSetNext("*/object-param-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/call-param-rule", new CallParamRuleFactory());
        digester.addRule("*/call-param-rule", new PatternRule("pattern"));
        digester.addSetNext("*/call-param-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/factory-create-rule", new FactoryCreateRuleFactory());
        digester.addRule("*/factory-create-rule", new PatternRule("pattern"));
        digester.addSetNext("*/factory-create-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/object-create-rule", new ObjectCreateRuleFactory());
        digester.addRule("*/object-create-rule", new PatternRule("pattern"));
        digester.addSetNext("*/object-create-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/set-properties-rule", new SetPropertiesRuleFactory());
        digester.addRule("*/set-properties-rule", new PatternRule("pattern"));
        digester.addSetNext("*/set-properties-rule", "add", ruleClassName);
        
        digester.addRule("*/set-properties-rule/alias", new SetPropertiesAliasRule());
        
        digester.addFactoryCreate("*/set-property-rule", new SetPropertyRuleFactory());
        digester.addRule("*/set-property-rule", new PatternRule("pattern"));
        digester.addSetNext("*/set-property-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/set-top-rule", new SetTopRuleFactory());
        digester.addRule("*/set-top-rule", new PatternRule("pattern"));
        digester.addSetNext("*/set-top-rule", "add", ruleClassName);
        
        digester.addFactoryCreate("*/set-next-rule", new SetNextRuleFactory());
        digester.addRule("*/set-next-rule", new PatternRule("pattern"));
        digester.addSetNext("*/set-next-rule", "add", ruleClassName);
        digester.addFactoryCreate("*/set-root-rule", new SetRootRuleFactory());
        digester.addRule("*/set-root-rule", new PatternRule("pattern"));
        digester.addSetNext("*/set-root-rule", "add", ruleClassName);
    }
    
    
    /**
     * A rule for extracting the pattern matching strings from the rules XML.
     * In the digester-rules document type, a pattern can either be declared
     * in the 'value' attribute of a <pattern> element (in which case the pattern
     * applies to all rules elements contained within the <pattern> element),
     * or it can be declared in the optional 'pattern' attribute of a rule
     * element.
     */
    private class PatternRule extends Rule {
        
        private String attrName;
        private String pattern = null;
        
        /**
         * @param attrName The name of the attribute containing the pattern
         */
        public PatternRule(String attrName) {
            super();
            this.attrName = attrName;
        }
        
        /**
         * If a pattern is defined for the attribute, push it onto the
         * pattern stack.
         */
        public void begin(Attributes attributes) {
            pattern = attributes.getValue(attrName);
            if (pattern != null) {
                patternStack.push(pattern);
            }
        }
        
        /**
         * If there was a pattern for this element, pop it off the pattern
         * stack.
         */
        public void end() {
            if (pattern != null) {
                patternStack.pop();
            }
        }
    }
    
    /**
     * A rule for including one rules XML file within another. Included files
     * behave as if they are 'macro-expanded' within the includer. This means
     * that the values of the pattern stack are prefixed to every pattern
     * in the included rules. <p>This rule will detect 'circular' includes,
     * which would result in infinite recursion. It throws a
     * CircularIncludeException when a cycle is detected, which will terminate
     * the parse.
     */
    private class IncludeRule extends Rule {
        public IncludeRule() {
            super();
        }
        
        /**
         * To include a rules xml file, we instantiate another Digester, and
         * another DigesterRulesRuleSet. We pass the
         * pattern stack and the target Digester to the new rule set, and
         * tell the Digester to parse the file.
         */
        public void begin(Attributes attributes) throws Exception {
            // The path attribute gives the URI to another digester rules xml file
            String fileName = attributes.getValue("path");
            if (fileName != null && fileName.length() > 0) {
                includeXMLRules(fileName);
            }
            
            // The class attribute gives the name of a class that implements
            // the DigesterRulesSource interface
            String className = attributes.getValue("class");
            if (className != null && className.length() > 0) {
                includeProgrammaticRules(className);
            }
        }
        
        /**
         * Creates another DigesterRuleParser, and uses it to extract the rules
         * out of the give XML file. The contents of the current pattern stack
         * will be prepended to all of the pattern strings parsed from the file.
         */
        private void includeXMLRules(String fileName)
                        throws IOException, SAXException, CircularIncludeException {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            if (cl == null) {
                cl = DigesterRuleParser.this.getClass().getClassLoader();
            }
            URL fileURL = cl.getResource(fileName);
            if (fileURL == null) {
                throw new FileNotFoundException("File \"" + fileName + "\" not found.");
            }
            fileName = fileURL.toExternalForm();
            if (includedFiles.add(fileName) == false) {
                // circular include detected
                throw new CircularIncludeException(fileName);
            }
            // parse the included xml file
            DigesterRuleParser includedSet =
                        new DigesterRuleParser(targetDigester, patternStack, includedFiles);
            includedSet.setDigesterRulesDTD(getDigesterRulesDTD());
            Digester digester = new Digester();
            digester.addRuleSet(includedSet);
            digester.push(DigesterRuleParser.this);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -