📄 digester.java
字号:
/* $Id: Digester.java 467222 2006-10-24 03:17:11Z markt $
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.tomcat.util.digester;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.IntrospectionUtils;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
/**
* <p>A <strong>Digester</strong> processes an XML input stream by matching a
* series of element nesting patterns to execute Rules that have been added
* prior to the start of parsing. This package was inspired by the
* <code>XmlMapper</code> class that was part of Tomcat 3.0 and 3.1,
* but is organized somewhat differently.</p>
*
* <p>See the <a href="package-summary.html#package_description">Digester
* Developer Guide</a> for more information.</p>
*
* <p><strong>IMPLEMENTATION NOTE</strong> - A single Digester instance may
* only be used within the context of a single thread at a time, and a call
* to <code>parse()</code> must be completed before another can be initiated
* even from the same thread.</p>
*
* <p><strong>IMPLEMENTATION NOTE</strong> - A bug in Xerces 2.0.2 prevents
* the support of XML schema. You need Xerces 2.1/2.3 and up to make
* this class working with XML schema</p>
*/
public class Digester extends DefaultHandler {
// ---------------------------------------------------------- Static Fields
private static class SystemPropertySource
implements IntrospectionUtils.PropertySource {
public String getProperty( String key ) {
return System.getProperty(key);
}
}
protected static IntrospectionUtils.PropertySource source[] =
new IntrospectionUtils.PropertySource[] { new SystemPropertySource() };
// --------------------------------------------------------- Constructors
/**
* Construct a new Digester with default properties.
*/
public Digester() {
super();
}
/**
* Construct a new Digester, allowing a SAXParser to be passed in. This
* allows Digester to be used in environments which are unfriendly to
* JAXP1.1 (such as WebLogic 6.0). Thanks for the request to change go to
* James House (james@interobjective.com). This may help in places where
* you are able to load JAXP 1.1 classes yourself.
*/
public Digester(SAXParser parser) {
super();
this.parser = parser;
}
/**
* Construct a new Digester, allowing an XMLReader to be passed in. This
* allows Digester to be used in environments which are unfriendly to
* JAXP1.1 (such as WebLogic 6.0). Note that if you use this option you
* have to configure namespace and validation support yourself, as these
* properties only affect the SAXParser and emtpy constructor.
*/
public Digester(XMLReader reader) {
super();
this.reader = reader;
}
// --------------------------------------------------- Instance Variables
/**
* The body text of the current element.
*/
protected StringBuffer bodyText = new StringBuffer();
/**
* The stack of body text string buffers for surrounding elements.
*/
protected ArrayStack bodyTexts = new ArrayStack();
/**
* Stack whose elements are List objects, each containing a list of
* Rule objects as returned from Rules.getMatch(). As each xml element
* in the input is entered, the matching rules are pushed onto this
* stack. After the end tag is reached, the matches are popped again.
* The depth of is stack is therefore exactly the same as the current
* "nesting" level of the input xml.
*
* @since 1.6
*/
protected ArrayStack matches = new ArrayStack(10);
/**
* The class loader to use for instantiating application objects.
* If not specified, the context class loader, or the class loader
* used to load Digester itself, is used, based on the value of the
* <code>useContextClassLoader</code> variable.
*/
protected ClassLoader classLoader = null;
/**
* Has this Digester been configured yet.
*/
protected boolean configured = false;
/**
* The EntityResolver used by the SAX parser. By default it use this class
*/
protected EntityResolver entityResolver;
/**
* The URLs of entityValidator that have been registered, keyed by the public
* identifier that corresponds.
*/
protected HashMap entityValidator = new HashMap();
/**
* The application-supplied error handler that is notified when parsing
* warnings, errors, or fatal errors occur.
*/
protected ErrorHandler errorHandler = null;
/**
* The SAXParserFactory that is created the first time we need it.
*/
protected SAXParserFactory factory = null;
/**
* @deprecated This is now managed by {@link ParserFeatureSetterFactory}
*/
protected String JAXP_SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
/**
* The Locator associated with our parser.
*/
protected Locator locator = null;
/**
* The current match pattern for nested element processing.
*/
protected String match = "";
/**
* Do we want a "namespace aware" parser.
*/
protected boolean namespaceAware = false;
/**
* Registered namespaces we are currently processing. The key is the
* namespace prefix that was declared in the document. The value is an
* ArrayStack of the namespace URIs this prefix has been mapped to --
* the top Stack element is the most current one. (This architecture
* is required because documents can declare nested uses of the same
* prefix for different Namespace URIs).
*/
protected HashMap namespaces = new HashMap();
/**
* The parameters stack being utilized by CallMethodRule and
* CallParamRule rules.
*/
protected ArrayStack params = new ArrayStack();
/**
* The SAXParser we will use to parse the input stream.
*/
protected SAXParser parser = null;
/**
* The public identifier of the DTD we are currently parsing under
* (if any).
*/
protected String publicId = null;
/**
* The XMLReader used to parse digester rules.
*/
protected XMLReader reader = null;
/**
* The "root" element of the stack (in other words, the last object
* that was popped.
*/
protected Object root = null;
/**
* The <code>Rules</code> implementation containing our collection of
* <code>Rule</code> instances and associated matching policy. If not
* established before the first rule is added, a default implementation
* will be provided.
*/
protected Rules rules = null;
/**
* The XML schema language to use for validating an XML instance. By
* default this value is set to <code>W3C_XML_SCHEMA</code>
*/
protected String schemaLanguage = W3C_XML_SCHEMA;
/**
* The XML schema to use for validating an XML instance.
*/
protected String schemaLocation = null;
/**
* The object stack being constructed.
*/
protected ArrayStack stack = new ArrayStack();
/**
* Do we want to use the Context ClassLoader when loading classes
* for instantiating new objects. Default is <code>false</code>.
*/
protected boolean useContextClassLoader = false;
/**
* Do we want to use a validating parser.
*/
protected boolean validating = false;
/**
* The Log to which most logging calls will be made.
*/
protected Log log =
LogFactory.getLog("org.apache.commons.digester.Digester");
/**
* The Log to which all SAX event related logging calls will be made.
*/
protected Log saxLog =
LogFactory.getLog("org.apache.commons.digester.Digester.sax");
/**
* The schema language supported. By default, we use this one.
*/
protected static final String W3C_XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema";
/** Stacks used for interrule communication, indexed by name String */
private HashMap stacksByName = new HashMap();
// ------------------------------------------------------------- Properties
/**
* Return the currently mapped namespace URI for the specified prefix,
* if any; otherwise return <code>null</code>. These mappings come and
* go dynamically as the document is parsed.
*
* @param prefix Prefix to look up
*/
public String findNamespaceURI(String prefix) {
ArrayStack stack = (ArrayStack) namespaces.get(prefix);
if (stack == null) {
return (null);
}
try {
return ((String) stack.peek());
} catch (EmptyStackException e) {
return (null);
}
}
/**
* Return the class loader to be used for instantiating application objects
* when required. This is determined based upon the following rules:
* <ul>
* <li>The class loader set by <code>setClassLoader()</code>, if any</li>
* <li>The thread context class loader, if it exists and the
* <code>useContextClassLoader</code> property is set to true</li>
* <li>The class loader used to load the Digester class itself.
* </ul>
*/
public ClassLoader getClassLoader() {
if (this.classLoader != null) {
return (this.classLoader);
}
if (this.useContextClassLoader) {
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
if (classLoader != null) {
return (classLoader);
}
}
return (this.getClass().getClassLoader());
}
/**
* Set the class loader to be used for instantiating application objects
* when required.
*
* @param classLoader The new class loader to use, or <code>null</code>
* to revert to the standard rules
*/
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Return the current depth of the element stack.
*/
public int getCount() {
return (stack.size());
}
/**
* Return the name of the XML element that is currently being processed.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -