Author: remy.maucherat(a)jboss.com
Date: 2011-04-06 12:22:52 -0400 (Wed, 06 Apr 2011)
New Revision: 1695
Removed:
trunk/java/org/apache/jasper/xmlparser/ParserUtils.java
trunk/java/org/apache/jasper/xmlparser/TreeNode.java
Modified:
trunk/java/org/apache/jasper/Constants.java
trunk/java/org/apache/jasper/EmbeddedServletOptions.java
trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java
trunk/java/org/apache/jasper/compiler/TagPluginManager.java
Log:
- Switch to using STAX for the remaining Jasper XML parsing.
Modified: trunk/java/org/apache/jasper/Constants.java
===================================================================
--- trunk/java/org/apache/jasper/Constants.java 2011-04-06 10:54:24 UTC (rev 1694)
+++ trunk/java/org/apache/jasper/Constants.java 2011-04-06 16:22:52 UTC (rev 1695)
@@ -94,7 +94,7 @@
/**
* Default tag handler pool size.
*/
- public static final int MAX_POOL_SIZE = 5;
+ public static final int MAX_POOL_SIZE =
Integer.parseInt(System.getProperty("org.apache.jasper.Constants.MAX_POOL_SIZE",
"16"));
/**
* The query parameter that causes the JSP engine to just
@@ -121,56 +121,7 @@
*/
public static final String INC_SERVLET_PATH =
"javax.servlet.include.servlet_path";
- // Must be kept in sync with org/apache/catalina/Globals.java
- public static final String ALT_DD_ATTR =
- System.getProperty("org.apache.jasper.Constants.ALT_DD_ATTR",
"org.apache.catalina.deploy.alt_dd");
-
/**
- * Public Id and the Resource path (of the cached copy)
- * of the DTDs for tag library descriptors.
- */
- public static final String TAGLIB_DTD_PUBLIC_ID_11 =
- "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN";
- public static final String TAGLIB_DTD_RESOURCE_PATH_11 =
- "/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd";
- public static final String TAGLIB_DTD_PUBLIC_ID_12 =
- "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN";
- public static final String TAGLIB_DTD_RESOURCE_PATH_12 =
- "/javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd";
-
- /**
- * Public Id and the Resource path (of the cached copy)
- * of the DTDs for web application deployment descriptors
- */
- public static final String WEBAPP_DTD_PUBLIC_ID_22 =
- "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN";
- public static final String WEBAPP_DTD_RESOURCE_PATH_22 =
- "/javax/servlet/resources/web-app_2_2.dtd";
- public static final String WEBAPP_DTD_PUBLIC_ID_23 =
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN";
- public static final String WEBAPP_DTD_RESOURCE_PATH_23 =
- "/javax/servlet/resources/web-app_2_3.dtd";
-
- /**
- * List of the Public IDs that we cache, and their
- * associated location. This is used by
- * an EntityResolver to return the location of the
- * cached copy of a DTD.
- */
- public static final String[] CACHED_DTD_PUBLIC_IDS = {
- TAGLIB_DTD_PUBLIC_ID_11,
- TAGLIB_DTD_PUBLIC_ID_12,
- WEBAPP_DTD_PUBLIC_ID_22,
- WEBAPP_DTD_PUBLIC_ID_23,
- };
- public static final String[] CACHED_DTD_RESOURCE_PATHS = {
- TAGLIB_DTD_RESOURCE_PATH_11,
- TAGLIB_DTD_RESOURCE_PATH_12,
- WEBAPP_DTD_RESOURCE_PATH_22,
- WEBAPP_DTD_RESOURCE_PATH_23,
- };
-
- /**
* Default URLs to download the pluging for Netscape and IE.
*/
public static final String NS_PLUGIN_URL =
Modified: trunk/java/org/apache/jasper/EmbeddedServletOptions.java
===================================================================
--- trunk/java/org/apache/jasper/EmbeddedServletOptions.java 2011-04-06 10:54:24 UTC (rev
1694)
+++ trunk/java/org/apache/jasper/EmbeddedServletOptions.java 2011-04-06 16:22:52 UTC (rev
1695)
@@ -28,7 +28,6 @@
import org.apache.jasper.compiler.JspConfig;
import org.apache.jasper.compiler.Localizer;
import org.apache.jasper.compiler.TagPluginManager;
-import org.apache.jasper.xmlparser.ParserUtils;
import org.jboss.logging.Logger;
/**
@@ -407,10 +406,6 @@
setProperty( k, v);
}
- // quick hack
- String validating=config.getInitParameter( "validating");
- if( "false".equals( validating )) ParserUtils.validating=false;
-
String keepgen = config.getInitParameter("keepgenerated");
if (keepgen != null) {
if (keepgen.equalsIgnoreCase("true")) {
Modified: trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2011-04-06 10:54:24
UTC (rev 1694)
+++ trunk/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2011-04-06 16:22:52
UTC (rev 1695)
@@ -28,11 +28,13 @@
import javax.servlet.jsp.tagext.TagFileInfo;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
-import org.apache.jasper.xmlparser.ParserUtils;
-import org.apache.jasper.xmlparser.TreeNode;
/**
* Class responsible for generating an implicit tag library containing tag
@@ -113,43 +115,46 @@
tagName.lastIndexOf(suffix));
tagFileMap.put(tagName, path);
} else if (path.endsWith(IMPLICIT_TLD)) {
- InputStream in = null;
+ InputStream is = null;
try {
- in = ctxt.getResourceAsStream(path);
- if (in != null) {
+ is = ctxt.getResourceAsStream(path);
+ if (is != null) {
// Add implicit TLD to dependency list
if (pi != null) {
pi.addDependant(path);
}
- ParserUtils pu = new ParserUtils();
- TreeNode tld = pu.parseXMLDocument(uri, in);
-
- if (tld.findAttribute("version") != null) {
- this.jspversion =
tld.findAttribute("version");
+ XMLStreamReader reader =
XMLInputFactory.newInstance().createXMLStreamReader(is);
+
+ reader.require(XMLStreamConstants.START_DOCUMENT, null,
null);
+ while (reader.hasNext() && reader.next() !=
XMLStreamConstants.START_ELEMENT) {
+ // Skip until first element
}
+
+ final int count = reader.getAttributeCount();
+ for (int i = 0; i < count; i ++) {
+ if
("version".equals(reader.getAttributeLocalName(i))) {
+ this.jspversion = reader.getAttributeValue(i);
+ }
+ }
- // Process each child element of our <taglib> element
- Iterator list = tld.findChildren();
-
- while (list.hasNext()) {
- TreeNode element = (TreeNode) list.next();
- String tname = element.getName();
-
- if ("tlibversion".equals(tname) // JSP 1.1
- || "tlib-version".equals(tname)) { //
JSP 1.2
- this.tlibversion = element.getBody();
- } else if ("jspversion".equals(tname)
- || "jsp-version".equals(tname)) {
- this.jspversion = element.getBody();
- } else if ("shortname".equals(tname) ||
"short-name".equals(tname)) {
- // Ignore
+ while (reader.hasNext() && reader.nextTag() !=
XMLStreamConstants.END_ELEMENT) {
+ String elementName = reader.getLocalName();
+ if ("tlibversion".equals(elementName) // JSP
1.1
+ || "tlib-version".equals(elementName))
{ // JSP 1.2
+ this.tlibversion = reader.getElementText().trim();
+ } else if ("jspversion".equals(elementName)
+ || "jsp-version".equals(elementName))
{
+ this.jspversion = reader.getElementText().trim();
+ } else if ("shortname".equals(elementName) ||
"short-name".equals(elementName)) {
+ reader.getElementText();
} else {
// All other elements are invalid
err.jspError("jsp.error.invalid.implicit",
path);
}
}
+
try {
double version = Double.parseDouble(this.jspversion);
if (version < 2.0) {
@@ -159,10 +164,12 @@
err.jspError("jsp.error.invalid.implicit.version", path);
}
}
+ } catch (XMLStreamException e) {
+ err.jspError("jsp.error.invalid.implicit", path, e);
} finally {
- if (in != null) {
+ if (is != null) {
try {
- in.close();
+ is.close();
} catch (Throwable t) {
}
}
Modified: trunk/java/org/apache/jasper/compiler/TagPluginManager.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/TagPluginManager.java 2011-04-06 10:54:24 UTC
(rev 1694)
+++ trunk/java/org/apache/jasper/compiler/TagPluginManager.java 2011-04-06 16:22:52 UTC
(rev 1695)
@@ -17,13 +17,17 @@
package org.apache.jasper.compiler;
-import java.util.*;
-import java.io.*;
+import java.io.InputStream;
+import java.util.HashMap;
+
import javax.servlet.ServletContext;
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
import org.apache.jasper.JasperException;
-import org.apache.jasper.xmlparser.ParserUtils;
-import org.apache.jasper.xmlparser.TreeNode;
import org.apache.jasper.compiler.tagplugin.TagPlugin;
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
@@ -38,7 +42,7 @@
private static final String TAG_PLUGINS_ROOT_ELEM = "tag-plugins";
private boolean initialized = false;
- private HashMap tagPlugins = null;
+ private HashMap<String, TagPlugin> tagPlugins = null;
private ServletContext ctxt;
private PageInfo pageInfo;
@@ -67,54 +71,77 @@
}
private void init(ErrorDispatcher err) throws JasperException {
- if (initialized)
- return;
+ if (initialized)
+ return;
- InputStream is = ctxt.getResourceAsStream(TAG_PLUGINS_XML);
- if (is == null)
- return;
+ InputStream is = ctxt.getResourceAsStream(TAG_PLUGINS_XML);
+ if (is == null)
+ return;
- TreeNode root = (new ParserUtils()).parseXMLDocument(TAG_PLUGINS_XML,
- is);
- if (root == null) {
- return;
- }
+ XMLStreamReader reader;
+ try {
+ reader = XMLInputFactory.newInstance().createXMLStreamReader(is);
+ reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
- if (!TAG_PLUGINS_ROOT_ELEM.equals(root.getName())) {
- err.jspError("jsp.error.plugin.wrongRootElement", TAG_PLUGINS_XML,
- TAG_PLUGINS_ROOT_ELEM);
- }
+ reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
+ while (reader.hasNext() && reader.next() !=
XMLStreamConstants.START_ELEMENT) {
+ // Skip until first element
+ }
- tagPlugins = new HashMap();
- Iterator pluginList = root.findChildren("tag-plugin");
- while (pluginList.hasNext()) {
- TreeNode pluginNode = (TreeNode) pluginList.next();
- TreeNode tagClassNode = pluginNode.findChild("tag-class");
- if (tagClassNode == null) {
- // Error
- return;
- }
- String tagClass = tagClassNode.getBody().trim();
- TreeNode pluginClassNode = pluginNode.findChild("plugin-class");
- if (pluginClassNode == null) {
- // Error
- return;
- }
+ if (!TAG_PLUGINS_ROOT_ELEM.equals(reader.getLocalName())) {
+ err.jspError("jsp.error.plugin.wrongRootElement",
TAG_PLUGINS_XML,
+ TAG_PLUGINS_ROOT_ELEM);
+ }
- String pluginClassStr = pluginClassNode.getBody();
- TagPlugin tagPlugin = null;
- try {
- Class pluginClass = Class.forName(pluginClassStr);
- tagPlugin = (TagPlugin) pluginClass.newInstance();
- } catch (Exception e) {
- throw new JasperException(e);
- }
- if (tagPlugin == null) {
- return;
- }
- tagPlugins.put(tagClass, tagPlugin);
- }
- initialized = true;
+ tagPlugins = new HashMap<String, TagPlugin>();
+ while (reader.hasNext() && reader.nextTag() !=
XMLStreamConstants.END_ELEMENT) {
+ String elementName = reader.getLocalName();
+ if ("tag-plugin".equals(elementName)) { // JSP 1.2
+ String tagClassName = null;
+ String pluginClassName = null;
+ while (reader.hasNext() && reader.nextTag() !=
XMLStreamConstants.END_ELEMENT) {
+ String childClementName = reader.getLocalName();
+ if ("tag-class".equals(childClementName)) {
+ tagClassName = reader.getElementText().trim();
+ } else if ("plugin-class".equals(childClementName)) {
+ pluginClassName = reader.getElementText().trim();
+ } else {
+ err.jspError("jsp.error.invalid.tagplugin",
TAG_PLUGINS_XML);
+ }
+ }
+ if (tagClassName == null || pluginClassName == null) {
+ err.jspError("jsp.error.invalid.tagplugin",
TAG_PLUGINS_XML);
+ }
+ TagPlugin tagPlugin = null;
+ try {
+ Class<?> pluginClass =
Thread.currentThread().getContextClassLoader().loadClass(pluginClassName);
+ tagPlugin = (TagPlugin) pluginClass.newInstance();
+ } catch (Exception e) {
+ throw new JasperException(e);
+ }
+ if (tagPlugin == null) {
+ return;
+ }
+ tagPlugins.put(tagClassName, tagPlugin);
+
+ } else {
+ // All other elements are invalid
+ err.jspError("jsp.error.invalid.tagplugin",
TAG_PLUGINS_XML);
+ }
+ }
+ } catch (XMLStreamException e) {
+ err.jspError("jsp.error.invalid.tagplugin", TAG_PLUGINS_XML, e);
+ } catch (FactoryConfigurationError e) {
+ throw new JasperException(e);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (Throwable t) {
+ }
+ }
+ }
+ initialized = true;
}
/**
Deleted: trunk/java/org/apache/jasper/xmlparser/ParserUtils.java
===================================================================
--- trunk/java/org/apache/jasper/xmlparser/ParserUtils.java 2011-04-06 10:54:24 UTC (rev
1694)
+++ trunk/java/org/apache/jasper/xmlparser/ParserUtils.java 2011-04-06 16:22:52 UTC (rev
1695)
@@ -1,235 +0,0 @@
-/*
- * 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.jasper.xmlparser;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.jasper.Constants;
-import org.apache.jasper.JasperException;
-import org.apache.jasper.compiler.Localizer;
-import org.jboss.logging.Logger;
-import org.jboss.logging.Logger;
-import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-
-
-/**
- * XML parsing utilities for processing web application deployment
- * descriptor and tag library descriptor files. FIXME - make these
- * use a separate class loader for the parser to be used.
- *
- * @author Craig R. McClanahan
- * @version $Revision$ $Date$
- */
-
-public class ParserUtils {
-
- /**
- * An error handler for use when parsing XML documents.
- */
- static ErrorHandler errorHandler = new MyErrorHandler();
-
- /**
- * An entity resolver for use when parsing XML documents.
- */
- static EntityResolver entityResolver = new MyEntityResolver();
-
- // Turn off for JSP 2.0 until switch over to using xschema.
- public static boolean validating = false;
-
-
- // --------------------------------------------------------- Public Methods
-
- /**
- * Parse the specified XML document, and return a <code>TreeNode</code>
- * that corresponds to the root node of the document tree.
- *
- * @param uri URI of the XML document being parsed
- * @param is Input source containing the deployment descriptor
- *
- * @exception JasperException if an input/output error occurs
- * @exception JasperException if a parsing error occurs
- */
- public TreeNode parseXMLDocument(String uri, InputSource is)
- throws JasperException {
-
- Document document = null;
-
- // Perform an XML parse of this document, via JAXP
- try {
- DocumentBuilderFactory factory =
- DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- factory.setValidating(validating);
- DocumentBuilder builder = factory.newDocumentBuilder();
- builder.setEntityResolver(entityResolver);
- builder.setErrorHandler(errorHandler);
- document = builder.parse(is);
- } catch (ParserConfigurationException ex) {
- throw new JasperException
- (Localizer.getMessage("jsp.error.parse.xml", uri), ex);
- } catch (SAXParseException ex) {
- throw new JasperException
- (Localizer.getMessage("jsp.error.parse.xml.line",
- uri,
- Integer.toString(ex.getLineNumber()),
- Integer.toString(ex.getColumnNumber())),
- ex);
- } catch (SAXException sx) {
- throw new JasperException
- (Localizer.getMessage("jsp.error.parse.xml", uri), sx);
- } catch (IOException io) {
- throw new JasperException
- (Localizer.getMessage("jsp.error.parse.xml", uri), io);
- }
-
- // Convert the resulting document to a graph of TreeNodes
- return (convert(null, document.getDocumentElement()));
- }
-
-
- /**
- * Parse the specified XML document, and return a <code>TreeNode</code>
- * that corresponds to the root node of the document tree.
- *
- * @param uri URI of the XML document being parsed
- * @param is Input stream containing the deployment descriptor
- *
- * @exception JasperException if an input/output error occurs
- * @exception JasperException if a parsing error occurs
- */
- public TreeNode parseXMLDocument(String uri, InputStream is)
- throws JasperException {
-
- return (parseXMLDocument(uri, new InputSource(is)));
- }
-
-
- // ------------------------------------------------------ Protected Methods
-
-
- /**
- * Create and return a TreeNode that corresponds to the specified Node,
- * including processing all of the attributes and children nodes.
- *
- * @param parent The parent TreeNode (if any) for the new TreeNode
- * @param node The XML document Node to be converted
- */
- protected TreeNode convert(TreeNode parent, Node node) {
-
- // Construct a new TreeNode for this node
- TreeNode treeNode = new TreeNode(node.getNodeName(), parent);
-
- // Convert all attributes of this node
- NamedNodeMap attributes = node.getAttributes();
- if (attributes != null) {
- int n = attributes.getLength();
- for (int i = 0; i < n; i++) {
- Node attribute = attributes.item(i);
- treeNode.addAttribute(attribute.getNodeName(),
- attribute.getNodeValue());
- }
- }
-
- // Create and attach all children of this node
- NodeList children = node.getChildNodes();
- if (children != null) {
- int n = children.getLength();
- for (int i = 0; i < n; i++) {
- Node child = children.item(i);
- if (child instanceof Comment)
- continue;
- if (child instanceof Text) {
- String body = ((Text) child).getData();
- if (body != null) {
- body = body.trim();
- if (body.length() > 0)
- treeNode.setBody(body);
- }
- } else {
- TreeNode treeChild = convert(treeNode, child);
- }
- }
- }
-
- // Return the completed TreeNode graph
- return (treeNode);
- }
-}
-
-
-// ------------------------------------------------------------ Private Classes
-
-class MyEntityResolver implements EntityResolver {
-
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException {
- for (int i = 0; i < Constants.CACHED_DTD_PUBLIC_IDS.length; i++) {
- String cachedDtdPublicId = Constants.CACHED_DTD_PUBLIC_IDS[i];
- if (cachedDtdPublicId.equals(publicId)) {
- String resourcePath = Constants.CACHED_DTD_RESOURCE_PATHS[i];
- InputStream input = this.getClass().getResourceAsStream(
- resourcePath);
- if (input == null) {
- throw new SAXException(Localizer.getMessage(
- "jsp.error.internal.filenotfound", resourcePath));
- }
- InputSource isrc = new InputSource(input);
- return isrc;
- }
- }
- Logger log = Logger.getLogger(MyEntityResolver.class);
- if (log.isDebugEnabled())
- log.debug("Resolve entity failed" + publicId + " " +
systemId);
- log.error(Localizer.getMessage("jsp.error.parse.xml.invalidPublicId",
- publicId));
- return null;
- }
-}
-
-class MyErrorHandler implements ErrorHandler {
-
- public void warning(SAXParseException ex) throws SAXException {
- Logger log = Logger.getLogger(MyErrorHandler.class);
- if (log.isDebugEnabled())
- log.debug("ParserUtils: warning ", ex);
- // We ignore warnings
- }
-
- public void error(SAXParseException ex) throws SAXException {
- throw ex;
- }
-
- public void fatalError(SAXParseException ex) throws SAXException {
- throw ex;
- }
-}
\ No newline at end of file
Deleted: trunk/java/org/apache/jasper/xmlparser/TreeNode.java
===================================================================
--- trunk/java/org/apache/jasper/xmlparser/TreeNode.java 2011-04-06 10:54:24 UTC (rev
1694)
+++ trunk/java/org/apache/jasper/xmlparser/TreeNode.java 2011-04-06 16:22:52 UTC (rev
1695)
@@ -1,360 +0,0 @@
-/*
- * 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.jasper.xmlparser;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-
-
-/**
- * Simplified implementation of a Node from a Document Object Model (DOM)
- * parse of an XML document. This class is used to represent a DOM tree
- * so that the XML parser's implementation of <code>org.w3c.dom</code>
need
- * not be visible to the remainder of Jasper.
- * <p>
- * <strong>WARNING</strong> - Construction of a new tree, or modifications
- * to an existing one, are not thread-safe and such accesses must be
- * synchronized.
- *
- * @author Craig R. McClanahan
- * @version $Revision$ $Date$
- */
-
-public class TreeNode {
-
-
- // ----------------------------------------------------------- Constructors
-
-
- /**
- * Construct a new node with no parent.
- *
- * @param name The name of this node
- */
- public TreeNode(String name) {
-
- this(name, null);
-
- }
-
-
- /**
- * Construct a new node with the specified parent.
- *
- * @param name The name of this node
- * @param parent The node that is the parent of this node
- */
- public TreeNode(String name, TreeNode parent) {
-
- super();
- this.name = name;
- this.parent = parent;
- if (this.parent != null)
- this.parent.addChild(this);
-
- }
-
-
- // ----------------------------------------------------- Instance Variables
-
-
- /**
- * The attributes of this node, keyed by attribute name,
- * Instantiated only if required.
- */
- protected HashMap attributes = null;
-
-
- /**
- * The body text associated with this node (if any).
- */
- protected String body = null;
-
-
- /**
- * The children of this node, instantiated only if required.
- */
- protected ArrayList children = null;
-
-
- /**
- * The name of this node.
- */
- protected String name = null;
-
-
- /**
- * The parent node of this node.
- */
- protected TreeNode parent = null;
-
-
- // --------------------------------------------------------- Public Methods
-
-
- /**
- * Add an attribute to this node, replacing any existing attribute
- * with the same name.
- *
- * @param name The attribute name to add
- * @param value The new attribute value
- */
- public void addAttribute(String name, String value) {
-
- if (attributes == null)
- attributes = new HashMap();
- attributes.put(name, value);
-
- }
-
-
- /**
- * Add a new child node to this node.
- *
- * @param node The new child node
- */
- public void addChild(TreeNode node) {
-
- if (children == null)
- children = new ArrayList();
- children.add(node);
-
- }
-
-
- /**
- * Return the value of the specified node attribute if it exists, or
- * <code>null</code> otherwise.
- *
- * @param name Name of the requested attribute
- */
- public String findAttribute(String name) {
-
- if (attributes == null)
- return (null);
- else
- return ((String) attributes.get(name));
-
- }
-
-
- /**
- * Return an Iterator of the attribute names of this node. If there are
- * no attributes, an empty Iterator is returned.
- */
- public Iterator findAttributes() {
-
- if (attributes == null)
- return (Collections.EMPTY_LIST.iterator());
- else
- return (attributes.keySet().iterator());
-
- }
-
-
- /**
- * Return the first child node of this node with the specified name,
- * if there is one; otherwise, return <code>null</code>.
- *
- * @param name Name of the desired child element
- */
- public TreeNode findChild(String name) {
-
- if (children == null)
- return (null);
- Iterator items = children.iterator();
- while (items.hasNext()) {
- TreeNode item = (TreeNode) items.next();
- if (name.equals(item.getName()))
- return (item);
- }
- return (null);
-
- }
-
-
- /**
- * Return an Iterator of all children of this node. If there are no
- * children, an empty Iterator is returned.
- */
- public Iterator findChildren() {
-
- if (children == null)
- return (Collections.EMPTY_LIST.iterator());
- else
- return (children.iterator());
-
- }
-
-
- /**
- * Return an Iterator over all children of this node that have the
- * specified name. If there are no such children, an empty Iterator
- * is returned.
- *
- * @param name Name used to select children
- */
- public Iterator findChildren(String name) {
-
- if (children == null)
- return (Collections.EMPTY_LIST.iterator());
-
- ArrayList results = new ArrayList();
- Iterator items = children.iterator();
- while (items.hasNext()) {
- TreeNode item = (TreeNode) items.next();
- if (name.equals(item.getName()))
- results.add(item);
- }
- return (results.iterator());
-
- }
-
-
- /**
- * Return the body text associated with this node (if any).
- */
- public String getBody() {
-
- return (this.body);
-
- }
-
-
- /**
- * Return the name of this node.
- */
- public String getName() {
-
- return (this.name);
-
- }
-
-
- /**
- * Remove any existing value for the specified attribute name.
- *
- * @param name The attribute name to remove
- */
- public void removeAttribute(String name) {
-
- if (attributes != null)
- attributes.remove(name);
-
- }
-
-
- /**
- * Remove a child node from this node, if it is one.
- *
- * @param node The child node to remove
- */
- public void removeNode(TreeNode node) {
-
- if (children != null)
- children.remove(node);
-
- }
-
-
- /**
- * Set the body text associated with this node (if any).
- *
- * @param body The body text (if any)
- */
- public void setBody(String body) {
-
- this.body = body;
-
- }
-
-
- /**
- * Return a String representation of this TreeNode.
- */
- public String toString() {
-
- StringBuilder sb = new StringBuilder();
- toString(sb, 0, this);
- return (sb.toString());
-
- }
-
-
- // ------------------------------------------------------ Protected Methods
-
-
- /**
- * Append to the specified StringBuilder a character representation of
- * this node, with the specified amount of indentation.
- *
- * @param sb The StringBuilder to append to
- * @param indent Number of characters of indentation
- * @param node The TreeNode to be printed
- */
- protected void toString(StringBuilder sb, int indent,
- TreeNode node) {
-
- int indent2 = indent + 2;
-
- // Reconstruct an opening node
- for (int i = 0; i < indent; i++)
- sb.append(' ');
- sb.append('<');
- sb.append(node.getName());
- Iterator names = node.findAttributes();
- while (names.hasNext()) {
- sb.append(' ');
- String name = (String) names.next();
- sb.append(name);
- sb.append("=\"");
- String value = node.findAttribute(name);
- sb.append(value);
- sb.append("\"");
- }
- sb.append(">\n");
-
- // Reconstruct the body text of this node (if any)
- String body = node.getBody();
- if ((body != null) && (body.length() > 0)) {
- for (int i = 0; i < indent2; i++)
- sb.append(' ');
- sb.append(body);
- sb.append("\n");
- }
-
- // Reconstruct child nodes with extra indentation
- Iterator children = node.findChildren();
- while (children.hasNext()) {
- TreeNode child = (TreeNode) children.next();
- toString(sb, indent2, child);
- }
-
- // Reconstruct a closing node marker
- for (int i = 0; i < indent; i++)
- sb.append(' ');
- sb.append("</");
- sb.append(node.getName());
- sb.append(">\n");
-
- }
-
-
-}