Author: dkulp
Date: Thu Apr 5 16:23:32 2012
New Revision: 1309926
URL: http://svn.apache.org/viewvc?rev=1309926&view=rev
Log:
[CAMEL-5142] Use a pool of input/output factories in StaxConverter to
allow it to work better with the in-jdk parsers. Log some info entries
for things that are known to sometimes be problematic.
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java
URL:
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java?rev=1309926&r1=1309925&r2=1309926&view=diff
==============================================================================
---
camel/trunk/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java
(original)
+++
camel/trunk/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java
Thu Apr 5 16:23:32 2012
@@ -17,20 +17,29 @@
package org.apache.camel.converter.jaxp;
import java.io.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
import org.apache.camel.Converter;
import org.apache.camel.Exchange;
import org.apache.camel.util.IOHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A converter of StAX objects
@@ -39,37 +48,104 @@ import org.apache.camel.util.IOHelper;
*/
@Converter
public class StaxConverter {
+ private static final transient Logger LOG =
LoggerFactory.getLogger(XmlErrorListener.class);
+
+ private static final BlockingQueue<XMLInputFactory> INPUT_FACTORY_POOL;
+ private static final BlockingQueue<XMLOutputFactory> OUTPUT_FACTORY_POOL;
+ static {
+ int i = 20;
+ try {
+ String s = AccessController.doPrivileged(new
PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return
System.getProperty("org.apache.cxf.staxutils.pool-size", "-1");
+ }
+ });
+ i = Integer.parseInt(s);
+ } catch (Throwable t) {
+ //ignore
+ i = 20;
+ }
+ if (i <= 0) {
+ i = 20;
+ }
+ INPUT_FACTORY_POOL = new LinkedBlockingQueue<XMLInputFactory>(i);
+ OUTPUT_FACTORY_POOL = new LinkedBlockingQueue<XMLOutputFactory>(i);
+ }
+
private XMLInputFactory inputFactory;
private XMLOutputFactory outputFactory;
@Converter
public XMLEventWriter createXMLEventWriter(OutputStream out, Exchange
exchange) throws XMLStreamException {
- return getOutputFactory().createXMLEventWriter(IOHelper.buffered(out),
IOHelper.getCharsetName(exchange));
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ return factory.createXMLEventWriter(IOHelper.buffered(out),
IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
@Converter
public XMLEventWriter createXMLEventWriter(Writer writer) throws
XMLStreamException {
- return
getOutputFactory().createXMLEventWriter(IOHelper.buffered(writer));
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ return factory.createXMLEventWriter(IOHelper.buffered(writer));
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
@Converter
public XMLEventWriter createXMLEventWriter(Result result) throws
XMLStreamException {
- return getOutputFactory().createXMLEventWriter(result);
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ if (result instanceof DOMResult && !isWoodstox(factory)) {
+ //FIXME - if not woodstox, this will likely not work well
+ //likely should copy CXF's W3CDOM stuff
+ LOG.info("DOMResult is known to have issues with {0}. We
suggest using Woodstox",
+ factory.getClass());
+ }
+ return factory.createXMLEventWriter(result);
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
@Converter
public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream,
Exchange exchange) throws XMLStreamException {
- return
getOutputFactory().createXMLStreamWriter(IOHelper.buffered(outputStream),
IOHelper.getCharsetName(exchange));
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ return
factory.createXMLStreamWriter(IOHelper.buffered(outputStream),
IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
@Converter
public XMLStreamWriter createXMLStreamWriter(Writer writer) throws
XMLStreamException {
- return
getOutputFactory().createXMLStreamWriter(IOHelper.buffered(writer));
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ return factory.createXMLStreamWriter(IOHelper.buffered(writer));
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
@Converter
public XMLStreamWriter createXMLStreamWriter(Result result) throws
XMLStreamException {
- return getOutputFactory().createXMLStreamWriter(result);
+ XMLOutputFactory factory = getOutputFactory();
+ try {
+ if (result instanceof DOMResult && !isWoodstox(factory)) {
+ //FIXME - if not woodstox, this will likely not work well
+ //likely should copy CXF's W3CDOM stuff
+ LOG.info("DOMResult is known to have issues with {0}. We
suggest using Woodstox",
+ factory.getClass());
+ }
+ return factory.createXMLStreamWriter(result);
+ } finally {
+ returnXMLOutputFactory(factory);
+ }
}
/**
@@ -77,32 +153,68 @@ public class StaxConverter {
*/
@Deprecated
public XMLStreamReader createXMLStreamReader(InputStream in) throws
XMLStreamException {
- return getInputFactory().createXMLStreamReader(IOHelper.buffered(in));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLStreamReader(IOHelper.buffered(in));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLStreamReader createXMLStreamReader(InputStream in, Exchange
exchange) throws XMLStreamException {
- return getInputFactory().createXMLStreamReader(IOHelper.buffered(in),
IOHelper.getCharsetName(exchange));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLStreamReader(IOHelper.buffered(in),
IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLStreamReader createXMLStreamReader(File file, Exchange exchange)
throws XMLStreamException, FileNotFoundException {
- return getInputFactory().createXMLStreamReader(IOHelper.buffered(new
FileInputStream(file)), IOHelper.getCharsetName(exchange));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLStreamReader(IOHelper.buffered(new
FileInputStream(file)), IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLStreamReader createXMLStreamReader(Reader reader) throws
XMLStreamException {
- return
getInputFactory().createXMLStreamReader(IOHelper.buffered(reader));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLStreamReader(IOHelper.buffered(reader));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLStreamReader createXMLStreamReader(Source in) throws
XMLStreamException {
- return getInputFactory().createXMLStreamReader(in);
+ XMLInputFactory factory = getInputFactory();
+ try {
+ if (in instanceof DOMSource && !isWoodstox(factory)) {
+ //FIXME - if not woodstox, this will likely not work well
+ //likely should copy CXF's W3CDOM stuff
+ LOG.info("DOMSource is known to have issues with {0}. We
suggest using Woodstox",
+ factory.getClass());
+ }
+ return factory.createXMLStreamReader(in);
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLStreamReader createXMLStreamReader(String string) throws
XMLStreamException {
- return getInputFactory().createXMLStreamReader(new
StringReader(string));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLStreamReader(new StringReader(string));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
/**
@@ -110,56 +222,148 @@ public class StaxConverter {
*/
@Deprecated
public XMLEventReader createXMLEventReader(InputStream in) throws
XMLStreamException {
- return getInputFactory().createXMLEventReader(IOHelper.buffered(in));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLEventReader(IOHelper.buffered(in));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLEventReader createXMLEventReader(InputStream in, Exchange
exchange) throws XMLStreamException {
- return getInputFactory().createXMLEventReader(IOHelper.buffered(in),
IOHelper.getCharsetName(exchange));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLEventReader(IOHelper.buffered(in),
IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLEventReader createXMLEventReader(File file, Exchange exchange)
throws XMLStreamException, FileNotFoundException {
- return getInputFactory().createXMLEventReader(IOHelper.buffered(new
FileInputStream(file)), IOHelper.getCharsetName(exchange));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLEventReader(IOHelper.buffered(new
FileInputStream(file)), IOHelper.getCharsetName(exchange));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLEventReader createXMLEventReader(Reader reader) throws
XMLStreamException {
- return
getInputFactory().createXMLEventReader(IOHelper.buffered(reader));
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLEventReader(IOHelper.buffered(reader));
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws
XMLStreamException {
- return getInputFactory().createXMLEventReader(reader);
+ XMLInputFactory factory = getInputFactory();
+ try {
+ return factory.createXMLEventReader(reader);
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
@Converter
public XMLEventReader createXMLEventReader(Source in) throws
XMLStreamException {
- return getInputFactory().createXMLEventReader(in);
+ XMLInputFactory factory = getInputFactory();
+ try {
+ if (in instanceof DOMSource && !isWoodstox(factory)) {
+ //FIXME - if not woodstox, this will likely not work well
+ LOG.info("DOMSource is known to have issues with {0}. We
suggest using Woodstox",
+ factory.getClass());
+ }
+ return factory.createXMLEventReader(in);
+ } finally {
+ returnXMLInputFactory(factory);
+ }
}
+
+
+ private boolean isWoodstox(Object factory) {
+ return
factory.getClass().getPackage().getName().startsWith("com.ctc.wstx");
+ }
+
+ private XMLInputFactory getXMLInputFactory() {
+ XMLInputFactory f = INPUT_FACTORY_POOL.poll();
+ if (f == null) {
+ f = createXMLInputFactory(true);
+ }
+ return f;
+ }
+
+ private void returnXMLInputFactory(XMLInputFactory factory) {
+ if (factory != inputFactory) {
+ INPUT_FACTORY_POOL.offer(factory);
+ }
+ }
+
+ private XMLOutputFactory getXMLOutputFactory() {
+ XMLOutputFactory f = OUTPUT_FACTORY_POOL.poll();
+ if (f == null) {
+ f = XMLOutputFactory.newInstance();
+ }
+ return f;
+ }
+
+ private void returnXMLOutputFactory(XMLOutputFactory factory) {
+ if (factory != outputFactory) {
+ OUTPUT_FACTORY_POOL.offer(factory);
+ }
+ }
+
+ public static XMLInputFactory createXMLInputFactory(boolean nsAware) {
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ setProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, nsAware);
+ setProperty(factory, XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+ setProperty(factory, XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES,
Boolean.FALSE);
+ setProperty(factory, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
Boolean.FALSE);
+ factory.setXMLResolver(new XMLResolver() {
+ public Object resolveEntity(String publicID, String systemID,
+ String baseURI, String namespace)
+ throws XMLStreamException {
+ throw new XMLStreamException("Reading external entities is
disabled");
+ }
+ });
+ return factory;
+ }
+
+ private static void setProperty(XMLInputFactory f, String p, Object o) {
+ try {
+ f.setProperty(p, o);
+ } catch (Throwable t) {
+ //ignore
+ }
+ }
+
// Properties
//-------------------------------------------------------------------------
-
public XMLInputFactory getInputFactory() {
if (inputFactory == null) {
- inputFactory = XMLInputFactory.newInstance();
+ return getXMLInputFactory();
}
return inputFactory;
}
-
- public void setInputFactory(XMLInputFactory inputFactory) {
- this.inputFactory = inputFactory;
- }
-
public XMLOutputFactory getOutputFactory() {
if (outputFactory == null) {
- outputFactory = XMLOutputFactory.newInstance();
+ return getXMLOutputFactory();
}
return outputFactory;
}
-
+
+ public void setInputFactory(XMLInputFactory inputFactory) {
+ this.inputFactory = inputFactory;
+ }
public void setOutputFactory(XMLOutputFactory outputFactory) {
this.outputFactory = outputFactory;
}
+
+
}