Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed robustness of namespace handling for buffered WFS GetFeature respo... #91

Merged
merged 1 commit into from
Apr 19, 2013
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import static org.deegree.commons.xml.CommonNamespaces.XLNNS;
import static org.deegree.commons.xml.CommonNamespaces.XSINS;
import static org.deegree.commons.xml.CommonNamespaces.XSI_PREFIX;
import static org.deegree.commons.xml.stax.XMLStreamUtils.skipToRequiredElement;

import java.io.IOException;
Expand Down Expand Up @@ -80,11 +82,11 @@ public class BufferableXMLStreamWriter implements XMLStreamWriter {

private static final int MEMORY_BUFFER_SIZE_IN_BYTES = 10 * 1024 * 1024;

private static final String ELEMENT_NAME_DUMMY_LEVEL = "DummyLevel";
private static final String ELEMENT_NAME_CONTAINER_ROOT = "Container";

private static final String ELEMENT_NAME_WRAPPER = "WrapperElement";
private static final String ELEMENT_NAME_OPEN_ELEMENT = "OpenElement";

private static final String ELEMENT_NAME_CONTENT = "Content";
private static final String ELEMENT_NAME_UNCLEAR_REFERENCE = "Reference";

private final XMLStreamWriter sink;

Expand Down Expand Up @@ -117,7 +119,7 @@ public void appendBufferedXML( GMLStreamWriter gmlWriter )
throws XMLStreamException, FactoryConfigurationError, IOException {

XMLStreamReader inStream = getBufferedXML();
skipToRequiredElement( inStream, new QName( ELEMENT_NAME_CONTENT ) );
skipToRequiredElement( inStream, new QName( ELEMENT_NAME_UNCLEAR_REFERENCE ) );
boolean onContentElement = true;

int eventType = 0;
Expand All @@ -137,7 +139,11 @@ public void appendBufferedXML( GMLStreamWriter gmlWriter )
}
case END_ELEMENT: {
String localName = inStream.getLocalName();
if ( !localName.equals( ELEMENT_NAME_WRAPPER ) ) {
if ( localName.equals( ELEMENT_NAME_UNCLEAR_REFERENCE ) ) {
// StaX workaround: signal "end" of empty element to get rid of locally bound namespace prefixes
// otherwise sink.getPrefix () will lie right in our faces...
sink.writeCharacters( "" );
} else if ( !localName.equals( ELEMENT_NAME_CONTAINER_ROOT ) ) {
sink.writeEndElement();
}
break;
Expand All @@ -151,8 +157,7 @@ public void appendBufferedXML( GMLStreamWriter gmlWriter )
sink.writeStartElement( localName );
} else {
if ( sink.getPrefix( nsUri ) == null ) {
sink.setPrefix( prefix, nsUri );
sink.writeStartElement( nsUri, localName );
sink.writeStartElement( prefix, localName, nsUri );
sink.writeNamespace( prefix, nsUri );
} else {
sink.writeStartElement( nsUri, localName );
Expand All @@ -161,41 +166,8 @@ public void appendBufferedXML( GMLStreamWriter gmlWriter )
} else {
onContentElement = false;
}

// copy all namespace bindings
for ( int i = 0; i < inStream.getNamespaceCount(); i++ ) {
String nsPrefix = inStream.getNamespacePrefix( i );
String nsURI = inStream.getNamespaceURI( i );
sink.writeNamespace( nsPrefix, nsURI );
}

// copy all attributes
for ( int i = 0; i < inStream.getAttributeCount(); i++ ) {
String attrLocalName = inStream.getAttributeLocalName( i );
String nsPrefix = inStream.getAttributePrefix( i );
String value = inStream.getAttributeValue( i );
String nsURI = inStream.getAttributeNamespace( i );
if ( nsURI == null || nsURI.equals( NULL_NS_URI ) ) {
sink.writeAttribute( attrLocalName, value );
} else {
if ( attrLocalName.equals( "href" ) && nsURI.equals( XLNNS ) ) {
if ( value.startsWith( "{" ) || value.endsWith( "}" ) ) {
String objectId = value.substring( 1, value.length() - 1 );
if ( gmlWriter.getReferenceResolveStrategy().isObjectExported( objectId ) ) {
value = "#" + objectId;
} else {
value = xLinkTemplate.replace( "{}", objectId );
}
}
}

if ( sink.getPrefix( nsURI ) == null ) {
sink.writeNamespace( nsPrefix, nsURI );
}

sink.writeAttribute( nsURI, attrLocalName, value );
}
}
copyNamespaceBindings( inStream );
copyAttributes( gmlWriter, inStream );
break;
}
default: {
Expand All @@ -206,6 +178,47 @@ public void appendBufferedXML( GMLStreamWriter gmlWriter )
}
}

private void copyAttributes( GMLStreamWriter gmlWriter, XMLStreamReader inStream )
throws XMLStreamException {
for ( int i = 0; i < inStream.getAttributeCount(); i++ ) {
String attrLocalName = inStream.getAttributeLocalName( i );
String nsPrefix = inStream.getAttributePrefix( i );
String value = inStream.getAttributeValue( i );
String nsURI = inStream.getAttributeNamespace( i );
if ( nsURI == null || nsURI.equals( NULL_NS_URI ) ) {
sink.writeAttribute( attrLocalName, value );
} else {
if ( attrLocalName.equals( "href" ) && nsURI.equals( XLNNS ) ) {
if ( value.startsWith( "{" ) || value.endsWith( "}" ) ) {
String objectId = value.substring( 1, value.length() - 1 );
if ( gmlWriter.getReferenceResolveStrategy().isObjectExported( objectId ) ) {
value = "#" + objectId;
} else {
value = xLinkTemplate.replace( "{}", objectId );
}
}
}

if ( sink.getPrefix( nsURI ) == null ) {
sink.writeNamespace( nsPrefix, nsURI );
}

sink.writeAttribute( nsURI, attrLocalName, value );
}
}
}

private void copyNamespaceBindings( XMLStreamReader inStream )
throws XMLStreamException {
for ( int i = 0; i < inStream.getNamespaceCount(); i++ ) {
String nsPrefix = inStream.getNamespacePrefix( i );
String nsURI = inStream.getNamespaceURI( i );
if ( sink.getPrefix( nsURI ) == null ) {
sink.writeNamespace( nsPrefix, nsURI );
}
}
}

public XMLStreamReader getBufferedXML()
throws XMLStreamException, FactoryConfigurationError, IOException {
if ( buffer == null ) {
Expand All @@ -230,19 +243,22 @@ public void activateBuffering()

private void writeWrapperElementWithNamespacesAndDummyLevel()
throws XMLStreamException {
activeWriter.writeStartElement( ELEMENT_NAME_WRAPPER );
activeWriter.writeStartElement( ELEMENT_NAME_CONTAINER_ROOT );
Iterator<String> namespaceIter = nsBindings.getNamespaceURIs();
while ( namespaceIter.hasNext() ) {
String ns = namespaceIter.next();
String prefix = nsBindings.getPrefix( ns );
activeWriter.writeNamespace( prefix, ns );
LOG.debug( prefix + "->" + ns );
}
if ( nsBindings.getPrefix( XSINS ) == null ) {
activeWriter.writeNamespace( XSI_PREFIX, XSINS );
}

for ( int i = 0; i < openElements - 1; i++ ) {
activeWriter.writeStartElement( ELEMENT_NAME_DUMMY_LEVEL );
for ( int i = 0; i < openElements; i++ ) {
activeWriter.writeStartElement( ELEMENT_NAME_OPEN_ELEMENT );
}
activeWriter.writeStartElement( ELEMENT_NAME_CONTENT );
activeWriter.writeEmptyElement( ELEMENT_NAME_UNCLEAR_REFERENCE );
}

@Override
Expand Down Expand Up @@ -301,9 +317,6 @@ public void writeEndDocument()
@Override
public void close()
throws XMLStreamException {
if ( activeWriter != sink ) {
activeWriter.writeEndElement();
}
activeWriter.close();
}

Expand Down