You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dk...@apache.org on 2016/02/01 22:06:31 UTC

[1/5] camel git commit: CAMEL-9534: XmlConverter: use a pool of SAXParser / XMLReader instances

Repository: camel
Updated Branches:
  refs/heads/master 7d781cce7 -> 070ed43e1


CAMEL-9534: XmlConverter: use a pool of SAXParser / XMLReader instances

Creating and configuring a new SAXParserFactory and SAXParser / XMLReader
for every SAXSource is very expensive.

A SAXParser / XMLReader instance can be used to parse many XML documents.

Add an XMLReaderPool helper to manage existing XMLReader instances (i.e.
hand out existing instances from the pool, reset properties / features and
return the instance to the pool after use).

Use pooled XMLReaders in XmlConverter.toSAXSource* (except if a specific
SAXParserFactory is configured on the Exchange).

Signed-off-by: Karsten Blees <ka...@dcon.de>


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/3c8560f0
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/3c8560f0
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/3c8560f0

Branch: refs/heads/master
Commit: 3c8560f003e0a4534cef428664fd4811621aa03c
Parents: 7d90d5d
Author: Karsten Blees <bl...@dcon.de>
Authored: Wed Jan 27 19:10:22 2016 +0100
Committer: Daniel Kulp <dk...@apache.org>
Committed: Mon Feb 1 16:06:24 2016 -0500

----------------------------------------------------------------------
 .../camel/converter/jaxp/XMLReaderPool.java     | 234 +++++++++++++++++++
 .../camel/converter/jaxp/XmlConverter.java      |  50 ++--
 2 files changed, 265 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/3c8560f0/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
new file mode 100644
index 0000000..ec50920
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
@@ -0,0 +1,234 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxp;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+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.XMLReader;
+
+/**
+ * Manages a pool of XMLReader (and associated SAXParser) instances for reuse.
+ */
+public class XMLReaderPool {
+    private final Queue<WeakReference<XMLReader>> pool = new ConcurrentLinkedQueue<WeakReference<XMLReader>>();
+    private final SAXParserFactory saxParserFactory;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param saxParserFactory
+     *            the SAXParserFactory used to create new SAXParser instances
+     */
+    public XMLReaderPool(SAXParserFactory saxParserFactory) {
+        this.saxParserFactory = saxParserFactory;
+    }
+
+    /**
+     * Returns an XMLReader that can be used exactly once. Calling one of the
+     * {@code parse} methods returns the reader to the pool. This is useful
+     * for e.g. SAXSource which bundles an XMLReader with an InputSource that
+     * can also be consumed just once.
+     *
+     * @return the XMLReader
+     * @throws SAXException
+     *             see {@link SAXParserFactory#newSAXParser()}
+     * @throws ParserConfigurationException
+     *             see {@link SAXParserFactory#newSAXParser()}
+     */
+    public XMLReader createXMLReader() throws SAXException, ParserConfigurationException {
+        XMLReader xmlReader = null;
+        WeakReference<XMLReader> ref;
+        while ((ref = pool.poll()) != null) {
+            if ((xmlReader = ref.get()) != null)
+                break;
+        }
+
+        if (xmlReader == null) {
+            xmlReader = saxParserFactory.newSAXParser().getXMLReader();
+        }
+
+        return new OneTimeXMLReader(xmlReader);
+    }
+
+    /**
+     * Wraps another XMLReader for single use only.
+     */
+    private class OneTimeXMLReader implements XMLReader {
+        private XMLReader xmlReader;
+        private final Map<String, Boolean> initFeatures = new HashMap<String, Boolean>();
+        private final Map<String, Object> initProperties = new HashMap<String, Object>();
+        private final ContentHandler initContentHandler;
+        private final DTDHandler initDtdHandler;
+        private final EntityResolver initEntityResolver;
+        private final ErrorHandler initErrorHandler;
+
+        private OneTimeXMLReader(XMLReader xmlReader) {
+            this.xmlReader = xmlReader;
+            this.initContentHandler = xmlReader.getContentHandler();
+            this.initDtdHandler = xmlReader.getDTDHandler();
+            this.initEntityResolver = xmlReader.getEntityResolver();
+            this.initErrorHandler = xmlReader.getErrorHandler();
+        }
+
+        private void release() {
+            // reset XMLReader to its initial state
+            for (Map.Entry<String, Boolean> feature : initFeatures.entrySet()) {
+                try {
+                    xmlReader.setFeature(feature.getKey(), feature.getValue().booleanValue());
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            for (Map.Entry<String, Object> property : initProperties.entrySet()) {
+                try {
+                    xmlReader.setProperty(property.getKey(), property.getValue());
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            xmlReader.setContentHandler(initContentHandler);
+            xmlReader.setDTDHandler(initDtdHandler);
+            xmlReader.setEntityResolver(initEntityResolver);
+            xmlReader.setErrorHandler(initErrorHandler);
+
+            // return the wrapped instance to the pool
+            pool.offer(new WeakReference<XMLReader>(xmlReader));
+            xmlReader = null;
+        }
+
+        private void checkValid() {
+            if (xmlReader == null)
+                throw new IllegalStateException("OneTimeXMLReader.parse() can only be used once!");
+        }
+
+        @Override
+        public boolean getFeature(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException {
+            checkValid();
+            return xmlReader.getFeature(name);
+        }
+
+        @Override
+        public void setFeature(String name, boolean value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {
+            checkValid();
+            if (!initFeatures.containsKey(name))
+                initFeatures.put(name, Boolean.valueOf(xmlReader.getFeature(name)));
+            xmlReader.setFeature(name, value);
+        }
+
+        @Override
+        public Object getProperty(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException {
+            checkValid();
+            return xmlReader.getProperty(name);
+        }
+
+        @Override
+        public void setProperty(String name, Object value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {
+            checkValid();
+            if (!initProperties.containsKey(name))
+                initProperties.put(name, xmlReader.getProperty(name));
+            xmlReader.setProperty(name, value);
+        }
+
+        @Override
+        public ContentHandler getContentHandler() {
+            checkValid();
+            return xmlReader.getContentHandler();
+        }
+
+        @Override
+        public void setContentHandler(ContentHandler handler) {
+            checkValid();
+            xmlReader.setContentHandler(handler);
+        }
+
+        @Override
+        public DTDHandler getDTDHandler() {
+            checkValid();
+            return xmlReader.getDTDHandler();
+        }
+
+        @Override
+        public void setDTDHandler(DTDHandler handler) {
+            checkValid();
+            xmlReader.setDTDHandler(handler);
+        }
+
+        @Override
+        public EntityResolver getEntityResolver() {
+            checkValid();
+            return xmlReader.getEntityResolver();
+        }
+
+        @Override
+        public void setEntityResolver(EntityResolver resolver) {
+            checkValid();
+            xmlReader.setEntityResolver(resolver);
+        }
+
+        @Override
+        public ErrorHandler getErrorHandler() {
+            checkValid();
+            return xmlReader.getErrorHandler();
+        }
+
+        @Override
+        public void setErrorHandler(ErrorHandler handler) {
+            checkValid();
+            xmlReader.setErrorHandler(handler);
+        }
+
+        @Override
+        public void parse(InputSource input) throws IOException, SAXException {
+            checkValid();
+            try {
+                xmlReader.parse(input);
+            } finally {
+                release();
+            }
+        }
+
+        @Override
+        public void parse(String systemId) throws IOException, SAXException {
+            checkValid();
+            try {
+                xmlReader.parse(systemId);
+            } finally {
+                release();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/3c8560f0/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
index d29f643..649d327 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
@@ -36,7 +36,6 @@ import java.util.Properties;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
@@ -91,6 +90,7 @@ public class XmlConverter {
 
     private volatile DocumentBuilderFactory documentBuilderFactory;
     private volatile TransformerFactory transformerFactory;
+    private volatile XMLReaderPool xmlReaderPool;
 
     public XmlConverter() {
     }
@@ -581,31 +581,25 @@ public class XmlConverter {
         }
         inputSource.setSystemId(source.getSystemId());
         inputSource.setPublicId(source.getPublicId());
+
         XMLReader xmlReader = null;
-        SAXParserFactory sfactory = null;
-        //Need to setup XMLReader security feature by default
         try {
             // use the SAXPaserFactory which is set from exchange
             if (exchange != null) {
-                sfactory = exchange.getProperty(Exchange.SAXPARSER_FACTORY, SAXParserFactory.class);
-            }
-            if (sfactory == null) {
-                sfactory = SAXParserFactory.newInstance();
-                try {
-                    sfactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
-                } catch (Exception e) {
-                    LOG.warn("SAXParser doesn't support the feature {} with value {}, due to {}.", new Object[]{javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, "true", e});
+                SAXParserFactory sfactory = exchange.getProperty(Exchange.SAXPARSER_FACTORY, SAXParserFactory.class);
+                if (sfactory != null) {
+                    if (!sfactory.isNamespaceAware()) {
+                        sfactory.setNamespaceAware(true);
+                    }
+                    xmlReader = sfactory.newSAXParser().getXMLReader();
                 }
-                try {
-                    sfactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
-                } catch (SAXException e) {
-                    LOG.warn("SAXParser doesn't support the feature {} with value {}, due to {}."
-                            , new Object[]{"http://xml.org/sax/features/external-general-entities", false, e});                
+            }
+            if (xmlReader == null) {
+                if (xmlReaderPool == null) {
+                    xmlReaderPool = new XMLReaderPool(createSAXParserFactory());
                 }
+                xmlReader = xmlReaderPool.createXMLReader();
             }
-            sfactory.setNamespaceAware(true);
-            SAXParser parser = sfactory.newSAXParser();
-            xmlReader = parser.getXMLReader();
         } catch (Exception ex) {
             LOG.warn("Cannot create the SAXParser XMLReader, due to {}", ex);
         }
@@ -1208,4 +1202,22 @@ public class XmlConverter {
             }
         }
     }
+
+    public SAXParserFactory createSAXParserFactory() {
+        SAXParserFactory sfactory = SAXParserFactory.newInstance();
+        // Need to setup XMLReader security feature by default
+        try {
+            sfactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        } catch (Exception e) {
+            LOG.warn("SAXParser doesn't support the feature {} with value {}, due to {}.", new Object[]{javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, "true", e});
+        }
+        try {
+            sfactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+        } catch (Exception e) {
+            LOG.warn("SAXParser doesn't support the feature {} with value {}, due to {}."
+                    , new Object[]{"http://xml.org/sax/features/external-general-entities", false, e});
+        }
+        sfactory.setNamespaceAware(true);
+        return sfactory;
+    }
 }


[2/5] camel git commit: CAMEL-9534: optimize attribute handling in StAX2SAXSource adapter

Posted by dk...@apache.org.
CAMEL-9534: optimize attribute handling in StAX2SAXSource adapter

Creating a copy of all attribute data for each START_ELEMENT event is not
necessary and wastes time and memory.

Use a custom SAX Attributes implementation that just forwards all calls to
the respective StAX XMLStreamReader.getAttribute* methods.

Signed-off-by: Karsten Blees <ka...@dcon.de>


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/7d90d5d1
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/7d90d5d1
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/7d90d5d1

Branch: refs/heads/master
Commit: 7d90d5d14012b688af4038f9e38df218185a810a
Parents: 3ac8d9f
Author: Karsten Blees <bl...@dcon.de>
Authored: Sat Jan 30 14:04:51 2016 +0100
Committer: Daniel Kulp <dk...@apache.org>
Committed: Mon Feb 1 16:06:24 2016 -0500

----------------------------------------------------------------------
 .../camel/converter/jaxp/StAX2SAXSource.java    | 154 ++++++++++++++-----
 1 file changed, 112 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/7d90d5d1/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
index e4a68b6..957637b 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
@@ -33,7 +33,6 @@ import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.AttributesImpl;
 
 /**
  * Adapter to turn a StAX {@link XMLStreamReader} into a {@link SAXSource}.
@@ -60,6 +59,7 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
     }
 
     protected void parse() throws SAXException {
+        final StAX2SAXAttributes attributes = new StAX2SAXAttributes();
         try {
             while (true) {
                 switch (streamReader.getEventType()) {
@@ -110,19 +110,14 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
                     contentHandler.endDocument();
                     return;
                 case XMLStreamConstants.END_ELEMENT: {
-                    String uri = streamReader.getNamespaceURI();
+                    String uri = nullToEmpty(streamReader.getNamespaceURI());
                     String localName = streamReader.getLocalName();
-                    String prefix = streamReader.getPrefix();
-                    String qname = prefix != null && prefix.length() > 0
-                        ? prefix + ":" + localName : localName;
+                    String qname = getPrefixedName(streamReader.getPrefix(), localName);
                     contentHandler.endElement(uri, localName, qname);
+
                     // namespaces
                     for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
                         String nsPrefix = streamReader.getNamespacePrefix(i);
-                        String nsUri = streamReader.getNamespaceURI(i);
-                        if (nsUri == null) {
-                            nsUri = "";
-                        }
                         contentHandler.endPrefixMapping(nsPrefix);
                     }
                     break;
@@ -138,21 +133,19 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
                     contentHandler.startDocument();
                     break;
                 case XMLStreamConstants.START_ELEMENT: {
-                    String uri = streamReader.getNamespaceURI();
-                    String localName = streamReader.getLocalName();
-                    String prefix = streamReader.getPrefix();
-                    String qname = prefix != null && prefix.length() > 0
-                        ? prefix + ":" + localName : localName;
                     // namespaces
                     for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
                         String nsPrefix = streamReader.getNamespacePrefix(i);
-                        String nsUri = streamReader.getNamespaceURI(i);
-                        if (nsUri == null) {
-                            nsUri = "";
-                        }
+                        String nsUri = nullToEmpty(streamReader.getNamespaceURI(i));
                         contentHandler.startPrefixMapping(nsPrefix, nsUri);
                     }
-                    contentHandler.startElement(uri == null ? "" : uri, localName, qname, getAttributes());
+
+                    String uri = nullToEmpty(streamReader.getNamespaceURI());
+                    String localName = streamReader.getLocalName();
+                    String qname = getPrefixedName(streamReader.getPrefix(), localName);
+                    attributes.init();
+                    contentHandler.startElement(uri, localName, qname, attributes);
+                    attributes.reset();
                     break;
                 }
                 default:
@@ -177,37 +170,114 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
         }
     }
 
-    protected String getQualifiedName() {
-        String prefix = streamReader.getPrefix();
-        if (prefix != null && prefix.length() > 0) {
-            return prefix + ":" + streamReader.getLocalName();
-        } else {
-            return streamReader.getLocalName();
+    private String getPrefixedName(String prefix, String localName) {
+        if (prefix == null || prefix.length() == 0) {
+            return localName;
         }
+        return prefix + ":" + localName;
     }
 
-    protected Attributes getAttributes() {
-        AttributesImpl attrs = new AttributesImpl();
+    private String nullToEmpty(String s) {
+        return s == null ? "" : s;
+    }
 
-        for (int i = 0; i < streamReader.getAttributeCount(); i++) {
-            String uri = streamReader.getAttributeNamespace(i);
-            String localName = streamReader.getAttributeLocalName(i);
-            String prefix = streamReader.getAttributePrefix(i);
-            String qName;
-            if (prefix != null && prefix.length() > 0) {
-                qName = prefix + ':' + localName;
-            } else {
-                qName = localName;
+    class StAX2SAXAttributes implements Attributes {
+
+        private int attributeCount;
+
+        void init() {
+            attributeCount = streamReader.getAttributeCount();
+        }
+
+        void reset() {
+            attributeCount = 0;
+        }
+
+        @Override
+        public int getLength() {
+            return attributeCount;
+        }
+
+        private boolean checkIndex(int index) {
+            return index >= 0 && index < attributeCount;
+        }
+
+        @Override
+        public String getURI(int index) {
+            if (!checkIndex(index))
+                return null;
+            return nullToEmpty(streamReader.getAttributeNamespace(index));
+        }
+
+        @Override
+        public String getLocalName(int index) {
+            if (!checkIndex(index))
+                return null;
+            return streamReader.getAttributeLocalName(index);
+        }
+
+        @Override
+        public String getQName(int index) {
+            if (!checkIndex(index))
+                return null;
+            String localName = streamReader.getAttributeLocalName(index);
+            String prefix = streamReader.getAttributePrefix(index);
+            return getPrefixedName(prefix, localName);
+        }
+
+        @Override
+        public String getType(int index) {
+            if (!checkIndex(index))
+                return null;
+            return streamReader.getAttributeType(index);
+        }
+
+        @Override
+        public String getValue(int index) {
+            if (!checkIndex(index))
+                return null;
+            return nullToEmpty(streamReader.getAttributeType(index));
+        }
+
+        @Override
+        public int getIndex(String searchUri, String searchLocalName) {
+            for (int i = 0; i < attributeCount; i++) {
+                if (getURI(i).equals(searchUri) && getLocalName(i).equals(searchLocalName)) {
+                    return i;
+                }
             }
-            String type = streamReader.getAttributeType(i);
-            String value = streamReader.getAttributeValue(i);
-            if (value == null) {
-                value = "";
+            return -1;
+        }
+
+        @Override
+        public int getIndex(String searchQName) {
+            for (int i = 0; i < attributeCount; i++) {
+                if (getQName(i).equals(searchQName)) {
+                    return i;
+                }
             }
+            return -1;
+        }
+
+        @Override
+        public String getType(String uri, String localName) {
+            return getType(getIndex(uri, localName));
+        }
+
+        @Override
+        public String getType(String qName) {
+            return getType(getIndex(qName));
+        }
+
+        @Override
+        public String getValue(String uri, String localName) {
+            return getValue(getIndex(uri, localName));
+        }
 
-            attrs.addAttribute(uri == null ? "" : uri, localName, qName, type, value);
+        @Override
+        public String getValue(String qName) {
+            return getValue(getIndex(qName));
         }
-        return attrs;
     }
 
     public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {


[3/5] camel git commit: CAMEL-9534: XsltBuilder: always convert StAXSource to SAXSource

Posted by dk...@apache.org.
CAMEL-9534: XsltBuilder: always convert StAXSource to SAXSource

Some older TrAX implementations such as Xalan and Saxon-B do not support
StAXSource.

Using the Woodstox StAX parser with the default TrAX implementation (XSLTC)
doesn't handle CDATA sections correctly (Woodstox reports these as CDATA
events, which are ignored by XSLTC's StAXStream2SAX adapter).

Using StAXSource instead of SAXSource with the default TrAX implementation
(XSLTC) or Saxon results in a significant performance penalty.

Rename Camel's StaxSource adapter to StAX2SAXSource to better reflect what
it does. Use the adapter for all TrAX implementations (not just Xalan).

Signed-off-by: Karsten Blees <ka...@dcon.de>


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/fe0e85a9
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/fe0e85a9
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/fe0e85a9

Branch: refs/heads/master
Commit: fe0e85a92200662f441d71baafc5bfe40108894f
Parents: 7d781cc
Author: Karsten Blees <bl...@dcon.de>
Authored: Thu Jan 28 21:27:54 2016 +0100
Committer: Daniel Kulp <dk...@apache.org>
Committed: Mon Feb 1 16:06:24 2016 -0500

----------------------------------------------------------------------
 .../apache/camel/builder/xml/XsltBuilder.java   |  33 +--
 .../camel/converter/jaxp/StAX2SAXSource.java    | 275 +++++++++++++++++++
 .../apache/camel/converter/jaxp/StaxSource.java | 275 -------------------
 .../builder/xml/XsltTestErrorListenerTest.java  |   2 +-
 .../converter/jaxp/StAX2SAXSourceTest.java      |  63 +++++
 .../camel/converter/jaxp/StaxSourceTest.java    |  63 -----
 6 files changed, 354 insertions(+), 357 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
index 7a5a610..d9d65f4 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
@@ -27,7 +27,6 @@ import java.util.Set;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.XMLStreamReader;
 import javax.xml.transform.ErrorListener;
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
@@ -51,7 +50,7 @@ import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.RuntimeTransformException;
 import org.apache.camel.TypeConverter;
-import org.apache.camel.converter.jaxp.StaxSource;
+import org.apache.camel.converter.jaxp.StAX2SAXSource;
 import org.apache.camel.converter.jaxp.XmlConverter;
 import org.apache.camel.support.ServiceSupport;
 import org.apache.camel.support.SynchronizationAdapter;
@@ -120,7 +119,6 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
 
         ResultHandler resultHandler = resultHandlerFactory.createResult(exchange);
         Result result = resultHandler.getResult();
-        exchange.setProperty("isXalanTransformer", isXalanTransformer(transformer));
         // let's copy the headers before we invoke the transform in case they modify them
         Message out = exchange.getOut();
         out.copyFrom(exchange.getIn());
@@ -137,6 +135,17 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
                 Object body = exchange.getIn().getBody();
                 source = getSource(exchange, body);
             }
+
+            if (source instanceof StAXSource) {
+                // Always convert StAXSource to SAXSource.
+                // * Xalan and Saxon-B don't support StAXSource.
+                // * The JDK default implementation (XSLTC) doesn't handle CDATA events
+                //   (see com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX).
+                // * Saxon-HE/PE/EE seem to support StAXSource, but don't advertise this
+                //   officially (via TransformerFactory.getFeature(StAXSource.FEATURE))
+                source = new StAX2SAXSource(((StAXSource) source).getXMLStreamReader());
+            }
+
             LOG.trace("Using {} as source", source);
             transformer.transform(source, result);
             LOG.trace("Transform complete with result {}", result);
@@ -148,10 +157,6 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
         }
     }
     
-    boolean isXalanTransformer(Transformer transformer) {
-        return transformer.getClass().getName().startsWith("org.apache.xalan.transformer");
-    }
-
     boolean isSaxonTransformer(Transformer transformer) {
         return transformer.getClass().getName().startsWith("net.sf.saxon");
     }
@@ -494,14 +499,13 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
      * <p/>
      * This implementation will prefer to source in the following order:
      * <ul>
-     *   <li>StAX - Is StAX is allowed</li>
+     *   <li>StAX - If StAX is allowed</li>
      *   <li>SAX - SAX as 2nd choice</li>
      *   <li>Stream - Stream as 3rd choice</li>
      *   <li>DOM - DOM as 4th choice</li>
      * </ul>
      */
     protected Source getSource(Exchange exchange, Object body) {
-        Boolean isXalanTransformer = exchange.getProperty("isXalanTransformer", Boolean.class);
         // body may already be a source
         if (body instanceof Source) {
             return (Source) body;
@@ -509,15 +513,8 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
         Source source = null;
         if (body != null) {
             if (isAllowStAX()) {
-                if (isXalanTransformer) {
-                    XMLStreamReader reader = exchange.getContext().getTypeConverter().tryConvertTo(XMLStreamReader.class, exchange, body);
-                    if (reader != null) {
-                        // create a new SAXSource with stax parser API
-                        source = new StaxSource(reader);
-                    }
-                } else {
-                    source = exchange.getContext().getTypeConverter().tryConvertTo(StAXSource.class, exchange, body);
-                }
+                // try StAX if enabled
+                source = exchange.getContext().getTypeConverter().tryConvertTo(StAXSource.class, exchange, body);
             }
             if (source == null) {
                 // then try SAX

http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
new file mode 100644
index 0000000..e4a68b6
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
@@ -0,0 +1,275 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxp;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.sax.SAXSource;
+
+import org.xml.sax.Attributes;
+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;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Adapter to turn a StAX {@link XMLStreamReader} into a {@link SAXSource}.
+ */
+public class StAX2SAXSource extends SAXSource implements XMLReader {
+
+    private XMLStreamReader streamReader;
+
+    private ContentHandler contentHandler;
+
+    private LexicalHandler lexicalHandler;
+
+    public StAX2SAXSource(XMLStreamReader streamReader) {
+        this.streamReader = streamReader;
+        setInputSource(new InputSource());
+    }
+
+    public XMLReader getXMLReader() {
+        return this;
+    }
+
+    public XMLStreamReader getXMLStreamReader() {
+        return streamReader;
+    }
+
+    protected void parse() throws SAXException {
+        try {
+            while (true) {
+                switch (streamReader.getEventType()) {
+                // Attributes are handled in START_ELEMENT
+                case XMLStreamConstants.ATTRIBUTE:
+                    break;
+                case XMLStreamConstants.CDATA:
+                {
+                    if (lexicalHandler != null) {
+                        lexicalHandler.startCDATA();
+                    }
+                    int length = streamReader.getTextLength();
+                    int start = streamReader.getTextStart();
+                    char[] chars = streamReader.getTextCharacters();
+                    contentHandler.characters(chars, start, length);
+                    if (lexicalHandler != null) {
+                        lexicalHandler.endCDATA();
+                    }
+                    break;
+                }
+                case XMLStreamConstants.CHARACTERS:
+                {
+                    int length = streamReader.getTextLength();
+                    int start = streamReader.getTextStart();
+                    char[] chars = streamReader.getTextCharacters();
+                    contentHandler.characters(chars, start, length);
+                    break;
+                }
+                case XMLStreamConstants.SPACE:
+                {
+                    int length = streamReader.getTextLength();
+                    int start = streamReader.getTextStart();
+                    char[] chars = streamReader.getTextCharacters();
+                    contentHandler.ignorableWhitespace(chars, start, length);
+                    break;
+                }
+                case XMLStreamConstants.COMMENT:
+                    if (lexicalHandler != null) {
+                        int length = streamReader.getTextLength();
+                        int start = streamReader.getTextStart();
+                        char[] chars = streamReader.getTextCharacters();
+                        lexicalHandler.comment(chars, start, length);
+                    }
+                    break;
+                case XMLStreamConstants.DTD:
+                    break;
+                case XMLStreamConstants.END_DOCUMENT:
+                    contentHandler.endDocument();
+                    return;
+                case XMLStreamConstants.END_ELEMENT: {
+                    String uri = streamReader.getNamespaceURI();
+                    String localName = streamReader.getLocalName();
+                    String prefix = streamReader.getPrefix();
+                    String qname = prefix != null && prefix.length() > 0
+                        ? prefix + ":" + localName : localName;
+                    contentHandler.endElement(uri, localName, qname);
+                    // namespaces
+                    for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
+                        String nsPrefix = streamReader.getNamespacePrefix(i);
+                        String nsUri = streamReader.getNamespaceURI(i);
+                        if (nsUri == null) {
+                            nsUri = "";
+                        }
+                        contentHandler.endPrefixMapping(nsPrefix);
+                    }
+                    break;
+                }
+                case XMLStreamConstants.ENTITY_DECLARATION:
+                case XMLStreamConstants.ENTITY_REFERENCE:
+                case XMLStreamConstants.NAMESPACE:
+                case XMLStreamConstants.NOTATION_DECLARATION:
+                    break;
+                case XMLStreamConstants.PROCESSING_INSTRUCTION:
+                    break;
+                case XMLStreamConstants.START_DOCUMENT:
+                    contentHandler.startDocument();
+                    break;
+                case XMLStreamConstants.START_ELEMENT: {
+                    String uri = streamReader.getNamespaceURI();
+                    String localName = streamReader.getLocalName();
+                    String prefix = streamReader.getPrefix();
+                    String qname = prefix != null && prefix.length() > 0
+                        ? prefix + ":" + localName : localName;
+                    // namespaces
+                    for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
+                        String nsPrefix = streamReader.getNamespacePrefix(i);
+                        String nsUri = streamReader.getNamespaceURI(i);
+                        if (nsUri == null) {
+                            nsUri = "";
+                        }
+                        contentHandler.startPrefixMapping(nsPrefix, nsUri);
+                    }
+                    contentHandler.startElement(uri == null ? "" : uri, localName, qname, getAttributes());
+                    break;
+                }
+                default:
+                    break;
+                }
+                if (!streamReader.hasNext()) {
+                    return;
+                }
+                streamReader.next();
+            }
+        } catch (XMLStreamException e) {
+            SAXParseException spe;
+            if (e.getLocation() != null) {
+                spe = new SAXParseException(e.getMessage(), null, null,
+                                            e.getLocation().getLineNumber(),
+                                            e.getLocation().getColumnNumber(), e);
+            } else {
+                spe = new SAXParseException(e.getMessage(), null, null, -1, -1, e);
+            }
+            spe.initCause(e);
+            throw spe;
+        }
+    }
+
+    protected String getQualifiedName() {
+        String prefix = streamReader.getPrefix();
+        if (prefix != null && prefix.length() > 0) {
+            return prefix + ":" + streamReader.getLocalName();
+        } else {
+            return streamReader.getLocalName();
+        }
+    }
+
+    protected Attributes getAttributes() {
+        AttributesImpl attrs = new AttributesImpl();
+
+        for (int i = 0; i < streamReader.getAttributeCount(); i++) {
+            String uri = streamReader.getAttributeNamespace(i);
+            String localName = streamReader.getAttributeLocalName(i);
+            String prefix = streamReader.getAttributePrefix(i);
+            String qName;
+            if (prefix != null && prefix.length() > 0) {
+                qName = prefix + ':' + localName;
+            } else {
+                qName = localName;
+            }
+            String type = streamReader.getAttributeType(i);
+            String value = streamReader.getAttributeValue(i);
+            if (value == null) {
+                value = "";
+            }
+
+            attrs.addAttribute(uri == null ? "" : uri, localName, qName, type, value);
+        }
+        return attrs;
+    }
+
+    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return false;
+    }
+
+    public void setFeature(String name, boolean value)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+    }
+
+    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+        return null;
+    }
+
+    public void setProperty(String name, Object value)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+        if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
+            lexicalHandler = (LexicalHandler) value;
+        } else {
+            throw new SAXNotRecognizedException(name);
+        }
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+        this.contentHandler = handler;
+        if (handler instanceof LexicalHandler
+            && lexicalHandler == null) {
+            lexicalHandler = (LexicalHandler)handler;
+        }
+    }
+
+    public ContentHandler getContentHandler() {
+        return this.contentHandler;
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    public void parse(InputSource input) throws SAXException {
+        StAX2SAXSource.this.parse();
+    }
+
+    public void parse(String systemId) throws SAXException {
+        StAX2SAXSource.this.parse();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxSource.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxSource.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxSource.java
deleted file mode 100644
index d8d764a..0000000
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StaxSource.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.converter.jaxp;
-
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.transform.sax.SAXSource;
-
-import org.xml.sax.Attributes;
-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;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * A streaming {@link javax.xml.transform.sax.SAXSource}
- */
-public class StaxSource extends SAXSource implements XMLReader {
-
-    private XMLStreamReader streamReader;
-
-    private ContentHandler contentHandler;
-
-    private LexicalHandler lexicalHandler;
-
-    public StaxSource(XMLStreamReader streamReader) {
-        this.streamReader = streamReader;
-        setInputSource(new InputSource());
-    }
-
-    public XMLReader getXMLReader() {
-        return this;
-    }
-
-    public XMLStreamReader getXMLStreamReader() {
-        return streamReader;
-    }
-
-    protected void parse() throws SAXException {
-        try {
-            while (true) {
-                switch (streamReader.getEventType()) {
-                // Attributes are handled in START_ELEMENT
-                case XMLStreamConstants.ATTRIBUTE:
-                    break;
-                case XMLStreamConstants.CDATA:
-                {
-                    if (lexicalHandler != null) {
-                        lexicalHandler.startCDATA();
-                    }
-                    int length = streamReader.getTextLength();
-                    int start = streamReader.getTextStart();
-                    char[] chars = streamReader.getTextCharacters();
-                    contentHandler.characters(chars, start, length);
-                    if (lexicalHandler != null) {
-                        lexicalHandler.endCDATA();
-                    }
-                    break;
-                }
-                case XMLStreamConstants.CHARACTERS:
-                {
-                    int length = streamReader.getTextLength();
-                    int start = streamReader.getTextStart();
-                    char[] chars = streamReader.getTextCharacters();
-                    contentHandler.characters(chars, start, length);
-                    break;
-                }
-                case XMLStreamConstants.SPACE:
-                {
-                    int length = streamReader.getTextLength();
-                    int start = streamReader.getTextStart();
-                    char[] chars = streamReader.getTextCharacters();
-                    contentHandler.ignorableWhitespace(chars, start, length);
-                    break;
-                }
-                case XMLStreamConstants.COMMENT:
-                    if (lexicalHandler != null) {
-                        int length = streamReader.getTextLength();
-                        int start = streamReader.getTextStart();
-                        char[] chars = streamReader.getTextCharacters();
-                        lexicalHandler.comment(chars, start, length);
-                    }
-                    break;
-                case XMLStreamConstants.DTD:
-                    break;
-                case XMLStreamConstants.END_DOCUMENT:
-                    contentHandler.endDocument();
-                    return;
-                case XMLStreamConstants.END_ELEMENT: {
-                    String uri = streamReader.getNamespaceURI();
-                    String localName = streamReader.getLocalName();
-                    String prefix = streamReader.getPrefix();
-                    String qname = prefix != null && prefix.length() > 0
-                        ? prefix + ":" + localName : localName;
-                    contentHandler.endElement(uri, localName, qname);
-                    // namespaces
-                    for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
-                        String nsPrefix = streamReader.getNamespacePrefix(i);
-                        String nsUri = streamReader.getNamespaceURI(i);
-                        if (nsUri == null) {
-                            nsUri = "";
-                        }
-                        contentHandler.endPrefixMapping(nsPrefix);
-                    }
-                    break;
-                }
-                case XMLStreamConstants.ENTITY_DECLARATION:
-                case XMLStreamConstants.ENTITY_REFERENCE:
-                case XMLStreamConstants.NAMESPACE:
-                case XMLStreamConstants.NOTATION_DECLARATION:
-                    break;
-                case XMLStreamConstants.PROCESSING_INSTRUCTION:
-                    break;
-                case XMLStreamConstants.START_DOCUMENT:
-                    contentHandler.startDocument();
-                    break;
-                case XMLStreamConstants.START_ELEMENT: {
-                    String uri = streamReader.getNamespaceURI();
-                    String localName = streamReader.getLocalName();
-                    String prefix = streamReader.getPrefix();
-                    String qname = prefix != null && prefix.length() > 0
-                        ? prefix + ":" + localName : localName;
-                    // namespaces
-                    for (int i = 0; i < streamReader.getNamespaceCount(); i++) {
-                        String nsPrefix = streamReader.getNamespacePrefix(i);
-                        String nsUri = streamReader.getNamespaceURI(i);
-                        if (nsUri == null) {
-                            nsUri = "";
-                        }
-                        contentHandler.startPrefixMapping(nsPrefix, nsUri);
-                    }
-                    contentHandler.startElement(uri == null ? "" : uri, localName, qname, getAttributes());
-                    break;
-                }
-                default:
-                    break;
-                }
-                if (!streamReader.hasNext()) {
-                    return;
-                }
-                streamReader.next();
-            }
-        } catch (XMLStreamException e) {
-            SAXParseException spe;
-            if (e.getLocation() != null) {
-                spe = new SAXParseException(e.getMessage(), null, null,
-                                            e.getLocation().getLineNumber(),
-                                            e.getLocation().getColumnNumber(), e);
-            } else {
-                spe = new SAXParseException(e.getMessage(), null, null, -1, -1, e);
-            }
-            spe.initCause(e);
-            throw spe;
-        }
-    }
-
-    protected String getQualifiedName() {
-        String prefix = streamReader.getPrefix();
-        if (prefix != null && prefix.length() > 0) {
-            return prefix + ":" + streamReader.getLocalName();
-        } else {
-            return streamReader.getLocalName();
-        }
-    }
-
-    protected Attributes getAttributes() {
-        AttributesImpl attrs = new AttributesImpl();
-
-        for (int i = 0; i < streamReader.getAttributeCount(); i++) {
-            String uri = streamReader.getAttributeNamespace(i);
-            String localName = streamReader.getAttributeLocalName(i);
-            String prefix = streamReader.getAttributePrefix(i);
-            String qName;
-            if (prefix != null && prefix.length() > 0) {
-                qName = prefix + ':' + localName;
-            } else {
-                qName = localName;
-            }
-            String type = streamReader.getAttributeType(i);
-            String value = streamReader.getAttributeValue(i);
-            if (value == null) {
-                value = "";
-            }
-
-            attrs.addAttribute(uri == null ? "" : uri, localName, qName, type, value);
-        }
-        return attrs;
-    }
-
-    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
-        return false;
-    }
-
-    public void setFeature(String name, boolean value)
-        throws SAXNotRecognizedException, SAXNotSupportedException {
-    }
-
-    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
-        return null;
-    }
-
-    public void setProperty(String name, Object value)
-        throws SAXNotRecognizedException, SAXNotSupportedException {
-        if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
-            lexicalHandler = (LexicalHandler) value;
-        } else {
-            throw new SAXNotRecognizedException(name);
-        }
-    }
-
-    public void setEntityResolver(EntityResolver resolver) {
-    }
-
-    public EntityResolver getEntityResolver() {
-        return null;
-    }
-
-    public void setDTDHandler(DTDHandler handler) {
-    }
-
-    public DTDHandler getDTDHandler() {
-        return null;
-    }
-
-    public void setContentHandler(ContentHandler handler) {
-        this.contentHandler = handler;
-        if (handler instanceof LexicalHandler
-            && lexicalHandler == null) {
-            lexicalHandler = (LexicalHandler)handler;
-        }
-    }
-
-    public ContentHandler getContentHandler() {
-        return this.contentHandler;
-    }
-
-    public void setErrorHandler(ErrorHandler handler) {
-    }
-
-    public ErrorHandler getErrorHandler() {
-        return null;
-    }
-
-    public void parse(InputSource input) throws SAXException {
-        StaxSource.this.parse();
-    }
-
-    public void parse(String systemId) throws SAXException {
-        StaxSource.this.parse();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/test/java/org/apache/camel/builder/xml/XsltTestErrorListenerTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/builder/xml/XsltTestErrorListenerTest.java b/camel-core/src/test/java/org/apache/camel/builder/xml/XsltTestErrorListenerTest.java
index dbcce70..2741adc 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/xml/XsltTestErrorListenerTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/xml/XsltTestErrorListenerTest.java
@@ -35,7 +35,7 @@ public class XsltTestErrorListenerTest extends TestCase {
 
     public void testErrorListener() throws Exception {
         // Xalan transformer cannot work as expected, so we just skip the test
-        if (xsltBuilder.isXalanTransformer(xsltBuilder.getConverter().getTransformerFactory().newTransformer())) {
+        if (xsltBuilder.getConverter().getTransformerFactory().getClass().getName().startsWith("org.apache.xalan")) {
             return;
         }
         errorListener.error(EasyMock.<TransformerException>anyObject());

http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/test/java/org/apache/camel/converter/jaxp/StAX2SAXSourceTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/converter/jaxp/StAX2SAXSourceTest.java b/camel-core/src/test/java/org/apache/camel/converter/jaxp/StAX2SAXSourceTest.java
new file mode 100644
index 0000000..c23b46f
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/converter/jaxp/StAX2SAXSourceTest.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultExchange;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class StAX2SAXSourceTest extends ContextTestSupport {
+
+    private static final String TEST_XML = "<root xmlns=\"urn:org.apache.camel:test\">Text</root>";
+
+    private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+    public void testDefaultPrefixInRootElementWithCopyTransformer() throws Exception {
+        TransformerFactory trf = TransformerFactory.newInstance();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        XMLStreamReader reader = context.getTypeConverter().mandatoryConvertTo(XMLStreamReader.class,
+            new StringReader(TEST_XML));
+        // ensure UTF-8 encoding
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setProperty(Exchange.CHARSET_NAME, UTF_8.toString());
+        XMLStreamWriter writer = context.getTypeConverter().mandatoryConvertTo(XMLStreamWriter.class, exchange, baos);
+        StAX2SAXSource staxSource = new StAX2SAXSource(reader);
+        StreamSource templateSource = new StreamSource(getClass().getResourceAsStream("/xslt/common/copy.xsl"));
+        Transformer transformer = trf.newTransformer(templateSource);
+        log.info("Used transformer: {}", transformer.getClass().getName());
+        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        transformer.transform(staxSource, new StreamResult(baos));
+        writer.flush();
+        baos.flush();
+        assertThat(new String(baos.toByteArray()), equalTo(TEST_XML));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/fe0e85a9/camel-core/src/test/java/org/apache/camel/converter/jaxp/StaxSourceTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/converter/jaxp/StaxSourceTest.java b/camel-core/src/test/java/org/apache/camel/converter/jaxp/StaxSourceTest.java
deleted file mode 100644
index 3a9d46c..0000000
--- a/camel-core/src/test/java/org/apache/camel/converter/jaxp/StaxSourceTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.converter.jaxp;
-
-import java.io.ByteArrayOutputStream;
-import java.io.StringReader;
-import java.nio.charset.Charset;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.camel.ContextTestSupport;
-import org.apache.camel.Exchange;
-import org.apache.camel.impl.DefaultExchange;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class StaxSourceTest extends ContextTestSupport {
-
-    private static final String TEST_XML = "<root xmlns=\"urn:org.apache.camel:test\">Text</root>";
-
-    private static final Charset UTF_8 = Charset.forName("UTF-8");
-
-    public void testDefaultPrefixInRootElementWithCopyTransformer() throws Exception {
-        TransformerFactory trf = TransformerFactory.newInstance();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        XMLStreamReader reader = context.getTypeConverter().mandatoryConvertTo(XMLStreamReader.class,
-            new StringReader(TEST_XML));
-        // ensure UTF-8 encoding
-        Exchange exchange = new DefaultExchange(context);
-        exchange.setProperty(Exchange.CHARSET_NAME, UTF_8.toString());
-        XMLStreamWriter writer = context.getTypeConverter().mandatoryConvertTo(XMLStreamWriter.class, exchange, baos);
-        StaxSource staxSource = new StaxSource(reader);
-        StreamSource templateSource = new StreamSource(getClass().getResourceAsStream("/xslt/common/copy.xsl"));
-        Transformer transformer = trf.newTransformer(templateSource);
-        log.info("Used transformer: {}", transformer.getClass().getName());
-        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-        transformer.transform(staxSource, new StreamResult(baos));
-        writer.flush();
-        baos.flush();
-        assertThat(new String(baos.toByteArray()), equalTo(TEST_XML));
-    }
-
-}


[5/5] camel git commit: Fix checkstyle issues with patch

Posted by dk...@apache.org.
Fix checkstyle issues with patch


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/070ed43e
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/070ed43e
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/070ed43e

Branch: refs/heads/master
Commit: 070ed43e1808ab2db381eaddd9abf520b88ce7cf
Parents: 3c8560f
Author: Daniel Kulp <dk...@apache.org>
Authored: Mon Feb 1 15:46:20 2016 -0500
Committer: Daniel Kulp <dk...@apache.org>
Committed: Mon Feb 1 16:06:25 2016 -0500

----------------------------------------------------------------------
 .../apache/camel/converter/jaxp/StAX2SAXSource.java  | 15 ++++++++++-----
 .../apache/camel/converter/jaxp/XMLReaderPool.java   | 14 +++++++++-----
 .../apache/camel/converter/jaxp/XmlConverter.java    |  3 ++-
 3 files changed, 21 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/070ed43e/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
index 957637b..89a17b0 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/StAX2SAXSource.java
@@ -204,22 +204,25 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
 
         @Override
         public String getURI(int index) {
-            if (!checkIndex(index))
+            if (!checkIndex(index)) {
                 return null;
+            }
             return nullToEmpty(streamReader.getAttributeNamespace(index));
         }
 
         @Override
         public String getLocalName(int index) {
-            if (!checkIndex(index))
+            if (!checkIndex(index)) {
                 return null;
+            }
             return streamReader.getAttributeLocalName(index);
         }
 
         @Override
         public String getQName(int index) {
-            if (!checkIndex(index))
+            if (!checkIndex(index)) {
                 return null;
+            }
             String localName = streamReader.getAttributeLocalName(index);
             String prefix = streamReader.getAttributePrefix(index);
             return getPrefixedName(prefix, localName);
@@ -227,15 +230,17 @@ public class StAX2SAXSource extends SAXSource implements XMLReader {
 
         @Override
         public String getType(int index) {
-            if (!checkIndex(index))
+            if (!checkIndex(index)) {
                 return null;
+            }
             return streamReader.getAttributeType(index);
         }
 
         @Override
         public String getValue(int index) {
-            if (!checkIndex(index))
+            if (!checkIndex(index)) {
                 return null;
+            }
             return nullToEmpty(streamReader.getAttributeType(index));
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/070ed43e/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
index ec50920..658268c 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XMLReaderPool.java
@@ -69,8 +69,9 @@ public class XMLReaderPool {
         XMLReader xmlReader = null;
         WeakReference<XMLReader> ref;
         while ((ref = pool.poll()) != null) {
-            if ((xmlReader = ref.get()) != null)
+            if ((xmlReader = ref.get()) != null) {
                 break;
+            }
         }
 
         if (xmlReader == null) {
@@ -83,7 +84,7 @@ public class XMLReaderPool {
     /**
      * Wraps another XMLReader for single use only.
      */
-    private class OneTimeXMLReader implements XMLReader {
+    private final class OneTimeXMLReader implements XMLReader {
         private XMLReader xmlReader;
         private final Map<String, Boolean> initFeatures = new HashMap<String, Boolean>();
         private final Map<String, Object> initProperties = new HashMap<String, Object>();
@@ -127,8 +128,9 @@ public class XMLReaderPool {
         }
 
         private void checkValid() {
-            if (xmlReader == null)
+            if (xmlReader == null) {
                 throw new IllegalStateException("OneTimeXMLReader.parse() can only be used once!");
+            }
         }
 
         @Override
@@ -142,8 +144,9 @@ public class XMLReaderPool {
         public void setFeature(String name, boolean value)
                 throws SAXNotRecognizedException, SAXNotSupportedException {
             checkValid();
-            if (!initFeatures.containsKey(name))
+            if (!initFeatures.containsKey(name)) {
                 initFeatures.put(name, Boolean.valueOf(xmlReader.getFeature(name)));
+            }
             xmlReader.setFeature(name, value);
         }
 
@@ -158,8 +161,9 @@ public class XMLReaderPool {
         public void setProperty(String name, Object value)
                 throws SAXNotRecognizedException, SAXNotSupportedException {
             checkValid();
-            if (!initProperties.containsKey(name))
+            if (!initProperties.containsKey(name)) {
                 initProperties.put(name, xmlReader.getProperty(name));
+            }
             xmlReader.setProperty(name, value);
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/070ed43e/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
index 649d327..c3c2aae 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
@@ -1048,8 +1048,9 @@ public class XmlConverter {
     }
 
     public void setTransformerFactory(TransformerFactory transformerFactory) {
-        if (transformerFactory != null)
+        if (transformerFactory != null) {
             configureSaxonTransformerFactory(transformerFactory);
+        }
         this.transformerFactory = transformerFactory;
     }
 


[4/5] camel git commit: CAMEL-9534: XsltComponent: fix support for Saxon-B and Saxon >= 9.6

Posted by dk...@apache.org.
CAMEL-9534: XsltComponent: fix support for Saxon-B and Saxon >= 9.6

Using reflection and Saxon-specific APIs to configure Saxon's MessageWarner
class is flaky - the current implementation introduced with CAMEL-7753 only
works for Saxon-HE 9.3 - 9.5. Using XsltComponent with other Saxon versions
fails with IllegalStateException "Error pre-loading Saxon classes...".

Use TransformerFactory.setAttribute(FeatureKeys.MESSAGE_EMITTER_CLASS) to
install the MessageWarner class. Only log a warning on failure.

Make lazy-initialized factory variables volatile so that they only become
visible to other threads after the factory is fully initialized.

Note: The MessageWarner class in Saxon 9.6+ redirects <xsl:message> output
to the ErrorListener of the TransformerFactory rather than the Transformer
instance (see https://saxonica.plan.io/issues/2581). This cannot be easily
fixed on the Camel side, as setting a Transformer-specific ErrorListener on
the TransformerFactory would break multithreaded routes.

Signed-off-by: Karsten Blees <ka...@dcon.de>


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/3ac8d9fd
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/3ac8d9fd
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/3ac8d9fd

Branch: refs/heads/master
Commit: 3ac8d9fd74ec00fa5a969eb790e1df496073d92b
Parents: fe0e85a
Author: Karsten Blees <bl...@dcon.de>
Authored: Mon Jan 25 22:27:16 2016 +0100
Committer: Daniel Kulp <dk...@apache.org>
Committed: Mon Feb 1 16:06:24 2016 -0500

----------------------------------------------------------------------
 .../apache/camel/builder/xml/XsltBuilder.java   | 62 +-------------------
 .../camel/component/xslt/XsltEndpoint.java      |  5 --
 .../camel/converter/jaxp/XmlConverter.java      | 46 ++++++++++++++-
 .../util/toolbox/XsltAggregationStrategy.java   |  1 -
 .../camel/builder/xml/XsltBuilderTest.java      | 38 ------------
 5 files changed, 47 insertions(+), 105 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/3ac8d9fd/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
index d9d65f4..d5e73da 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java
@@ -19,13 +19,13 @@ package org.apache.camel.builder.xml;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
+
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.ErrorListener;
 import javax.xml.transform.Result;
@@ -42,8 +42,6 @@ import javax.xml.transform.stream.StreamSource;
 
 import org.w3c.dom.Node;
 
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExpectedBodyTypeException;
 import org.apache.camel.Message;
@@ -52,12 +50,10 @@ import org.apache.camel.RuntimeTransformException;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.converter.jaxp.StAX2SAXSource;
 import org.apache.camel.converter.jaxp.XmlConverter;
-import org.apache.camel.support.ServiceSupport;
 import org.apache.camel.support.SynchronizationAdapter;
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
-import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -76,9 +72,8 @@ import static org.apache.camel.util.ObjectHelper.notNull;
  *
  * @version 
  */
-public class XsltBuilder extends ServiceSupport implements Processor, CamelContextAware {
+public class XsltBuilder implements Processor {
     private static final Logger LOG = LoggerFactory.getLogger(XsltBuilder.class);
-    private CamelContext camelContext;
     private Map<String, Object> parameters = new HashMap<String, Object>();
     private XmlConverter converter = new XmlConverter();
     private Templates template;
@@ -89,9 +84,6 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
     private boolean deleteOutputFile;
     private ErrorListener errorListener;
     private boolean allowStAX = true;
-    private volatile Method setMessageEmitterMethod;
-    private volatile Class<?> saxonReceiverClass;
-    private volatile Class<?> saxonWarnerClass;
 
     public XsltBuilder() {
     }
@@ -157,10 +149,6 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
         }
     }
     
-    boolean isSaxonTransformer(Transformer transformer) {
-        return transformer.getClass().getName().startsWith("net.sf.saxon");
-    }
-
     // Builder methods
     // -------------------------------------------------------------------------
 
@@ -448,17 +436,7 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
     }
 
     protected Transformer createTransformer() throws Exception {
-        Transformer t = getTemplate().newTransformer();
-
-        // special for saxon as we need to call setMessageEmitter on the transformer to hook from saxon to the JAXP errorListener
-        // so we can get notified if any errors happen during transformation
-        // see details at: https://stackoverflow.com/questions/4695489/capture-xslmessage-output-in-java
-        if (isSaxonTransformer(t) && setMessageEmitterMethod != null) {
-            Object warner = getCamelContext().getInjector().newInstance(saxonWarnerClass);
-            setMessageEmitterMethod.invoke(t, warner);
-        }
-
-        return t;
+        return getTemplate().newTransformer();
     }
 
     /**
@@ -589,40 +567,6 @@ public class XsltBuilder extends ServiceSupport implements Processor, CamelConte
         }
     }
 
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        ObjectHelper.notNull(camelContext, "camelContext", this);
-
-        // create a transformer to see if its saxon, as we then need to do some initial preparation
-        Transformer t = getTemplate().newTransformer();
-
-        if (isSaxonTransformer(t)) {
-            // pre-load saxon classes as we need to call the setMessageEmitter on the transformer to hook saxon to use the JAXP
-            // error listener, so we can capture errors and xsl:message outputs which end users may define in the xslt files
-            try {
-                saxonReceiverClass = getCamelContext().getClassResolver().resolveMandatoryClass("net.sf.saxon.event.Receiver");
-                saxonWarnerClass = getCamelContext().getClassResolver().resolveMandatoryClass("net.sf.saxon.serialize.MessageWarner");
-                setMessageEmitterMethod = t.getClass().getMethod("setMessageEmitter", saxonReceiverClass);
-            } catch (Exception e) {
-                throw new IllegalStateException("Error pre-loading Saxon classes. Make sure you have saxon on the classpath,"
-                        + " and the classloader can load the following two classes: net.sf.saxon.event.Receiver, net.sf.saxon.serialize.MessageWarner.", e);
-            }
-        }
-    }
-
-    @Override
-    protected void doStop() throws Exception {
-        // noop
-    }
-
     private static final class XsltBuilderOnCompletion extends SynchronizationAdapter {
         private final String fileName;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/3ac8d9fd/camel-core/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
index fc0bad6..4588b5c 100644
--- a/camel-core/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
+++ b/camel-core/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
@@ -390,13 +390,8 @@ public class XsltEndpoint extends ProcessorEndpoint {
         // must load resource first which sets a template and do a stylesheet compilation to catch errors early
         loadResource(resourceUri);
 
-        // and then inject camel context and start service
-        xslt.setCamelContext(getCamelContext());
-
         // the processor is the xslt builder
         setProcessor(xslt);
-
-        ServiceHelper.startService(xslt);
     }
 
     protected void configureOutput(XsltBuilder xslt, String output) throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/3ac8d9fd/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
index 3079e7c..d29f643 100644
--- a/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
+++ b/camel-core/src/main/java/org/apache/camel/converter/jaxp/XmlConverter.java
@@ -89,8 +89,8 @@ public class XmlConverter {
 
     private static final Logger LOG = LoggerFactory.getLogger(XmlConverter.class);
 
-    private DocumentBuilderFactory documentBuilderFactory;
-    private TransformerFactory transformerFactory;
+    private volatile DocumentBuilderFactory documentBuilderFactory;
+    private volatile TransformerFactory transformerFactory;
 
     public XmlConverter() {
     }
@@ -1054,6 +1054,8 @@ public class XmlConverter {
     }
 
     public void setTransformerFactory(TransformerFactory transformerFactory) {
+        if (transformerFactory != null)
+            configureSaxonTransformerFactory(transformerFactory);
         this.transformerFactory = transformerFactory;
     }
 
@@ -1163,7 +1165,47 @@ public class XmlConverter {
             LOG.warn("TransformerFactory doesn't support the feature {} with value {}, due to {}.", new Object[]{javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, "true", e});
         }
         factory.setErrorListener(new XmlErrorListener());
+        configureSaxonTransformerFactory(factory);
         return factory;
     }
 
+    /**
+     * Make a Saxon TransformerFactory more JAXP compliant by configuring it to
+     * send &lt;xsl:message&gt; output to the ErrorListener.
+     *
+     * @param factory
+     *            the TransformerFactory
+     */
+    public void configureSaxonTransformerFactory(TransformerFactory factory) {
+        // check whether we have a Saxon TransformerFactory ("net.sf.saxon" for open source editions (HE / B)
+        // and "com.saxonica" for commercial editions (PE / EE / SA))
+        Class<?> factoryClass = factory.getClass();
+        if (factoryClass.getName().startsWith("net.sf.saxon")
+                || factoryClass.getName().startsWith("com.saxonica")) {
+
+            // just in case there are multiple class loaders with different Saxon versions, use the
+            // TransformerFactory's class loader to find Saxon support classes
+            ClassLoader loader = factoryClass.getClassLoader();
+
+            // try to find Saxon's MessageWarner class that redirects <xsl:message> to the ErrorListener
+            Class<?> messageWarner = null;
+            try {
+                // Saxon >= 9.3
+                messageWarner = loader.loadClass("net.sf.saxon.serialize.MessageWarner");
+            } catch (ClassNotFoundException cnfe) {
+                try {
+                    // Saxon < 9.3 (including Saxon-B / -SA)
+                    messageWarner = loader.loadClass("net.sf.saxon.event.MessageWarner");
+                } catch (ClassNotFoundException cnfe2) {
+                    LOG.warn("Error loading Saxon's net.sf.saxon.serialize.MessageWarner class from the classpath!"
+                            + " <xsl:message> output will not be redirected to the ErrorListener!");
+                }
+            }
+
+            if (messageWarner != null) {
+                // set net.sf.saxon.FeatureKeys.MESSAGE_EMITTER_CLASS
+                factory.setAttribute("http://saxon.sf.net/feature/messageEmitterClass", messageWarner.getName());
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/3ac8d9fd/camel-core/src/main/java/org/apache/camel/util/toolbox/XsltAggregationStrategy.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/toolbox/XsltAggregationStrategy.java b/camel-core/src/main/java/org/apache/camel/util/toolbox/XsltAggregationStrategy.java
index fbadfae..31b4f7a 100644
--- a/camel-core/src/main/java/org/apache/camel/util/toolbox/XsltAggregationStrategy.java
+++ b/camel-core/src/main/java/org/apache/camel/util/toolbox/XsltAggregationStrategy.java
@@ -161,7 +161,6 @@ public class XsltAggregationStrategy implements AggregationStrategy {
         xslt.setFailOnNullBody(true);
         xslt.transformerCacheSize(0);
         xslt.setAllowStAX(true);
-        xslt.setCamelContext(context);
 
         configureOutput(xslt, output.name());
         loadResource(xslFile);

http://git-wip-us.apache.org/repos/asf/camel/blob/3ac8d9fd/camel-core/src/test/java/org/apache/camel/builder/xml/XsltBuilderTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/builder/xml/XsltBuilderTest.java b/camel-core/src/test/java/org/apache/camel/builder/xml/XsltBuilderTest.java
index 04468c7..aa02a90 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/xml/XsltBuilderTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/xml/XsltBuilderTest.java
@@ -51,8 +51,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -67,8 +65,6 @@ public class XsltBuilderTest extends ContextTestSupport {
 
         XsltBuilder builder = new XsltBuilder();
         builder.setTransformerURL(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -82,8 +78,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         File styleSheet = new File("src/test/resources/org/apache/camel/builder/xml/example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -98,8 +92,6 @@ public class XsltBuilderTest extends ContextTestSupport {
 
         XsltBuilder builder = new XsltBuilder();
         builder.setTransformerFile(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -113,8 +105,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         File styleSheet = new File("src/test/resources/org/apache/camel/builder/xml/example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(new FileInputStream(styleSheet));
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -129,8 +119,6 @@ public class XsltBuilderTest extends ContextTestSupport {
 
         XsltBuilder builder = new XsltBuilder();
         builder.setTransformerInputStream(new FileInputStream(styleSheet));
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -145,8 +133,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         Source styleSheet = new SAXSource(new InputSource(new FileInputStream(file)));
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -164,8 +150,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         Templates styleSheet = converter.getTransformerFactory().newTemplates(source);
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -179,8 +163,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet).outputString();
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -195,8 +177,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet).outputBytes();
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -211,8 +191,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet).outputDOM();
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -227,8 +205,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet).outputFile();
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -248,8 +224,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet).outputFile().deleteOutputFile();
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
@@ -280,9 +254,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         builder.setConverter(converter);
         assertSame(converter, builder.getConverter());
 
-        builder.setCamelContext(context);
-        builder.start();
-
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
 
@@ -299,9 +270,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         builder.outputBytes();
         assertIsInstanceOf(StreamResultHandlerFactory.class, builder.getResultHandlerFactory());
 
-        builder.setCamelContext(context);
-        builder.start();
-
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody("<hello>world!</hello>");
 
@@ -314,8 +282,6 @@ public class XsltBuilderTest extends ContextTestSupport {
         URL styleSheet = getClass().getResource("example.xsl");
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody(null);
@@ -333,8 +299,6 @@ public class XsltBuilderTest extends ContextTestSupport {
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
         builder.setFailOnNullBody(true);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody(null);
@@ -352,8 +316,6 @@ public class XsltBuilderTest extends ContextTestSupport {
 
         XsltBuilder builder = XsltBuilder.xslt(styleSheet);
         builder.setFailOnNullBody(false);
-        builder.setCamelContext(context);
-        builder.start();
 
         Exchange exchange = new DefaultExchange(context);
         exchange.getIn().setBody(null);