You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/08/09 23:51:33 UTC
svn commit: r802616 - in
/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax:
AbstractXMLStreamWriter.java
dialect/NamespaceContextCorrectingXMLStreamWriterWrapper.java
dialect/StAXDialect.java
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 {