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;
     }
+    
+
 }


Reply via email to