Author: boisvert
Date: Thu Mar 22 12:18:55 2007
New Revision: 521409
URL: http://svn.apache.org/viewvc?view=rev&rev=521409
Log:
Improve DOM conversion performance
Modified:
incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/msgmap/BaseXmlMapper.java
incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java
Modified:
incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/msgmap/BaseXmlMapper.java
URL:
http://svn.apache.org/viewvc/incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/msgmap/BaseXmlMapper.java?view=diff&rev=521409&r1=521408&r2=521409
==============================================================================
---
incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/msgmap/BaseXmlMapper.java
(original)
+++
incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/msgmap/BaseXmlMapper.java
Thu Mar 22 12:18:55 2007
@@ -36,51 +36,28 @@
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.sun.org.apache.xerces.internal.util.DOMUtil;
-
public abstract class BaseXmlMapper {
protected Log __log = LogFactory.getLog(getClass());
- private TransformerFactory _transformerFactory;
-
/** Cache of the parsed messages. */
private static Map<Source, Document> __parsed =
Collections.synchronizedMap(new WeakHashMap<Source, Document>());
- private static ThreadLocal<Transformer> __txers = new ThreadLocal();
-
protected BaseXmlMapper() {
- _transformerFactory = TransformerFactory.newInstance();
}
protected Element parse(Source content) throws MessageTranslationException
{
-
// Check for the message in the cache. note that we are using a
synchronized map here,
- // so that we are thread safe, although it is possible for the parse
to happen twice.
+ // so that we are thread safe, although it is possible for the parse
to happen twice.
Document parsed = __parsed.get(content);
if (parsed != null)
return parsed.getDocumentElement();
- Transformer txer = __txers.get();
- if (txer == null) {
- try {
- txer = _transformerFactory.newTransformer();
- __txers.set(txer);
- } catch (TransformerConfigurationException e) {
- String errmsg = "Transformer configuration error!";
- __log.fatal(errmsg, e);
- throw new Error(errmsg, e);
- }
- }
-
try {
- DOMResult domresult = new DOMResult();
- txer.transform(content, domresult);
- parsed = (Document) domresult.getNode();
- // Again, synchronized map...
+ parsed = DOMUtils.sourceToDOM(content);
__parsed.put(content, parsed);
return parsed.getDocumentElement();
- } catch (TransformerException e) {
- throw new MessageTranslationException("Transformer error!", e);
+ } catch (Exception e) {
+ throw new MessageTranslationException("Message parsing exception",
e);
}
}
Modified:
incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java
URL:
http://svn.apache.org/viewvc/incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java?view=diff&rev=521409&r1=521408&r2=521409
==============================================================================
--- incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java
(original)
+++ incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java
Thu Mar 22 12:18:55 2007
@@ -38,6 +38,19 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+//import javax.xml.transform.stax.StAXSource;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
@@ -53,51 +66,23 @@
/** The namespaceURI represented by the prefix <code>xmlns</code>. */
public static final String NS_URI_XMLNS = "http://www.w3.org/2000/xmlns/";
+ private static ThreadLocal<Transformer> __txers = new ThreadLocal();
+ private static ThreadLocal<DocumentBuilder> __builders = new ThreadLocal();
+ private static TransformerFactory _transformerFactory =
TransformerFactory.newInstance();
+
private static DocumentBuilderFactory __documentBuilderFactory ;
- private static ObjectPool __documentBuilderPool;
static {
- initDocumentBuilderPool();
+ initDocumentBuilderFactory();
}
/**
- * Initialize the document-builder pool.
+ * Initialize the document-builder factory.
*/
- private static void initDocumentBuilderPool() {
+ private static void initDocumentBuilderFactory() {
DocumentBuilderFactory f = XMLParserUtils.getDocumentBuilderFactory();
f.setNamespaceAware(true);
__documentBuilderFactory = f;
-
- PoolableObjectFactory pof = new BasePoolableObjectFactory() {
- public Object makeObject() throws Exception {
- if (__log.isDebugEnabled()) {
- __log.debug("makeObject: Creating new DocumentBuilder.");
- }
-
- DocumentBuilder db = null;
- synchronized (__documentBuilderFactory) {
- try {
- db = __documentBuilderFactory.newDocumentBuilder();
- db.setErrorHandler(new LoggingErrorHandler());
- } catch (ParserConfigurationException e) {
- __log.error(e);
- throw new RuntimeException(e);
- }
- }
- return db;
- }
-
- public void destroyObject(Object obj) throws Exception {
- if (__log.isDebugEnabled())
- __log.debug("destroyObject: Removing DocumentBuilder from
pool: " + obj);
- }
- };
-
- GenericObjectPool.Config poolCfg = new GenericObjectPool.Config();
- poolCfg.maxActive = Integer.MAX_VALUE;
- poolCfg.maxIdle = 20;
- poolCfg.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
- __documentBuilderPool = new GenericObjectPool(pof, poolCfg);
}
/**
@@ -603,17 +588,8 @@
}
public static Document newDocument() {
- DocumentBuilder db;
- try {
- db = borrow();
- } catch (Exception ex) {
- throw new RuntimeException("XML PARSE ERROR (NO PARSERS!)", ex);
- }
- try {
- return db.newDocument();
- } finally {
- returnObject(db);
- }
+ DocumentBuilder db = getBuilder();
+ return db.newDocument();
}
/**
@@ -630,36 +606,54 @@
* pooled document builder.
*/
public static Document parse(InputSource inputSource) throws
SAXException,IOException{
- DocumentBuilder db = borrow();
- try {
- return db.parse(inputSource);
- } finally {
- returnObject(db);
- }
-
+ DocumentBuilder db = getBuilder();
+ return db.parse(inputSource);
}
/**
- * Borrow a [EMAIL PROTECTED] DocumentBuilder} to the pool.
+ * Parse an XML document located using an [EMAIL PROTECTED] InputSource}
using the
+ * pooled document builder.
*/
- private static synchronized DocumentBuilder borrow() throws SAXException {
+ public static Document sourceToDOM(Source inputSource) throws IOException {
try {
- return (DocumentBuilder) __documentBuilderPool.borrowObject();
- } catch (SAXException sae) {
- throw sae;
- } catch (Exception ex) {
- throw new SAXException(ex);
- }
-
- }
-
- /** Return the [EMAIL PROTECTED] DocumentBuilder} to the pool. */
- private static synchronized void returnObject(DocumentBuilder db) {
- try {
- __documentBuilderPool.returnObject(db);
- } catch (Exception ex) {
- __log.debug("Error returning DocumentBuilder to object pool
(ignoring).", ex);
+ /*
+ // Requires JDK 1.6+
+ if (inputSource instanceof StAXSource) {
+ StAXSource stax = (StAXSource) inputSource;
+ //if (stax.getXMLEventReader() != null ||
sax.getXMLStreamReader() != null) {
+ if (sax.getXMLStreamReader() != null) {
+ return parse(stax.getXMLStreamReader());
+ }
+ }
+ */
+ if (inputSource instanceof SAXSource) {
+ InputSource sax = ((SAXSource) inputSource).getInputSource();
+ if (sax.getCharacterStream() != null || sax.getByteStream() !=
null) {
+ return parse( ((SAXSource) inputSource).getInputSource() );
+ }
+ }
+ if (inputSource instanceof DOMSource) {
+ Node node = ((DOMSource) inputSource).getNode();
+ if (node != null) {
+ return toDOMDocument(node);
+ }
+ }
+ if (inputSource instanceof StreamSource) {
+ StreamSource stream = (StreamSource) inputSource;
+ if (stream.getReader() != null || stream.getInputStream() !=
null) {
+ return toDocumentFromStream( (StreamSource) inputSource);
+ }
+ }
+ DOMResult domresult = new DOMResult(newDocument());
+ Transformer txer = getTransformer();
+ txer.transform(inputSource, domresult);
+ return (Document) domresult.getNode();
+ } catch (SAXException e) {
+ throwIOException(e);
+ } catch (TransformerException e) {
+ throwIOException(e);
}
+ throw new IllegalArgumentException("Cannot parse XML source: " +
inputSource.getClass());
}
/**
@@ -790,10 +784,187 @@
String prefix = nscontext.getPrefix(uri);
if (prefix == null || "".equals(prefix))
domElement.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns", uri);
- else
+ else
domElement.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns:"+
prefix, uri);
-
+
+ }
+ }
+
+ public static Document toDOMDocument(Node node) throws
TransformerException {
+ // If the node is the document, just cast it
+ if (node instanceof Document) {
+ return (Document) node;
+ // If the node is an element
+ } else if (node instanceof Element) {
+ Element elem = (Element) node;
+ // If this is the root element, return its owner document
+ if (elem.getOwnerDocument().getDocumentElement() == elem) {
+ return elem.getOwnerDocument();
+ // else, create a new doc and copy the element inside it
+ } else {
+ Document doc = newDocument();
+ doc.appendChild(doc.importNode(node, true));
+ return doc;
+ }
+ // other element types are not handled
+ } else {
+ throw new TransformerException("Unable to convert DOM node to a
Document");
+ }
+ }
+
+ public static Document toDocumentFromStream(StreamSource source) throws
IOException, SAXException {
+ DocumentBuilder builder = getBuilder();
+ Document document = null;
+ Reader reader = source.getReader();
+ if (reader != null) {
+ document = builder.parse(new InputSource(reader));
+ } else {
+ InputStream inputStream = source.getInputStream();
+ if (inputStream != null) {
+ InputSource inputsource = new InputSource(inputStream);
+ inputsource.setSystemId( source.getSystemId() );
+ document = builder.parse(inputsource);
+ }
+ else {
+ throw new IOException("No input stream or reader available");
+ }
+ }
+ return document;
+ }
+
+ // sadly, as of JDK 5.0 IOException still doesn't support new
IOException(Throwable)
+ private static void throwIOException(Throwable t) throws IOException {
+ IOException e = new IOException(t.getMessage());
+ e.setStackTrace(t.getStackTrace());
+ throw e;
+ }
+
+
+ public static Document parse(XMLStreamReader reader)
+ throws XMLStreamException
+ {
+ Document doc = newDocument();
+ parse(reader, doc, doc);
+ return doc;
+ }
+
+ private static void parse(XMLStreamReader reader, Document doc, Node
parent)
+ throws XMLStreamException
+ {
+ int event = reader.getEventType();
+
+ while (reader.hasNext()) {
+ switch (event) {
+ case XMLStreamConstants.START_ELEMENT:
+ // create element
+ Element e = doc.createElementNS(reader.getNamespaceURI(),
reader.getLocalName());
+ if (reader.getPrefix() != null && reader.getPrefix() != "") {
+ e.setPrefix(reader.getPrefix());
+ }
+ parent.appendChild(e);
+
+ // copy namespaces
+ for (int ns = 0; ns < reader.getNamespaceCount(); ns++) {
+ String uri = reader.getNamespaceURI(ns);
+ String prefix = reader.getNamespacePrefix(ns);
+ declare(e, uri, prefix);
+ }
+
+ // copy attributes
+ for (int att = 0; att < reader.getAttributeCount(); att++) {
+ String name = reader.getAttributeLocalName(att);
+ String prefix = reader.getAttributePrefix(att);
+ if (prefix != null && prefix.length() > 0) {
+ name = prefix + ":" + name;
+ }
+ Attr attr =
doc.createAttributeNS(reader.getAttributeNamespace(att), name);
+ attr.setValue(reader.getAttributeValue(att));
+ e.setAttributeNode(attr);
+ }
+ // sub-nodes
+ if (reader.hasNext()) {
+ reader.next();
+ parse(reader, doc, e);
+ }
+ if (parent instanceof Document) {
+ while (reader.hasNext()) reader.next();
+ return;
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ return;
+ case XMLStreamConstants.CHARACTERS:
+ if (parent != null) {
+ parent.appendChild(doc.createTextNode(reader.getText()));
+ }
+ break;
+ case XMLStreamConstants.COMMENT:
+ if (parent != null) {
+ parent.appendChild(doc.createComment(reader.getText()));
+ }
+ break;
+ case XMLStreamConstants.CDATA:
+ parent.appendChild(doc.createCDATASection(reader.getText()));
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+
parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(),
reader.getPIData()));
+ break;
+ case XMLStreamConstants.ENTITY_REFERENCE:
+
parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(),
reader.getPIData()));
+ break;
+ case XMLStreamConstants.NAMESPACE:
+ case XMLStreamConstants.ATTRIBUTE:
+ break;
+ default:
+ break;
+ }
+
+ if (reader.hasNext()) {
+ event = reader.next();
+ }
+ }
+ }
+
+ private static void declare(Element node, String uri, String prefix) {
+ if (prefix != null && prefix.length() > 0) {
+ node.setAttributeNS(NS_URI_XMLNS, "xmlns:" + prefix, uri);
+ } else {
+ if (uri != null) {
+ node.setAttributeNS(NS_URI_XMLNS, "xmlns", uri);
+ }
+ }
+ }
+
+ private static Transformer getTransformer() {
+ Transformer txer = __txers.get();
+ if (txer == null) {
+ try {
+ txer = _transformerFactory.newTransformer();
+ __txers.set(txer);
+ } catch (TransformerConfigurationException e) {
+ String errmsg = "Transformer configuration error!";
+ __log.fatal(errmsg, e);
+ throw new Error(errmsg, e);
+ }
+ }
+ return txer;
+ }
+
+ private static DocumentBuilder getBuilder() {
+ DocumentBuilder builder = __builders.get();
+ if (builder == null) {
+ synchronized (__documentBuilderFactory) {
+ try {
+ builder = __documentBuilderFactory.newDocumentBuilder();
+ builder.setErrorHandler(new LoggingErrorHandler());
+ } catch (ParserConfigurationException e) {
+ __log.error(e);
+ throw new RuntimeException(e);
+ }
+ }
+ __builders.set(builder);
}
+ return builder;
}
}