org.mule.module.xml.stax.StaxSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mule-module-xml Show documentation
Show all versions of mule-module-xml Show documentation
Functionality for working with XML
/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.module.xml.stax;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javanet.staxutils.StAXReaderToContentHandler;
import javanet.staxutils.StAXSource;
import javanet.staxutils.helpers.XMLFilterImplEx;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
/**
* A StaxSource which gives us access to the underlying XMLStreamReader if we are
* StaxCapable down the line.
*/
public class StaxSource extends StAXSource
{
private XMLStreamReader reader;
// StAX to SAX converter that will read from StAX and produce SAX
// this object will be wrapped by the XMLReader exposed to the client
protected final StAXReaderToContentHandler handler;
// SAX allows ContentHandler to be changed during the parsing,
// but JAXB doesn't. So this repeater will sit between those
// two components.
protected XMLFilterImplEx repeater = new XMLFilterImplEx();
protected final XMLReader pseudoParser = new PseudoReader();
public StaxSource(XMLStreamReader reader)
{
super(reader);
this.reader = reader;
this.handler = new XMLStreamReaderToContentHandler(reader, repeater);
super.setXMLReader(pseudoParser);
// pass a dummy InputSource. We don't care
super.setInputSource(new InputSource());
}
public XMLStreamReader getXMLStreamReader()
{
return reader;
}
public final class PseudoReader implements XMLReader
{
// we will store this value but never use it by ourselves.
private EntityResolver entityResolver;
private DTDHandler dtdHandler;
private ErrorHandler errorHandler;
public boolean getFeature(String name) throws SAXNotRecognizedException
{
if ("http://xml.org/sax/features/namespaces".equals(name))
{
return true;
}
else if ("http://xml.org/sax/features/namespace-prefixes".equals(name))
{
return repeater.getNamespacePrefixes();
}
else if ("http://xml.org/sax/features/external-general-entities".equals(name))
{
return true;
}
else if ("http://xml.org/sax/features/external-parameter-entities".equals(name))
{
return true;
}
throw new SAXNotRecognizedException(name);
}
public void setFeature(String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException
{
if ("http://xml.org/sax/features/namespaces".equals(name))
{
// Presently we only support namespaces==true. [Issue 9]
if (!value)
{
throw new SAXNotSupportedException(name);
}
}
else if ("http://xml.org/sax/features/namespace-prefixes".equals(name))
{
repeater.setNamespacePrefixes(value);
}
else if ("http://xml.org/sax/features/external-general-entities".equals(name))
{
// Pass over, XOM likes to get this feature
}
else if ("http://xml.org/sax/features/external-parameter-entities".equals(name))
{
// Pass over, XOM likes to get this feature
}
else if ("http://xml.org/sax/features/validation".equals(name))
{
// Don't really make sense when using Stax
}
else
{
throw new SAXNotRecognizedException(name);
}
}
public Object getProperty(String name) throws SAXNotRecognizedException
{
if ("http://xml.org/sax/properties/lexical-handler".equals(name))
{
return repeater.getLexicalHandler();
}
throw new SAXNotRecognizedException(name);
}
public void setProperty(String name, Object value) throws SAXNotRecognizedException
{
if ("http://xml.org/sax/properties/lexical-handler".equals(name))
{
repeater.setLexicalHandler((LexicalHandler) value);
}
else
{
throw new SAXNotRecognizedException(name);
}
}
public void setEntityResolver(EntityResolver resolver)
{
this.entityResolver = resolver;
}
public EntityResolver getEntityResolver()
{
return entityResolver;
}
public void setDTDHandler(DTDHandler handler)
{
this.dtdHandler = handler;
}
public DTDHandler getDTDHandler()
{
return dtdHandler;
}
public void setContentHandler(ContentHandler handler)
{
repeater.setContentHandler(handler);
}
public ContentHandler getContentHandler()
{
return repeater.getContentHandler();
}
public void setErrorHandler(ErrorHandler handler)
{
this.errorHandler = handler;
}
public ErrorHandler getErrorHandler()
{
return errorHandler;
}
public void parse(InputSource input) throws SAXException
{
parse();
}
public void parse(String systemId) throws SAXException
{
parse();
}
public void parse() throws SAXException
{
// parses from a StAX reader and generates SAX events which
// go through the repeater and are forwarded to the appropriate
// component
try
{
handler.bridge();
}
catch (XMLStreamException e)
{
// determine location
int lineNumber = -1;
int columnNumber = -1;
if (e.getLocation() != null)
{
lineNumber = e.getLocation().getLineNumber();
columnNumber = e.getLocation().getColumnNumber();
}
// wrap it in a SAXException
SAXParseException se = new SAXParseException(e.getMessage(), null, null, lineNumber, columnNumber, e);
// if the consumer sets an error handler, it is our responsibility
// to notify it.
if (errorHandler != null) errorHandler.fatalError(se);
// this is a fatal error. Even if the error handler
// returns, we will abort anyway.
throw se;
}
finally
{
try
{
reader.close();
}
catch (XMLStreamException e)
{
throw new SAXException(e);
}
}
}
}
}