Author: dkulp Date: Fri Apr 6 13:42:02 2012 New Revision: 1310323 URL: http://svn.apache.org/viewvc?rev=1310323&view=rev Log: Merged revisions 1310319 via svn merge from https://svn.apache.org/repos/asf/camel/branches/camel-2.9.x
........ r1310319 | dkulp | 2012-04-06 09:38:11 -0400 (Fri, 06 Apr 2012) | 11 lines Merged revisions 1309926 via svn merge from https://svn.apache.org/repos/asf/camel/trunk ........ r1309926 | dkulp | 2012-04-05 12:23:32 -0400 (Thu, 05 Apr 2012) | 3 lines [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/branches/camel-2.8.x/ (props changed) camel/branches/camel-2.8.x/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java Propchange: camel/branches/camel-2.8.x/ ('svn:mergeinfo' removed) Propchange: camel/branches/camel-2.8.x/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: camel/branches/camel-2.8.x/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.8.x/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java?rev=1310323&r1=1310322&r2=1310323&view=diff ============================================================================== --- camel/branches/camel-2.8.x/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java (original) +++ camel/branches/camel-2.8.x/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxConverter.java Fri Apr 6 13:42:02 2012 @@ -16,28 +16,31 @@ */ package org.apache.camel.converter.jaxp; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; +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.converter.IOConverter; import org.apache.camel.util.IOHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A converter of StAX objects @@ -46,37 +49,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(outputStream, IOConverter.getCharsetName(exchange)); + XMLOutputFactory factory = getOutputFactory(); + try { + return factory.createXMLStreamWriter(outputStream, IOConverter.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); + } } /** @@ -84,27 +154,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 { + XMLInputFactory factory = getInputFactory(); + try { + return factory.createXMLStreamReader(new StringReader(string)); + } finally { + returnXMLInputFactory(factory); + } } /** @@ -112,56 +223,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; } + + }
