Author: veithen
Date: Sun Aug 9 21:51:33 2009
New Revision: 802616
URL: http://svn.apache.org/viewvc?rev=802616&view=rev
Log:
* Refactored NamespaceContextCorrectingXMLStreamWriterWrapper so that the
namespace context handling logic can be reused to build other XMLStreamWriter
implementations.
* Added a discussion about another ambiguity in the StAX specs to the
documentation of StAXDialect.
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java
(with props)
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialect.java
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java?rev=802616&view=auto
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java
(added)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java
Sun Aug 9 21:51:33 2009
@@ -0,0 +1,249 @@
+/*
+ * 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.axiom.util.stax;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.axiom.util.namespace.ScopedNamespaceContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Partial implementation of the {...@link XMLStreamWriter} interface. It
handles namespace bindings,
+ * i.e. the methods related to the namespace context. Subclasses only need to
implement write
+ * methods that take a prefix together with the namespace URI argument. All
{...@link XMLStreamWriter}
+ * methods that have a namespace URI argument, but no prefix argument are
implemented by this class.
+ */
+public abstract class AbstractXMLStreamWriter implements XMLStreamWriter {
+ private static final Log log =
LogFactory.getLog(AbstractXMLStreamWriter.class);
+
+ private final ScopedNamespaceContext namespaceContext = new
ScopedNamespaceContext();
+ private boolean inEmptyElement;
+
+ public final NamespaceContext getNamespaceContext() {
+ return namespaceContext;
+ }
+
+ public final void setNamespaceContext(NamespaceContext context) throws
XMLStreamException {
+ // TODO: not sure yet how to implement this method
+ throw new UnsupportedOperationException();
+ }
+
+ public final String getPrefix(String uri) throws XMLStreamException {
+ return namespaceContext.getPrefix(uri);
+ }
+
+ private void internalSetPrefix(String prefix, String uri) {
+ if (inEmptyElement) {
+ log.warn("The behavior of XMLStreamWriter#setPrefix and " +
+ "XMLStreamWriter#setDefaultNamespace is undefined when
invoked in the " +
+ "context of an empty element");
+ }
+ namespaceContext.setPrefix(prefix, uri);
+ }
+
+ public final void setDefaultNamespace(String uri) throws
XMLStreamException {
+ internalSetPrefix("", uri);
+ }
+
+ public final void setPrefix(String prefix, String uri) throws
XMLStreamException {
+ internalSetPrefix(prefix, uri);
+ }
+
+ public final void writeStartDocument() throws XMLStreamException {
+ doWriteStartDocument();
+ }
+
+ protected abstract void doWriteStartDocument() throws XMLStreamException;
+
+ public final void writeStartDocument(String encoding, String version)
throws XMLStreamException {
+ doWriteStartDocument(encoding, version);
+ }
+
+ protected abstract void doWriteStartDocument(String encoding, String
version) throws XMLStreamException;
+
+ public final void writeStartDocument(String version) throws
XMLStreamException {
+ doWriteStartDocument(version);
+ }
+
+ protected abstract void doWriteStartDocument(String version) throws
XMLStreamException;
+
+ public final void writeDTD(String dtd) throws XMLStreamException {
+ doWriteDTD(dtd);
+ }
+
+ protected abstract void doWriteDTD(String dtd) throws XMLStreamException;
+
+ public final void writeEndDocument() throws XMLStreamException {
+ doWriteEndDocument();
+ }
+
+ protected abstract void doWriteEndDocument() throws XMLStreamException;
+
+ private String internalGetPrefix(String namespaceURI) throws
XMLStreamException {
+ String prefix = namespaceContext.getPrefix(namespaceURI);
+ if (prefix == null) {
+ throw new XMLStreamException("Unbound namespace URI '" +
namespaceURI + "'");
+ } else {
+ return prefix;
+ }
+ }
+
+ public final void writeStartElement(String prefix, String localName,
String namespaceURI)
+ throws XMLStreamException {
+ doWriteStartElement(prefix, localName, namespaceURI);
+ namespaceContext.startScope();
+ inEmptyElement = false;
+ }
+
+ public final void writeStartElement(String namespaceURI, String localName)
throws XMLStreamException {
+ doWriteStartElement(internalGetPrefix(namespaceURI), namespaceURI,
localName);
+ namespaceContext.startScope();
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteStartElement(String prefix, String
localName, String namespaceURI)
+ throws XMLStreamException;
+
+ public final void writeStartElement(String localName) throws
XMLStreamException {
+ doWriteStartElement(localName);
+ namespaceContext.startScope();
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteStartElement(String localName) throws
XMLStreamException;
+
+ public final void writeEndElement() throws XMLStreamException {
+ doWriteEndElement();
+ namespaceContext.endScope();
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteEndElement() throws XMLStreamException;
+
+ public final void writeEmptyElement(String prefix, String localName,
String namespaceURI)
+ throws XMLStreamException {
+ doWriteEmptyElement(prefix, localName, namespaceURI);
+ inEmptyElement = true;
+ }
+
+ public final void writeEmptyElement(String namespaceURI, String localName)
+ throws XMLStreamException {
+ doWriteEmptyElement(internalGetPrefix(namespaceURI), namespaceURI,
localName);
+ inEmptyElement = true;
+ }
+
+ protected abstract void doWriteEmptyElement(String prefix, String
localName, String namespaceURI)
+ throws XMLStreamException;
+
+ public final void writeEmptyElement(String localName) throws
XMLStreamException {
+ doWriteEmptyElement(localName);
+ inEmptyElement = true;
+ }
+
+ protected abstract void doWriteEmptyElement(String localName) throws
XMLStreamException;
+
+ public final void writeAttribute(String prefix, String namespaceURI,
String localName, String value)
+ throws XMLStreamException {
+ doWriteAttribute(prefix, namespaceURI, localName, value);
+ }
+
+ public final void writeAttribute(String namespaceURI, String localName,
String value)
+ throws XMLStreamException {
+ doWriteAttribute(internalGetPrefix(namespaceURI), namespaceURI,
localName, value);
+ }
+
+ protected abstract void doWriteAttribute(String prefix, String
namespaceURI, String localName,
+ String value) throws XMLStreamException;
+
+ public final void writeAttribute(String localName, String value) throws
XMLStreamException {
+ doWriteAttribute(localName, value);
+ }
+
+ protected abstract void doWriteAttribute(String localName, String value)
+ throws XMLStreamException;
+
+ public final void writeNamespace(String prefix, String namespaceURI)
throws XMLStreamException {
+ doWriteNamespace(prefix, namespaceURI);
+ }
+
+ protected abstract void doWriteNamespace(String prefix, String
namespaceURI)
+ throws XMLStreamException;
+
+ public final void writeDefaultNamespace(String namespaceURI) throws
XMLStreamException {
+ doWriteDefaultNamespace(namespaceURI);
+ }
+
+ protected abstract void doWriteDefaultNamespace(String namespaceURI)
throws XMLStreamException;
+
+ public final void writeCharacters(char[] text, int start, int len) throws
XMLStreamException {
+ doWriteCharacters(text, start, len);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteCharacters(char[] text, int start, int len)
+ throws XMLStreamException;
+
+ public final void writeCharacters(String text) throws XMLStreamException {
+ doWriteCharacters(text);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteCharacters(String text) throws
XMLStreamException;
+
+ public final void writeCData(String data) throws XMLStreamException {
+ doWriteCData(data);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteCData(String data) throws
XMLStreamException;
+
+ public final void writeComment(String data) throws XMLStreamException {
+ doWriteComment(data);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteComment(String data) throws
XMLStreamException;
+
+ public final void writeEntityRef(String name) throws XMLStreamException {
+ doWriteEntityRef(name);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteEntityRef(String name) throws
XMLStreamException;
+
+ public final void writeProcessingInstruction(String target, String data)
+ throws XMLStreamException {
+ doWriteProcessingInstruction(target, data);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteProcessingInstruction(String target, String
data)
+ throws XMLStreamException;
+
+ public final void writeProcessingInstruction(String target) throws
XMLStreamException {
+ doWriteProcessingInstruction(target);
+ inEmptyElement = false;
+ }
+
+ protected abstract void doWriteProcessingInstruction(String target) throws
XMLStreamException;
+}
Propchange:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/AbstractXMLStreamWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java?rev=802616&r1=802615&r2=802616&view=diff
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java
(original)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java
Sun Aug 9 21:51:33 2009
@@ -23,8 +23,7 @@
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
-import org.apache.axiom.util.namespace.ScopedNamespaceContext;
-import org.apache.axiom.util.stax.wrapper.XMLStreamWriterWrapper;
+import org.apache.axiom.util.stax.AbstractXMLStreamWriter;
/**
* {...@link XMLStreamWriter} wrapper that handles namespace bindings on
behalf of the underlying
@@ -67,69 +66,110 @@
* This implies that if the wrapper is used, these methods will never be
called on the underlying
* writer.
*/
-public class NamespaceContextCorrectingXMLStreamWriterWrapper extends
XMLStreamWriterWrapper {
- private final ScopedNamespaceContext namespaceContext = new
ScopedNamespaceContext();
-
+public class NamespaceContextCorrectingXMLStreamWriterWrapper extends
AbstractXMLStreamWriter {
+ private final XMLStreamWriter parent;
+
public NamespaceContextCorrectingXMLStreamWriterWrapper(XMLStreamWriter
parent) {
- super(parent);
+ this.parent = parent;
}
- public NamespaceContext getNamespaceContext() {
- return namespaceContext;
+ protected void doWriteAttribute(String prefix, String namespaceURI, String
localName,
+ String value) throws XMLStreamException {
+ parent.writeAttribute(prefix, namespaceURI, localName, value);
}
- public void setNamespaceContext(NamespaceContext context) throws
XMLStreamException {
- // TODO: not sure yet how to implement this method
- throw new UnsupportedOperationException();
+ protected void doWriteAttribute(String localName, String value) throws
XMLStreamException {
+ parent.writeAttribute(localName, value);
}
- public String getPrefix(String uri) throws XMLStreamException {
- return namespaceContext.getPrefix(uri);
+ protected void doWriteCData(String data) throws XMLStreamException {
+ parent.writeCData(data);
}
- public void setDefaultNamespace(String uri) throws XMLStreamException {
- namespaceContext.setPrefix("", uri);
+ protected void doWriteCharacters(char[] text, int start, int len) throws
XMLStreamException {
+ parent.writeCharacters(text, start, len);
}
- public void setPrefix(String prefix, String uri) throws XMLStreamException
{
- namespaceContext.setPrefix(prefix, uri);
+ protected void doWriteCharacters(String text) throws XMLStreamException {
+ parent.writeCharacters(text);
}
- private String internalGetPrefix(String namespaceURI) throws
XMLStreamException {
- String prefix = namespaceContext.getPrefix(namespaceURI);
- if (prefix == null) {
- throw new XMLStreamException("Unbound namespace URI '" +
namespaceURI + "'");
- } else {
- return prefix;
- }
+ protected void doWriteComment(String data) throws XMLStreamException {
+ parent.writeComment(data);
}
-
- public void writeStartElement(String prefix, String localName, String
namespaceURI)
+
+ protected void doWriteDefaultNamespace(String namespaceURI) throws
XMLStreamException {
+ parent.writeDefaultNamespace(namespaceURI);
+ }
+
+ protected void doWriteDTD(String dtd) throws XMLStreamException {
+ parent.writeDTD(dtd);
+ }
+
+ protected void doWriteEmptyElement(String prefix, String localName, String
namespaceURI)
throws XMLStreamException {
- super.writeStartElement(prefix, localName, namespaceURI);
- namespaceContext.startScope();
+ parent.writeEmptyElement(prefix, localName, namespaceURI);
}
- public void writeStartElement(String namespaceURI, String localName)
throws XMLStreamException {
- super.writeStartElement(internalGetPrefix(namespaceURI), namespaceURI,
localName);
+ protected void doWriteEmptyElement(String localName) throws
XMLStreamException {
+ parent.writeEmptyElement(localName);
}
- public void writeStartElement(String localName) throws XMLStreamException {
- super.writeStartElement(localName);
- namespaceContext.startScope();
+ protected void doWriteEndDocument() throws XMLStreamException {
+ parent.writeEndDocument();
}
- public void writeEndElement() throws XMLStreamException {
- super.writeEndElement();
- namespaceContext.endScope();
+ protected void doWriteEndElement() throws XMLStreamException {
+ parent.writeEndElement();
}
- public void writeEmptyElement(String namespaceURI, String localName)
throws XMLStreamException {
- super.writeEmptyElement(internalGetPrefix(namespaceURI), namespaceURI,
localName);
+ protected void doWriteEntityRef(String name) throws XMLStreamException {
+ parent.writeEntityRef(name);
}
- public void writeAttribute(String namespaceURI, String localName, String
value)
+ protected void doWriteNamespace(String prefix, String namespaceURI) throws
XMLStreamException {
+ parent.writeNamespace(prefix, namespaceURI);
+ }
+
+ protected void doWriteProcessingInstruction(String target, String data)
throws XMLStreamException {
- super.writeAttribute(internalGetPrefix(namespaceURI), namespaceURI,
localName, value);
+ parent.writeProcessingInstruction(target, data);
+ }
+
+ protected void doWriteProcessingInstruction(String target) throws
XMLStreamException {
+ parent.writeProcessingInstruction(target);
+ }
+
+ protected void doWriteStartDocument() throws XMLStreamException {
+ parent.writeStartDocument();
+ }
+
+ protected void doWriteStartDocument(String encoding, String version)
throws XMLStreamException {
+ parent.writeStartDocument(encoding, version);
+ }
+
+ protected void doWriteStartDocument(String version) throws
XMLStreamException {
+ parent.writeStartDocument(version);
+ }
+
+ protected void doWriteStartElement(String prefix, String localName, String
namespaceURI)
+ throws XMLStreamException {
+ parent.writeStartElement(prefix, localName, namespaceURI);
+ }
+
+ protected void doWriteStartElement(String localName) throws
XMLStreamException {
+ parent.writeStartElement(localName);
+ }
+
+ public void close() throws XMLStreamException {
+ parent.close();
+ }
+
+ public void flush() throws XMLStreamException {
+ parent.flush();
+ }
+
+ public Object getProperty(String name) throws IllegalArgumentException {
+ return parent.getProperty(name);
}
}
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialect.java
URL:
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialect.java?rev=802616&r1=802615&r2=802616&view=diff
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialect.java
(original)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialect.java
Sun Aug 9 21:51:33 2009
@@ -113,6 +113,36 @@
* <li>An XML document may contain a namespace declaration such as
<tt>xmlns=""</tt>. In this
* case, it is not clear if {...@link
javax.xml.stream.XMLStreamReader#getNamespaceURI(int)}
* should return <code>null</code> or an empty string.</li>
+ * <li>The documentation of {...@link
javax.xml.stream.XMLStreamWriter#setPrefix(String, String)}
+ * and {...@link
javax.xml.stream.XMLStreamWriter#setDefaultNamespace(String)} requires that
+ * the namespace "is bound in the scope of the current START_ELEMENT /
END_ELEMENT pair".
+ * The meaning of this requirement is clear in the context of an element
written using
+ * the <code>writeStartElement</code> and <code>writeEndElement</code>
methods. On the
+ * other hand, the requirement is ambiguous in the context of an element
written using
+ * <code>writeEmptyElement</code> and there are two competing
interpretations:
+ * <ol>
+ * <li>Since the element is empty, it doesn't define a nested scope
and the namespace
+ * should be bound in the scope of the enclosing element.</li>
+ * <li>An invocation of one of the <code>writeEmptyElement</code>
methods actually
+ * doesn't write a complete element because it can be followed by
invocations
+ * of <code>writeAttribute</code>, <code>writeNamespace</code> or
+ * <code>writeDefaultNamespace</code>. The element is only
completed by a
+ * call to a <code>write</code> method other than the
aforementioned methods.
+ * An element written using <code>writeEmptyElement</code>
therefore also
+ * defines a scope and the namespace should be bound in that
scope.</li>
+ * </ol>
+ * While the second interpretation seems to be more consistent, it would
introduce another
+ * ambiguity for the following sequence of calls:
<code>writeEmptyElement</code>,
+ * <code>writeAttribute</code>, <code>setPrefix</code>,
<code>writeCharacters</code>.
+ * In this case, it is not clear if the scope of the empty element
should end at the call to
+ * <code>writeAttribute</code> or <code>writeCharacters</code>.
+ * <p>
+ * Because of these ambiguities, the dialect implementations don't
attempt to normalize the
+ * behavior of {...@link
javax.xml.stream.XMLStreamWriter#setPrefix(String, String)}
+ * and {...@link
javax.xml.stream.XMLStreamWriter#setDefaultNamespace(String)} in this particular
+ * context, and their usage in conjunction with
<code>writeEmptyElement</code> should be
+ * avoided.
+ * </li>
* </ul>
*/
public interface StAXDialect {