You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2005/07/29 12:39:36 UTC
svn commit: r226344 - in /cocoon:
blocks/forms/trunk/java/org/apache/cocoon/forms/util/ trunk/
trunk/src/java/org/apache/cocoon/util/location/
Author: sylvain
Date: Fri Jul 29 03:39:26 2005
New Revision: 226344
URL: http://svn.apache.org/viewcvs?rev=226344&view=rev
Log:
Add location tracking utilities, remove CForms dependency on Xerces
Added:
cocoon/trunk/src/java/org/apache/cocoon/util/location/
cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java (with props)
cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java (with props)
cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html (with props)
Modified:
cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/DomHelper.java
cocoon/trunk/status.xml
Modified: cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/DomHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/DomHelper.java?rev=226344&r1=226343&r2=226344&view=diff
==============================================================================
--- cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/DomHelper.java (original)
+++ cocoon/blocks/forms/trunk/java/org/apache/cocoon/forms/util/DomHelper.java Fri Jul 29 03:39:26 2005
@@ -25,19 +25,14 @@
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.util.location.LocationAttributes;
+import org.apache.cocoon.util.location.LocatorToAttributesPipe;
import org.apache.cocoon.xml.SaxBuffer;
+import org.apache.cocoon.xml.dom.DOMBuilder;
import org.apache.cocoon.xml.dom.DOMStreamer;
import org.apache.commons.lang.BooleanUtils;
-import org.apache.excalibur.xml.EntityResolver;
+import org.apache.excalibur.xml.sax.SAXParser;
import org.apache.excalibur.xml.sax.XMLizable;
-import org.apache.xerces.dom.NodeImpl;
-import org.apache.xerces.parsers.DOMParser;
-import org.apache.xerces.xni.Augmentations;
-import org.apache.xerces.xni.NamespaceContext;
-import org.apache.xerces.xni.QName;
-import org.apache.xerces.xni.XMLAttributes;
-import org.apache.xerces.xni.XMLLocator;
-import org.apache.xerces.xni.XNIException;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
@@ -46,7 +41,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
-import org.w3c.dom.UserDataHandler;
+import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;
@@ -74,54 +69,19 @@
* with the method {@link #parse(InputSource)} of this class.
*/
public static String getLocation(Element element) {
- String location = null;
- if (element instanceof NodeImpl) {
- location = (String)((NodeImpl)element).getUserData("location");
- }
-
- if (location != null) {
- return location;
- }
- return "(location unknown)";
+ return LocationAttributes.getLocationString(element);
}
public static String getSystemIdLocation(Element element) {
- String loc = getLocation(element);
- if (loc.charAt(0) != '(') {
- int end = loc.lastIndexOf(':');
- if (end > 0) {
- int start = loc.lastIndexOf(':', end - 1);
- if (start >= 0) {
- return loc.substring(0, start);
- }
- }
- }
- return null;
+ return LocationAttributes.getURI(element);
}
public static int getLineLocation(Element element) {
- String loc = getLocation(element);
- if (loc.charAt(0) != '(') {
- int end = loc.lastIndexOf(':');
- if (end > 0) {
- int start = loc.lastIndexOf(':', end - 1);
- if (start >= 0) {
- return Integer.parseInt(loc.substring(start + 1, end));
- }
- }
- }
- return -1;
+ return LocationAttributes.getLine(element);
}
public static int getColumnLocation(Element element) {
- String loc = getLocation(element);
- if (loc.charAt(0) != '(') {
- int end = loc.lastIndexOf(':');
- if (end > 0) {
- return Integer.parseInt(loc.substring(end));
- }
- }
- return -1;
+ return LocationAttributes.getColumn(element);
}
/**
@@ -330,75 +290,20 @@
*/
public static Document parse(InputSource inputSource, ServiceManager manager)
throws SAXException, SAXNotSupportedException, IOException, ServiceException {
- DOMParser domParser = new LocationTrackingDOMParser();
- domParser.setFeature(
- "http://apache.org/xml/features/dom/defer-node-expansion",
- false);
- domParser.setFeature(
- "http://apache.org/xml/features/dom/create-entity-ref-nodes",
- false);
- EntityResolver resolver = null;
- if (manager.hasService(EntityResolver.ROLE)) {
- resolver = (EntityResolver)manager.lookup(EntityResolver.ROLE);
- domParser.setEntityResolver(resolver);
- }
+ SAXParser parser = (SAXParser)manager.lookup(SAXParser.ROLE);
+ DOMBuilder builder = new DOMBuilder();
+
+ // Enhance the sax stream with location information
+ ContentHandler locationHandler = new LocatorToAttributesPipe(builder);
try {
- domParser.parse(inputSource);
- return domParser.getDocument();
+ parser.parse(inputSource, locationHandler);
} finally {
- manager.release(resolver);
- }
- }
-
- /**
- * An extension of the Xerces DOM parser that puts the location of each
- * node in that node's UserData.
- */
- public static class LocationTrackingDOMParser extends DOMParser {
- XMLLocator locator;
-
- public void startDocument(XMLLocator xmlLocator, String s,
- NamespaceContext namespaceContext,
- Augmentations augmentations) throws XNIException {
- super.startDocument(xmlLocator, s, namespaceContext,
- augmentations);
- this.locator = xmlLocator;
- setLocation();
- }
-
- public void startElement(QName qName, XMLAttributes xmlAttributes,
- Augmentations augmentations) throws XNIException {
- super.startElement(qName, xmlAttributes, augmentations);
- setLocation();
- }
-
- private final void setLocation() {
- // Older versions of Xerces had a different signature for the
- // startDocument method. If such a version is used, the
- // startDocument method above will not be called and locator will
- // hence be null.
- // Tell the users this so that they don't get a stupid NPE.
- if (this.locator == null) {
- throw new RuntimeException(
- "Error: locator is null. Check that you have the" +
- " correct version of Xerces (such as the one that" +
- " comes with Cocoon) in your endorsed library path.");
- }
- NodeImpl node = null;
- try {
- node = (NodeImpl)this.getProperty(
- "http://apache.org/xml/properties/dom/current-element-node");
- } catch (org.xml.sax.SAXException ex) {
- System.err.println("except" + ex);
- }
- if (node != null) {
- String location = locator.getLiteralSystemId() + ":" +
- locator.getLineNumber() + ":" + locator.getColumnNumber();
- node.setUserData("location", location, (UserDataHandler)null);
- }
+ manager.release(parser);
}
+
+ return builder.getDocument();
}
public static Map getLocalNSDeclarations(Element elm)
Added: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java?rev=226344&view=auto
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java Fri Jul 29 03:39:26 2005
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2005 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.cocoon.util.location;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A class to handle location information stored in attributes.
+ * These attributes are typically setup using {@link LocatorToAttributesPipe}
+ *
+ * @see LocatorToAttributesPipe
+ * @version $Id$
+ */
+public class LocationAttributes {
+ /** Prefix for the location namespace */
+ public static final String PREFIX = "loc";
+ /** Namespace URI for location attributes */
+ public static final String URI = "http://apache.org/cocoon/location";
+
+ /** Attribute name for the location URI */
+ public static final String SRC_ATTR = "src";
+ /** Attribute name for the line number */
+ public static final String LINE_ATTR = "line";
+ /** Attribute name for the column number */
+ public static final String COL_ATTR = "column";
+
+ /** Attribute qualified name for the location URI */
+ public static final String Q_SRC_ATTR = "loc:src";
+ /** Attribute qualified name for the line number */
+ public static final String Q_LINE_ATTR = "loc:line";
+ /** Attribute qualified name for the column number */
+ public static final String Q_COL_ATTR = "loc:column";
+
+ /** Value returned when location is unknown */
+ public static final String UNKNOWN_LOCATION = "[unknown location]";
+
+ // Private constructor, we only have static methods
+ private LocationAttributes() {
+ // Nothing
+ }
+
+ /**
+ * Add location attributes to a set of SAX attributes.
+ *
+ * @param locator the <code>Locator</code> (can be null)
+ * @param attrs the <code>Attributes</code> where locator information should be added
+ * @return
+ */
+ public static Attributes addLocationAttributes(Locator locator, Attributes attrs) {
+ if (locator == null || attrs.getIndex(URI, SRC_ATTR) != -1) {
+ // No location information known, or already has it
+ return attrs;
+ }
+
+ // Get an AttributeImpl so that we can add new attributes.
+ AttributesImpl newAttrs = attrs instanceof AttributesImpl ?
+ (AttributesImpl)attrs : new AttributesImpl(attrs);
+
+ newAttrs.addAttribute(URI, SRC_ATTR, Q_SRC_ATTR, "CDATA", locator.getSystemId());
+ newAttrs.addAttribute(URI, LINE_ATTR, Q_LINE_ATTR, "CDATA", Integer.toString(locator.getLineNumber()));
+ newAttrs.addAttribute(URI, COL_ATTR, Q_COL_ATTR, "CDATA", Integer.toString(locator.getColumnNumber()));
+
+ return newAttrs;
+ }
+
+ /**
+ * Returns the location of an element (SAX flavor).
+ *
+ * @param attrs the element's attributes that hold the location information
+ * @return a location string of type "<code>foo.xml:10:80</code>" or
+ * "<code>[unknown location]</code>" if <code>attrs</code> has no location information.
+ */
+ public static String getLocationString(Attributes attrs) {
+ String src = attrs.getValue(URI, SRC_ATTR);
+ if (src == null) {
+ return UNKNOWN_LOCATION;
+ }
+
+ return src + ":" + attrs.getValue(URI, LINE_ATTR) + ":" + attrs.getValue(URI, COL_ATTR);
+ }
+
+ /**
+ * Returns the URI of an element (SAX flavor)
+ *
+ * @param attrs the element's attributes that hold the location information
+ * @return the element's URI or "<code>[unknown location]</code>" if <code>attrs</code>
+ * has no location information.
+ */
+ public static String getURI(Attributes attrs) {
+ String src = attrs.getValue(URI, SRC_ATTR);
+ return src != null ? src : UNKNOWN_LOCATION;
+ }
+
+ /**
+ * Returns the line number of an element (SAX flavor)
+ *
+ * @param attrs the element's attributes that hold the location information
+ * @return the element's line number or <code>-1</code> if <code>attrs</code>
+ * has no location information.
+ */
+ public static int getLine(Attributes attrs) {
+ String line = attrs.getValue(URI, LINE_ATTR);
+ return line != null ? Integer.parseInt(line) : -1;
+ }
+
+ /**
+ * Returns the column number of an element (SAX flavor)
+ *
+ * @param attrs the element's attributes that hold the location information
+ * @return the element's column number or <code>-1</code> if <code>attrs</code>
+ * has no location information.
+ */
+ public static int getColumn(Attributes attrs) {
+ String col = attrs.getValue(URI, COL_ATTR);
+ return col != null ? Integer.parseInt(col) : -1;
+ }
+
+ /**
+ * Returns the location of an element that has been processed by this pipe (DOM flavor).
+ *
+ * @param elem the element that holds the location information
+ * @return a location string of type "<code>foo.xml:10:80</code>" or
+ * "<code>[unknown location]</code>" if <code>attrs</code> has no location information.
+ */
+ public static String getLocationString(Element elem) {
+ Attr srcAttr = elem.getAttributeNodeNS(URI, SRC_ATTR);
+ if (srcAttr == null) {
+ return UNKNOWN_LOCATION;
+ }
+
+ return srcAttr.getValue() + ":" + elem.getAttributeNS(URI, LINE_ATTR) + ":" + elem.getAttributeNS(URI, COL_ATTR);
+ }
+
+ /**
+ * Returns the URI of an element (DOM flavor)
+ *
+ * @param elem the element that holds the location information
+ * @return the element's URI or "<code>[unknown location]</code>" if <code>elem</code>
+ * has no location information.
+ */
+ public static String getURI(Element elem) {
+ Attr attr = elem.getAttributeNodeNS(URI, SRC_ATTR);
+ return attr != null ? attr.getValue() : UNKNOWN_LOCATION;
+ }
+
+ /**
+ * Returns the line number of an element (DOM flavor)
+ *
+ * @param elem the element that holds the location information
+ * @return the element's line number or <code>-1</code> if <code>elem</code>
+ * has no location information.
+ */
+ public static int getLine(Element elem) {
+ Attr attr = elem.getAttributeNodeNS(URI, LINE_ATTR);
+ return attr != null ? Integer.parseInt(attr.getValue()) : -1;
+ }
+
+ /**
+ * Returns the column number of an element (DOM flavor)
+ *
+ * @param elem the element that holds the location information
+ * @return the element's column number or <code>-1</code> if <code>elem</code>
+ * has no location information.
+ */
+ public static int getColumn(Element elem) {
+ Attr attr = elem.getAttributeNodeNS(URI, COL_ATTR);
+ return attr != null ? Integer.parseInt(attr.getValue()) : -1;
+ }
+}
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocationAttributes.java
------------------------------------------------------------------------------
svn:keywords = Id
Added: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java?rev=226344&view=auto
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java Fri Jul 29 03:39:26 2005
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2005 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.cocoon.util.location;
+
+import org.apache.cocoon.xml.AbstractXMLPipe;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * A SAX filter that adds the information available from the <code>Locator</code> as attributes.
+ * The purpose of having location as attributes is to allow this information to survive transformations
+ * of the document (an XSL could copy these attributes over) or conversion of SAX events to a DOM.
+ * <p>
+ * The location is added as 3 attributes in a specific namespace to each element.
+ * <pre>
+ * <root xmlns:loc="http://apache.org/cocoon/location"
+ * loc:src="file://path/to/file.xml"
+ * loc:line="1" loc:column="1">
+ * <foo loc:src="file://path/to/file.xml" loc:line="2" loc:column="3"/>
+ * </root>
+ * </pre>
+ * <strong>Note:</strong> Although this adds a lot of information to the serialized form of the document,
+ * the overhead in SAX events is not that big, as attribute names are interned, and all <code>src</code>
+ * attributes point to the same string.
+ *
+ * @see org.apache.cocoon.util.location.LocationAttributes
+ * @version $Id$
+ */
+public class LocatorToAttributesPipe extends AbstractXMLPipe {
+
+ private Locator locator;
+
+ /**
+ * Create a filter. It has to be chained to another handler to be really useful.
+ */
+ public LocatorToAttributesPipe() {
+ }
+
+ /**
+ * Create a filter that is chained to another handler.
+ * @param next the next handler in the chain.
+ */
+ public LocatorToAttributesPipe(ContentHandler next) {
+ setContentHandler(next);
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ super.setDocumentLocator(locator);
+ }
+
+ public void startDocument() throws SAXException {
+ super.startDocument();
+ super.startPrefixMapping(LocationAttributes.PREFIX, LocationAttributes.URI);
+ }
+
+ public void endDocument() throws SAXException {
+ endPrefixMapping(LocationAttributes.PREFIX);
+ super.endDocument();
+ }
+
+ public void startElement(String uri, String loc, String raw, Attributes attrs) throws SAXException {
+ // Add location attributes to the element
+ super.startElement(uri, loc, raw, LocationAttributes.addLocationAttributes(locator, attrs));
+ }
+}
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/LocatorToAttributesPipe.java
------------------------------------------------------------------------------
svn:keywords = Id
Added: cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html?rev=226344&view=auto
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html Fri Jul 29 03:39:26 2005
@@ -0,0 +1,3 @@
+<html>
+ <body>Classes and utilities used to track location information.</body>
+</html>
\ No newline at end of file
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/src/java/org/apache/cocoon/util/location/package.html
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/status.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/status.xml?rev=226344&r1=226343&r2=226344&view=diff
==============================================================================
--- cocoon/trunk/status.xml (original)
+++ cocoon/trunk/status.xml Fri Jul 29 03:39:26 2005
@@ -509,6 +509,10 @@
</action>
</release>
<release version="2.1.8" date="TBD">
+ <action dev="SW" type="add">
+ New org.apache.cocoon.util.location package, providing utilities to track locations in XML documents and
+ the objects built from these documents.
+ </action>
<action dev="SW" type="fix" fixes-bug="35618" due-to="Philippe Gassmann" due-to-email="phil@anyware-tech.com">
Mail block: Allow any of the Cocoon-provided protocols to be used for attachments in SendMailTransformer.
This means that "cocoon:" URLs are no more rewritten as external http requests.