camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acosent...@apache.org
Subject [camel] 02/09: CAMEL-13851: Refactoring to reuse as much code as possible from the xslt component
Date Fri, 06 Sep 2019 07:52:48 GMT
This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 1565c94164230e8a95b1c266d147c552cf797a41
Author: Marc Giger <giger@apache.org>
AuthorDate: Wed Aug 21 18:15:39 2019 +0200

    CAMEL-13851: Refactoring to reuse as much code as possible from the xslt component
---
 .../camel/component/xj/JsonFileResultHandler.java  |  22 +-
 .../component/xj/JsonFileResultHandlerFactory.java |  14 +-
 .../component/xj/JsonSourceHandlerFactoryImpl.java |  33 +-
 .../component/xj/JsonStreamResultHandler.java      |  22 +-
 .../xj/JsonStreamResultHandlerFactory.java         |  10 +
 .../component/xj/JsonStringResultHandler.java      |  22 +-
 .../xj/JsonStringResultHandlerFactory.java         |  11 +
 .../camel/component/xj/JsonXmlStreamReader.java    |  15 +-
 .../camel/component/xj/TransformDirection.java     |   3 +
 .../org/apache/camel/component/xj/XJComponent.java | 178 +-------
 .../org/apache/camel/component/xj/XJConstants.java |  33 +-
 .../org/apache/camel/component/xj/XJEndpoint.java  | 496 ++-------------------
 .../camel/component/xj/XmlJsonStreamWriter.java    |  18 +-
 .../org/apache/camel/component/xj/XsltBuilder.java | 482 --------------------
 .../org/apache/camel/component/xj/XsltHelper.java  | 104 -----
 .../component/xslt}/SourceHandlerFactory.java      |  15 +-
 .../xslt}/XmlSourceHandlerFactoryImpl.java         |  62 ++-
 .../apache/camel/component/xslt/XsltBuilder.java   | 137 ++----
 .../apache/camel/component/xslt/XsltComponent.java |  19 +-
 .../apache/camel/component/xslt/XsltEndpoint.java  |  19 +-
 .../endpoint/dsl/XJEndpointBuilderFactory.java     |  96 ++--
 21 files changed, 391 insertions(+), 1420 deletions(-)

diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandler.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandler.java
index 5d6f2c1..538976f 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandler.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandler.java
@@ -16,32 +16,46 @@
  */
 package org.apache.camel.component.xj;
 
+import java.io.File;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.stax.StAXResult;
+
 import com.fasterxml.jackson.core.JsonEncoding;
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonGenerator;
 import org.apache.camel.Message;
 import org.apache.camel.component.xslt.ResultHandler;
 
-import javax.xml.transform.Result;
-import javax.xml.transform.stax.StAXResult;
-import java.io.File;
-
+/**
+ * Result handler impl. to write a json document into a {@link File}
+ */
 public class JsonFileResultHandler implements ResultHandler {
 
     private final File file;
     private final Result result;
 
+    /**
+     * Creates a new json to file result handler instance
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonFileResultHandler(JsonFactory jsonFactory, File file) throws Exception {
         this.file = file;
         final JsonGenerator jsonGenerator = jsonFactory.createGenerator(this.file, JsonEncoding.UTF8);
         this.result = new StAXResult(new XmlJsonStreamWriter(jsonGenerator));
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Result getResult() {
         return this.result;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void setBody(Message in) {
         in.setBody(this.file);
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandlerFactory.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandlerFactory.java
index 0b065ac..d56a320 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandlerFactory.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonFileResultHandlerFactory.java
@@ -16,21 +16,31 @@
  */
 package org.apache.camel.component.xj;
 
+import java.io.File;
+
 import com.fasterxml.jackson.core.JsonFactory;
 import org.apache.camel.Exchange;
 import org.apache.camel.component.xslt.ResultHandler;
 import org.apache.camel.component.xslt.ResultHandlerFactory;
 import org.apache.camel.support.ExchangeHelper;
 
-import java.io.File;
-
+/**
+ * {@JsonFileResultHandler} factory
+ */
 public class JsonFileResultHandlerFactory implements ResultHandlerFactory {
     private final JsonFactory jsonFactory;
 
+    /**
+     * Creates a new json to file result handler factory
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonFileResultHandlerFactory(JsonFactory jsonFactory) {
         this.jsonFactory = jsonFactory;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ResultHandler createResult(Exchange exchange) throws Exception {
         final String fileName = ExchangeHelper.getMandatoryHeader(exchange, Exchange.XSLT_FILE_NAME, String.class);
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonSourceHandlerFactoryImpl.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonSourceHandlerFactoryImpl.java
index 5959c86..9ba17a8 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonSourceHandlerFactoryImpl.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonSourceHandlerFactoryImpl.java
@@ -16,35 +16,54 @@
  */
 package org.apache.camel.component.xj;
 
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonParser;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExpectedBodyTypeException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
 
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.transform.Source;
 import javax.xml.transform.stax.StAXSource;
-import java.io.File;
-import java.io.InputStream;
-import java.io.Reader;
 
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExpectedBodyTypeException;
+import org.apache.camel.component.xslt.SourceHandlerFactory;
+
+/**
+ * Handler for json sources
+ */
 public class JsonSourceHandlerFactoryImpl implements SourceHandlerFactory {
 
     private JsonFactory jsonFactory;
     private boolean isFailOnNullBody = true;
 
+    /**
+     * Creates a new instance
+     * @param jsonFactory the jsonFactory to use to read the json document
+     */
     public JsonSourceHandlerFactoryImpl(JsonFactory jsonFactory) {
         this.jsonFactory = jsonFactory;
     }
 
+    /**
+     * Returns if we fail when the body is null
+     */
     public boolean isFailOnNullBody() {
         return isFailOnNullBody;
     }
 
+    /**
+     * Set if we should fail when the body is null
+     * @param failOnNullBody
+     */
     public void setFailOnNullBody(boolean failOnNullBody) {
         isFailOnNullBody = failOnNullBody;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Source getSource(Exchange exchange) throws Exception {
         Object body = exchange.getIn().getBody();
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandler.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandler.java
index 809e710..4bf71f1 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandler.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandler.java
@@ -16,32 +16,46 @@
  */
 package org.apache.camel.component.xj;
 
+import java.io.ByteArrayOutputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.stax.StAXResult;
+
 import com.fasterxml.jackson.core.JsonEncoding;
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonGenerator;
 import org.apache.camel.Message;
 import org.apache.camel.component.xslt.ResultHandler;
 
-import javax.xml.transform.Result;
-import javax.xml.transform.stax.StAXResult;
-import java.io.ByteArrayOutputStream;
-
+/**
+ * Result handler impl. to write a json document into a {@ByteArrayOutputStream}
+ */
 public class JsonStreamResultHandler implements ResultHandler {
 
     private final ByteArrayOutputStream byteArrayOutputStream;
     private final Result result;
 
+    /**
+     * Creates a new json to stream result handler instance
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonStreamResultHandler(JsonFactory jsonFactory) throws Exception {
         this.byteArrayOutputStream = new ByteArrayOutputStream();
         final JsonGenerator jsonGenerator = jsonFactory.createGenerator(this.byteArrayOutputStream, JsonEncoding.UTF8);
         this.result = new StAXResult(new XmlJsonStreamWriter(jsonGenerator));
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Result getResult() {
         return this.result;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void setBody(Message in) {
         in.setBody(this.byteArrayOutputStream.toByteArray());
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandlerFactory.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandlerFactory.java
index f639086..f9034fe 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandlerFactory.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStreamResultHandlerFactory.java
@@ -21,13 +21,23 @@ import org.apache.camel.Exchange;
 import org.apache.camel.component.xslt.ResultHandler;
 import org.apache.camel.component.xslt.ResultHandlerFactory;
 
+/**
+ * {@JsonStreamResultHandler} factory
+ */
 public class JsonStreamResultHandlerFactory implements ResultHandlerFactory {
     private final JsonFactory jsonFactory;
 
+    /**
+     * Creates a new json to stream result handler factory
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonStreamResultHandlerFactory(JsonFactory jsonFactory) {
         this.jsonFactory = jsonFactory;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ResultHandler createResult(Exchange exchange) throws Exception {
         return new JsonStreamResultHandler(jsonFactory);
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandler.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandler.java
index 61e12ea..7abf4e0 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandler.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandler.java
@@ -16,31 +16,45 @@
  */
 package org.apache.camel.component.xj;
 
+import java.io.StringWriter;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.stax.StAXResult;
+
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonGenerator;
 import org.apache.camel.Message;
 import org.apache.camel.component.xslt.ResultHandler;
 
-import javax.xml.transform.Result;
-import javax.xml.transform.stax.StAXResult;
-import java.io.StringWriter;
-
+/**
+ * Result handler impl. to write a json document into a {@link String}
+ */
 public class JsonStringResultHandler implements ResultHandler {
 
     private final StringWriter stringWriter;
     private final Result result;
 
+    /**
+     * Creates a new json to string result handler instance
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonStringResultHandler(JsonFactory jsonFactory) throws Exception {
         this.stringWriter = new StringWriter();
         final JsonGenerator jsonGenerator = jsonFactory.createGenerator(this.stringWriter);
         this.result = new StAXResult(new XmlJsonStreamWriter(jsonGenerator));
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Result getResult() {
         return this.result;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void setBody(Message in) {
         in.setBody(this.stringWriter.toString());
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandlerFactory.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandlerFactory.java
index e2991fc..c534c68 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandlerFactory.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonStringResultHandlerFactory.java
@@ -21,13 +21,24 @@ import org.apache.camel.Exchange;
 import org.apache.camel.component.xslt.ResultHandler;
 import org.apache.camel.component.xslt.ResultHandlerFactory;
 
+/**
+ * {@JsonStringResultHandler} factory
+ */
 public class JsonStringResultHandlerFactory implements ResultHandlerFactory {
+
     private final JsonFactory jsonFactory;
 
+    /**
+     * Creates a new json to string result handler factory
+     * @param jsonFactory the {@link JsonFactory} to use to write the json.
+     */
     public JsonStringResultHandlerFactory(JsonFactory jsonFactory) {
         this.jsonFactory = jsonFactory;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ResultHandler createResult(Exchange exchange) throws Exception {
         return new JsonStringResultHandler(jsonFactory);
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonXmlStreamReader.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonXmlStreamReader.java
index 06106b5..b1d9e1a 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonXmlStreamReader.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/JsonXmlStreamReader.java
@@ -17,8 +17,13 @@
 
 package org.apache.camel.component.xj;
 
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
@@ -26,9 +31,9 @@ import javax.xml.stream.Location;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.events.XMLEvent;
-import java.io.IOException;
-import java.util.*;
-import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
 
 /**
  * XML Json bridge. Explicitly using XMLStreamReader and not XMLEventReader because saxon wants that.
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/TransformDirection.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/TransformDirection.java
index 73b0f2f..0cbf898 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/TransformDirection.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/TransformDirection.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.component.xj;
 
+/**
+ * Enum with the possible transform directions.
+ */
 public enum TransformDirection {
     XML2JSON,
     JSON2XML
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJComponent.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJComponent.java
index 030d560..18bd9d7 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJComponent.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJComponent.java
@@ -16,188 +16,20 @@
  */
 package org.apache.camel.component.xj;
 
-import org.apache.camel.Endpoint;
-import org.apache.camel.component.xslt.DefaultXsltUriResolverFactory;
-import org.apache.camel.component.xslt.XsltUriResolverFactory;
-import org.apache.camel.spi.Metadata;
+import org.apache.camel.component.xslt.XsltComponent;
+import org.apache.camel.component.xslt.XsltEndpoint;
 import org.apache.camel.spi.annotations.Component;
-import org.apache.camel.support.DefaultComponent;
-import org.apache.camel.support.EndpointHelper;
-import org.apache.camel.support.ResourceHelper;
-
-import javax.xml.transform.URIResolver;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-// todo?: This class is just a copy of XsltComponent because of minor but important different requirements. Refactoring of XsltComponent so that we can extend it?
 
 /**
  * The <a href="http://camel.apache.org/xj.html">XJ Component</a> is for performing xml to json and back transformations of messages
  */
 @Component("xj")
-public class XJComponent extends DefaultComponent {
-
-    @Metadata(label = "advanced")
-    private URIResolver uriResolver;
-    @Metadata(label = "advanced")
-    private XsltUriResolverFactory uriResolverFactory;
-    @Metadata(label = "advanced")
-    private Object saxonConfiguration;
-    @Metadata(label = "advanced")
-    private Map<String, Object> saxonConfigurationProperties = new HashMap<>();
-    @Metadata(label = "advanced", javaType = "java.lang.String")
-    private List<Object> saxonExtensionFunctions;
-    @Metadata(defaultValue = "true")
-    private boolean contentCache = true;
-    @Metadata
-    private boolean saxon;
+public class XJComponent extends XsltComponent {
 
     public XJComponent() {
     }
 
-    public XsltUriResolverFactory getUriResolverFactory() {
-        return uriResolverFactory;
-    }
-
-    /**
-     * To use a custom UriResolver which depends on a dynamic endpoint resource URI. Should not be used together with the option 'uriResolver'.
-     */
-    public void setUriResolverFactory(XsltUriResolverFactory uriResolverFactory) {
-        this.uriResolverFactory = uriResolverFactory;
-    }
-
-    public URIResolver getUriResolver() {
-        return uriResolver;
-    }
-
-    /**
-     * To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'.
-     */
-    public void setUriResolver(URIResolver uriResolver) {
-        this.uriResolver = uriResolver;
-    }
-
-    public boolean isContentCache() {
-        return contentCache;
-    }
-
-    /**
-     * Cache for the resource content (the stylesheet file) when it is loaded.
-     * If set to false Camel will reload the stylesheet file on each message processing. This is good for development.
-     * A cached stylesheet can be forced to reload at runtime via JMX using the clearCachedStylesheet operation.
-     */
-    public void setContentCache(boolean contentCache) {
-        this.contentCache = contentCache;
-    }
-
-    public boolean isSaxon() {
-        return saxon;
-    }
-
-    /**
-     * Whether to use Saxon as the transformerFactoryClass.
-     * If enabled then the class net.sf.saxon.TransformerFactoryImpl. You would need to add Saxon to the classpath.
-     */
-    public void setSaxon(boolean saxon) {
-        this.saxon = saxon;
-    }
-
-    public List<Object> getSaxonExtensionFunctions() {
-        return saxonExtensionFunctions;
-    }
-
-    /**
-     * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition.
-     * You would need to add camel-saxon to the classpath.
-     * The function is looked up in the registry, where you can comma to separate multiple values to lookup.
-     */
-    public void setSaxonExtensionFunctions(List<Object> extensionFunctions) {
-        this.saxonExtensionFunctions = extensionFunctions;
-    }
-
-    /**
-     * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition.
-     * You would need to add camel-saxon to the classpath.
-     * The function is looked up in the registry, where you can comma to separate multiple values to lookup.
-     */
-    public void setSaxonExtensionFunctions(String extensionFunctions) {
-        this.saxonExtensionFunctions = EndpointHelper.resolveReferenceListParameter(
-                getCamelContext(),
-                extensionFunctions,
-                Object.class
-        );
-    }
-
-    public Object getSaxonConfiguration() {
-        return saxonConfiguration;
-    }
-
-    /**
-     * To use a custom Saxon configuration
-     */
-    public void setSaxonConfiguration(Object saxonConfiguration) {
-        this.saxonConfiguration = saxonConfiguration;
-    }
-
-    public Map<String, Object> getSaxonConfigurationProperties() {
-        return saxonConfigurationProperties;
-    }
-
-    /**
-     * To set custom Saxon configuration properties
-     */
-    public void setSaxonConfigurationProperties(Map<String, Object> configurationProperties) {
-        this.saxonConfigurationProperties = configurationProperties;
-    }
-
-    @Override
-    protected Endpoint createEndpoint(String uri, final String remaining, Map<String, Object> parameters) throws Exception {
-        XJEndpoint endpoint = new XJEndpoint(uri, this);
-        endpoint.setContentCache(isContentCache());
-        endpoint.setSaxon(isSaxon());
-        endpoint.setSaxonConfiguration(saxonConfiguration);
-        endpoint.setSaxonConfigurationProperties(saxonConfigurationProperties);
-        endpoint.setSaxonExtensionFunctions(saxonExtensionFunctions);
-
-        // lookup custom resolver to use
-        URIResolver resolver = resolveAndRemoveReferenceParameter(parameters, "uriResolver", URIResolver.class);
-        if (resolver == null) {
-            // not in endpoint then use component specific resolver
-            resolver = getUriResolver();
-        }
-        if (resolver == null) {
-            // lookup custom resolver factory to use
-            XsltUriResolverFactory resolverFactory = resolveAndRemoveReferenceParameter(parameters, "uriResolverFactory", XsltUriResolverFactory.class);
-            if (resolverFactory == null) {
-                // not in endpoint then use component specific resolver factory
-                resolverFactory = getUriResolverFactory();
-            }
-            if (resolverFactory == null) {
-                // fallback to use the Default URI resolver factory
-                resolverFactory = new DefaultXsltUriResolverFactory();
-            }
-
-            resolver = resolverFactory.createUriResolver(getCamelContext(), remaining);
-        }
-        endpoint.setUriResolver(resolver);
-
-        setProperties(endpoint, parameters);
-
-        String resourceUri = remaining;
-        if (ResourceHelper.isHttpUri(resourceUri)) {
-            // if its a http uri, then append additional parameters as they are part of the uri
-            resourceUri = ResourceHelper.appendParameters(resourceUri, parameters);
-        }
-        log.debug("{} using schema resource: {}", this, resourceUri);
-        endpoint.setResourceUri(resourceUri);
-
-        if (!parameters.isEmpty()) {
-            // additional parameters need to be stored on endpoint as they can be used to configure xslt builder additionally
-            endpoint.setParameters(parameters);
-        }
-
-        return endpoint;
+    protected XsltEndpoint createXsltEndpoint(String uri) {
+        return new XJEndpoint(uri, this);
     }
-
 }
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJConstants.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJConstants.java
index 932a335..82ee635 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJConstants.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJConstants.java
@@ -17,24 +17,47 @@
 
 package org.apache.camel.component.xj;
 
-import com.fasterxml.jackson.core.JsonToken;
-
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.fasterxml.jackson.core.JsonToken;
+
 public class XJConstants {
 
+    /**
+     * The namespace used by xj for typehints
+     */
     public static final String NS_XJ = "http://camel.apache.org/component/xj";
+
+    /**
+     * The namespace prefix used by xj for typehints
+     */
     public static final String NS_PREFIX_XJ = "xj";
 
+    /**
+     * Name typehint. Used to instruct xj to write a field with that name when converting to json. On the otherhand
+     * when converting to xml xj writes the json field name in that attribute.
+     */
     public static final String TYPE_HINT_NAME = "name";
+
+    /**
+     * JSON-Type hint. Used to instruct xj of which type the output is when converting to json. Otherwise when converting
+     * to xml the attribute holds the type that was in the original json document.
+     */
     public static final String TYPE_HINT_TYPE = "type";
 
-    public static final Map<JsonToken, String> JSONTYPE_TYPE_MAP;
-    public static final Map<String, JsonToken> TYPE_JSONTYPE_MAP;
+    /**
+     * Mapping from json-types to typehint names
+     */
+    static final Map<JsonToken, String> JSONTYPE_TYPE_MAP;
+
+    /**
+     * Mapping from typehint names to json-types
+     */
+    static final Map<String, JsonToken> TYPE_JSONTYPE_MAP;
 
-    public static final String UNSUPPORTED_OPERATION_EXCEPTION_MESSAGE = "unsupported / not yet implemented";
+    static final String UNSUPPORTED_OPERATION_EXCEPTION_MESSAGE = "unsupported / not yet implemented";
 
     static {
         final Map<JsonToken, String> jsonTypeTypeMap = new HashMap<>();
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java
index 59de196..9c80dd9 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java
@@ -17,511 +17,105 @@
 package org.apache.camel.component.xj;
 
 import com.fasterxml.jackson.core.JsonFactory;
-import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
-import org.apache.camel.Exchange;
 import org.apache.camel.api.management.ManagedAttribute;
-import org.apache.camel.api.management.ManagedOperation;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.component.xslt.ResultHandlerFactory;
-import org.apache.camel.component.xslt.XsltOutput;
-import org.apache.camel.spi.*;
-import org.apache.camel.support.EndpointHelper;
-import org.apache.camel.support.ProcessorEndpoint;
-import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.component.xslt.XsltBuilder;
+import org.apache.camel.component.xslt.XsltEndpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
 import org.apache.camel.util.ObjectHelper;
-import org.xml.sax.EntityResolver;
-
-import javax.xml.transform.*;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-// todo?: This class is just a copy of XsltEndpoint because of minor but important different requirements. Refactoring of XsltComponent so that we can extend it?
 
 /**
  * Transforms json/xml message back and forth using a XSLT.
  */
 @ManagedResource(description = "Managed XJEndpoint")
-@UriEndpoint(firstVersion = "2.25.0", scheme = "xj", title = "XJ", syntax = "xj:resourceUri", producerOnly = true, label = "transformation")
-public class XJEndpoint extends ProcessorEndpoint {
-
-    public static final String SAXON_TRANSFORMER_FACTORY_CLASS_NAME = "net.sf.saxon.TransformerFactoryImpl";
-
-    private volatile boolean cacheCleared;
-    private volatile XsltBuilder xslt;
-    private Map<String, Object> parameters;
+@UriEndpoint(firstVersion = "3.0.0", scheme = "xj", title = "XJ", syntax = "xj:resourceUri", producerOnly = true, label = "transformation")
+public class XJEndpoint extends XsltEndpoint {
 
     private JsonFactory jsonFactory = new JsonFactory();
 
     @UriParam
-    @Metadata(required = true)
+    @Metadata(required = true, description = "Transform direction. Either XML2JSON or JSON2XML")
     private TransformDirection transformDirection;
-    @UriPath
-    @Metadata(required = true)
-    private String resourceUri;
-    @UriParam(defaultValue = "true")
-    private boolean contentCache = true;
-    @UriParam(label = "advanced")
-    private String transformerFactoryClass;
-    @UriParam(label = "advanced")
-    private TransformerFactory transformerFactory;
-    @UriParam
-    private boolean saxon;
-    @UriParam(label = "advanced")
-    private Object saxonConfiguration;
-    @Metadata(label = "advanced")
-    private Map<String, Object> saxonConfigurationProperties = new HashMap<>();
-    @UriParam(label = "advanced", javaType = "java.lang.String")
-    private List<Object> saxonExtensionFunctions;
-    @UriParam(label = "advanced")
-    private ResultHandlerFactory resultHandlerFactory;
-    @UriParam(defaultValue = "true")
-    private boolean failOnNullBody = true;
-    @UriParam(defaultValue = "string")
-    private XsltOutput output = XsltOutput.string;
-    @UriParam(defaultValue = "0")
-    private int transformerCacheSize;
-    @UriParam(label = "advanced")
-    private ErrorListener errorListener;
-    @UriParam(label = "advanced")
-    private URIResolver uriResolver;
-    @UriParam
-    private boolean deleteOutputFile;
-    @UriParam(label = "advanced")
-    private EntityResolver entityResolver;
 
     public XJEndpoint(String endpointUri, Component component) {
         super(endpointUri, component);
     }
 
-    @ManagedOperation(description = "Clears the cached XSLT stylesheet, forcing to re-load the stylesheet on next request")
-    public void clearCachedStylesheet() {
-        this.cacheCleared = true;
-    }
-
-    @ManagedAttribute(description = "Whether the XSLT stylesheet is cached")
-    public boolean isCacheStylesheet() {
-        return contentCache;
-    }
-
-    public XJEndpoint findOrCreateEndpoint(String uri, String newResourceUri) {
-        String newUri = uri.replace(resourceUri, newResourceUri);
-        log.trace("Getting endpoint with URI: {}", newUri);
-        return getCamelContext().getEndpoint(newUri, XJEndpoint.class);
-    }
-
-    @Override
-    protected void onExchange(Exchange exchange) throws Exception {
-        if (!contentCache || cacheCleared) {
-            loadResource(resourceUri);
-        }
-        super.onExchange(exchange);
-    }
-
     @ManagedAttribute(description = "Transform direction")
     public TransformDirection getTransformDirection() {
         return transformDirection;
     }
 
     /**
-     * The transform direction. Either XML2JSON or JSON2XML
+     * Sets the transform direction.
      */
     public void setTransformDirection(TransformDirection transformDirection) {
         this.transformDirection = transformDirection;
     }
 
-    public boolean isCacheCleared() {
-        return cacheCleared;
-    }
-
-    public void setCacheCleared(boolean cacheCleared) {
-        this.cacheCleared = cacheCleared;
-    }
-
-    public XsltBuilder getXslt() {
-        return xslt;
-    }
-
-    public void setXslt(XsltBuilder xslt) {
-        this.xslt = xslt;
-    }
-
-    @ManagedAttribute(description = "Path to the template")
-    public String getResourceUri() {
-        return resourceUri;
-    }
-
-    /**
-     * Path to the template.
-     * <p/>
-     * The following is supported by the default URIResolver.
-     * You can prefix with: classpath, file, http, ref, or bean.
-     * classpath, file and http loads the resource using these protocols (classpath is default).
-     * ref will lookup the resource in the registry.
-     * bean will call a method on a bean to be used as the resource.
-     * For bean you can specify the method name after dot, eg bean:myBean.myMethod
-     *
-     * @param resourceUri the resource path
-     */
-    public void setResourceUri(String resourceUri) {
-        this.resourceUri = resourceUri;
-    }
-
-    public String getTransformerFactoryClass() {
-        return transformerFactoryClass;
-    }
-
-    /**
-     * To use a custom XSLT transformer factory, specified as a FQN class name
-     */
-    public void setTransformerFactoryClass(String transformerFactoryClass) {
-        this.transformerFactoryClass = transformerFactoryClass;
-    }
-
-    public TransformerFactory getTransformerFactory() {
-        return transformerFactory;
-    }
-
-    /**
-     * To use a custom XSLT transformer factory
-     */
-    public void setTransformerFactory(TransformerFactory transformerFactory) {
-        this.transformerFactory = transformerFactory;
-    }
-
-    @ManagedAttribute(description = "Whether to use Saxon as the transformerFactoryClass")
-    public boolean isSaxon() {
-        return saxon;
-    }
-
-    /**
-     * Whether to use Saxon as the transformerFactoryClass.
-     * If enabled then the class net.sf.saxon.TransformerFactoryImpl. You would need to add Saxon to the classpath.
-     */
-    public void setSaxon(boolean saxon) {
-        this.saxon = saxon;
-    }
-
-    public List<Object> getSaxonExtensionFunctions() {
-        return saxonExtensionFunctions;
-    }
-
-    /**
-     * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition.
-     * You would need to add camel-saxon to the classpath.
-     * The function is looked up in the registry, where you can comma to separate multiple values to lookup.
-     */
-    public void setSaxonExtensionFunctions(List<Object> extensionFunctions) {
-        this.saxonExtensionFunctions = extensionFunctions;
-    }
-
-    /**
-     * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition.
-     * You would need to add camel-saxon to the classpath.
-     * The function is looked up in the registry, where you can comma to separate multiple values to lookup.
-     */
-    public void setSaxonExtensionFunctions(String extensionFunctions) {
-        this.saxonExtensionFunctions = EndpointHelper.resolveReferenceListParameter(
-                getCamelContext(),
-                extensionFunctions,
-                Object.class
-        );
-    }
-
-    public Object getSaxonConfiguration() {
-        return saxonConfiguration;
-    }
-
-    /**
-     * To use a custom Saxon configuration
-     */
-    public void setSaxonConfiguration(Object saxonConfiguration) {
-        this.saxonConfiguration = saxonConfiguration;
-    }
-
-    public Map<String, Object> getSaxonConfigurationProperties() {
-        return saxonConfigurationProperties;
-    }
-
-    /**
-     * To set custom Saxon configuration properties
-     */
-    public void setSaxonConfigurationProperties(Map<String, Object> configurationProperties) {
-        this.saxonConfigurationProperties = configurationProperties;
-    }
-
-    public ResultHandlerFactory getResultHandlerFactory() {
-        return resultHandlerFactory;
-    }
-
-    /**
-     * Allows you to use a custom org.apache.camel.builder.xml.ResultHandlerFactory which is capable of
-     * using custom org.apache.camel.builder.xml.ResultHandler types.
-     */
-    public void setResultHandlerFactory(ResultHandlerFactory resultHandlerFactory) {
-        this.resultHandlerFactory = resultHandlerFactory;
-    }
-
-    @ManagedAttribute(description = "Whether or not to throw an exception if the input body is null")
-    public boolean isFailOnNullBody() {
-        return failOnNullBody;
-    }
-
-    /**
-     * Whether or not to throw an exception if the input body is null.
-     */
-    public void setFailOnNullBody(boolean failOnNullBody) {
-        this.failOnNullBody = failOnNullBody;
-    }
-
-    @ManagedAttribute(description = "What kind of option to use.")
-    public XsltOutput getOutput() {
-        return output;
-    }
-
-    /**
-     * Option to specify which output type to use.
-     * Possible values are: string, bytes, DOM, file. The first three options are all in memory based, where as file is streamed directly to a java.io.File.
-     * For file you must specify the filename in the IN header with the key Exchange.XSLT_FILE_NAME which is also CamelXsltFileName.
-     * Also any paths leading to the filename must be created beforehand, otherwise an exception is thrown at runtime.
-     */
-    public void setOutput(XsltOutput output) {
-        this.output = output;
-    }
-
-    public int getTransformerCacheSize() {
-        return transformerCacheSize;
-    }
-
-    /**
-     * The number of javax.xml.transform.Transformer object that are cached for reuse to avoid calls to Template.newTransformer().
-     */
-    public void setTransformerCacheSize(int transformerCacheSize) {
-        this.transformerCacheSize = transformerCacheSize;
-    }
-
-    public ErrorListener getErrorListener() {
-        return errorListener;
-    }
-
-    /**
-     * Allows to configure to use a custom javax.xml.transform.ErrorListener. Beware when doing this then the default error
-     * listener which captures any errors or fatal errors and store information on the Exchange as properties is not in use.
-     * So only use this option for special use-cases.
-     */
-    public void setErrorListener(ErrorListener errorListener) {
-        this.errorListener = errorListener;
-    }
-
-    @ManagedAttribute(description = "Cache for the resource content (the stylesheet file) when it is loaded.")
-    public boolean isContentCache() {
-        return contentCache;
-    }
-
-    /**
-     * Cache for the resource content (the stylesheet file) when it is loaded.
-     * If set to false Camel will reload the stylesheet file on each message processing. This is good for development.
-     * A cached stylesheet can be forced to reload at runtime via JMX using the clearCachedStylesheet operation.
-     */
-    public void setContentCache(boolean contentCache) {
-        this.contentCache = contentCache;
-    }
-
-    public URIResolver getUriResolver() {
-        return uriResolver;
-    }
-
-    /**
-     * To use a custom javax.xml.transform.URIResolver
-     */
-    public void setUriResolver(URIResolver uriResolver) {
-        this.uriResolver = uriResolver;
-    }
-
-    public boolean isDeleteOutputFile() {
-        return deleteOutputFile;
-    }
-
-    /**
-     * If you have output=file then this option dictates whether or not the output file should be deleted when the Exchange
-     * is done processing. For example suppose the output file is a temporary file, then it can be a good idea to delete it after use.
-     */
-    public void setDeleteOutputFile(boolean deleteOutputFile) {
-        this.deleteOutputFile = deleteOutputFile;
-    }
-
-    public EntityResolver getEntityResolver() {
-        return entityResolver;
-    }
-
-    /**
-     * To use a custom org.xml.sax.EntityResolver with javax.xml.transform.sax.SAXSource.
-     */
-    public void setEntityResolver(EntityResolver entityResolver) {
-        this.entityResolver = entityResolver;
-    }
-
-    public Map<String, Object> getParameters() {
-        return parameters;
-    }
-
-    /**
-     * Additional parameters to configure on the javax.xml.transform.Transformer.
-     */
-    public void setParameters(Map<String, Object> parameters) {
-        this.parameters = parameters;
-    }
-
-    /**
-     * Loads the resource.
-     *
-     * @param resourceUri the resource to load
-     * @throws TransformerException is thrown if error loading resource
-     * @throws IOException          is thrown if error loading resource
-     */
-    protected void loadResource(String resourceUri) throws TransformerException, IOException {
-        log.trace("{} loading schema resource: {}", this, resourceUri);
-        Source source = xslt.getUriResolver().resolve(resourceUri, null);
-        if (source == null) {
-            throw new IOException("Cannot load xsl resource " + resourceUri);
-        } else {
-            xslt.setTransformerSource(source);
-        }
-        // now loaded so clear flag
-        cacheCleared = false;
-    }
-
     @Override
     protected void doStart() throws Exception {
-        super.doStart();
-
         if (ObjectHelper.isEmpty(getResourceUri())) {
             // todo using a stylesheet for "identity" transform is slow. But with transformerFactory we can't get an identity transformer...
             setResourceUri("org/apache/camel/component/xj/identity.xsl");
         }
 
-        final CamelContext ctx = getCamelContext();
-        final ClassResolver resolver = ctx.getClassResolver();
-        final Injector injector = ctx.getInjector();
-
-        log.debug("{} using schema resource: {}", this, resourceUri);
-
-        this.xslt = new XsltBuilder();
-
-        boolean useSaxon = false;
-        if (transformerFactoryClass == null && (saxon || saxonExtensionFunctions != null)) {
-            useSaxon = true;
-            transformerFactoryClass = SAXON_TRANSFORMER_FACTORY_CLASS_NAME;
-        }
-
-        TransformerFactory factory = transformerFactory;
-        if (factory == null && transformerFactoryClass != null) {
-            // provide the class loader of this component to work in OSGi environments
-            Class<TransformerFactory> factoryClass = resolver.resolveMandatoryClass(transformerFactoryClass, TransformerFactory.class, XJEndpoint.class.getClassLoader());
-            log.debug("Using TransformerFactoryClass {}", factoryClass);
-            factory = injector.newInstance(factoryClass);
+        super.doStart();
+    }
 
-            if (useSaxon) {
-                XsltHelper.registerSaxonConfiguration(ctx, factoryClass, factory, saxonConfiguration);
-                XsltHelper.registerSaxonConfigurationProperties(ctx, factoryClass, factory, saxonConfigurationProperties);
-                XsltHelper.registerSaxonExtensionFunctions(ctx, factoryClass, factory, saxonExtensionFunctions);
-            }
-        }
+    @Override
+    protected XsltBuilder createXsltBuilder() throws Exception {
+        final XsltBuilder xsltBuilder = super.createXsltBuilder();
+        xsltBuilder.setAllowStAX(true); // we rely on stax so always to true.
 
-        if (factory != null) {
-            log.debug("Using TransformerFactory {}", factory);
-            xslt.setTransformerFactory(factory);
-        }
-        if (resultHandlerFactory != null) {
-            xslt.setResultHandlerFactory(resultHandlerFactory);
-        }
-        if (this.transformDirection == TransformDirection.XML2JSON) {
-            xslt.setSourceHandlerFactory(new XmlSourceHandlerFactoryImpl());
-        } else {
-            xslt.setSourceHandlerFactory(new JsonSourceHandlerFactoryImpl(jsonFactory));
-        }
-        if (errorListener != null) {
-            xslt.errorListener(errorListener);
-        }
-        xslt.setFailOnNullBody(failOnNullBody);
-        xslt.transformerCacheSize(transformerCacheSize);
-        xslt.setUriResolver(uriResolver);
-        xslt.setEntityResolver(entityResolver);
-        xslt.setAllowStAX(true); // we rely on stax so always to true. No issues so far with jdk 1.8 and saxon xslt.
-        xslt.setDeleteOutputFile(deleteOutputFile);
+        configureInput(xsltBuilder);
 
-        configureOutput(xslt, output.name());
+        return xsltBuilder;
+    }
 
-        // any additional transformer parameters then make a copy to avoid side-effects
-        if (parameters != null) {
-            Map<String, Object> copy = new HashMap<>(parameters);
-            xslt.setParameters(copy);
+    /**
+     * Configures the source input depending on the {@link XJEndpoint#transformDirection}
+     */
+    protected void configureInput(XsltBuilder xsltBuilder) {
+        if (TransformDirection.JSON2XML == this.transformDirection) {
+            final JsonSourceHandlerFactoryImpl sourceHandlerFactory = new JsonSourceHandlerFactoryImpl(jsonFactory);
+            sourceHandlerFactory.setFailOnNullBody(isFailOnNullBody());
+            xsltBuilder.setSourceHandlerFactory(sourceHandlerFactory);
         }
-
-        // must load resource first which sets a template and do a stylesheet compilation to catch errors early
-        loadResource(resourceUri);
-
-        // the processor is the xslt builder
-        setProcessor(xslt);
+        // in the other direction, XML2JSON, the default org.apache.camel.component.xslt.XmlSourceHandlerFactoryImpl will be used
     }
 
-    protected void configureOutput(XsltBuilder xslt, String output) throws Exception {
+    /**
+     * Configures the result output depending on the {@link XJEndpoint#transformDirection}
+     */
+    protected void configureOutput(XsltBuilder xsltBuilder, String output) throws Exception {
         switch (this.transformDirection) {
             case JSON2XML:
-                configureXmlOutput(xslt, output);
+                super.configureOutput(xsltBuilder, output);
                 break;
             case XML2JSON:
-                configureJsonOutput(xslt, output);
+                configureJsonOutput(xsltBuilder, output);
                 break;
             default:
                 throw new IllegalArgumentException("Unknown transformation direction: " + this.transformDirection);
         }
     }
 
-    protected void configureXmlOutput(XsltBuilder xslt, String output) throws Exception {
-        if (ObjectHelper.isEmpty(output)) {
-            return;
-        }
-
-        switch (output) {
-            case "string":
-                xslt.outputString();
-                break;
-            case "bytes":
-                xslt.outputBytes();
-                break;
-            case "DOM":
-                xslt.outputDOM();
-                break;
-            case "file":
-                xslt.outputFile();
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown output type: " + output);
-        }
-    }
-
-    protected void configureJsonOutput(XsltBuilder xslt, String output) throws Exception {
-        switch (output) {
-            case "bytes":
-                xslt.setResultHandlerFactory(new JsonStreamResultHandlerFactory(jsonFactory));
-                break;
-            case "DOM":
-                throw new UnsupportedOperationException("DOM output not supported when transforming to json");
-            case "file":
-                xslt.setResultHandlerFactory(new JsonFileResultHandlerFactory(jsonFactory));
-                break;
-            default:
-                xslt.setResultHandlerFactory(new JsonStringResultHandlerFactory(jsonFactory));
-                break;
+    /**
+     * Configures the result output when transforming to JSON
+     */
+    protected void configureJsonOutput(XsltBuilder xsltBuilder, String output) {
+        if ("DOM".equals(output)) {
+            throw new UnsupportedOperationException("DOM output not supported when transforming to json");
+        } else if ("bytes".equals(output)) {
+            xsltBuilder.setResultHandlerFactory(new JsonStreamResultHandlerFactory(jsonFactory));
+        } else if ("file".equals(output)) {
+            xsltBuilder.setResultHandlerFactory(new JsonFileResultHandlerFactory(jsonFactory));
+        } else {
+            xsltBuilder.setResultHandlerFactory(new JsonStringResultHandlerFactory(jsonFactory));
         }
     }
-
-    @Override
-    protected void doStop() throws Exception {
-        super.doStop();
-        ServiceHelper.stopService(xslt);
-    }
 }
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlJsonStreamWriter.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlJsonStreamWriter.java
index ab64538..a9ef928 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlJsonStreamWriter.java
+++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlJsonStreamWriter.java
@@ -17,16 +17,24 @@
 
 package org.apache.camel.component.xj;
 
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonToken;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.stream.events.XMLEvent;
-import java.io.IOException;
-import java.util.*;
-import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonToken;
 
 /**
  * XML Json bridge. Explicitly using StreamWriter and not XMLEventWriter because saxon wants that.
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltBuilder.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltBuilder.java
deleted file mode 100644
index ea69c86..0000000
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltBuilder.java
+++ /dev/null
@@ -1,482 +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.component.xj;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Message;
-import org.apache.camel.Processor;
-import org.apache.camel.component.xslt.*;
-import org.apache.camel.support.ExchangeHelper;
-import org.apache.camel.support.SynchronizationAdapter;
-import org.apache.camel.support.builder.xml.XMLConverterHelper;
-import org.apache.camel.util.FileUtil;
-import org.apache.camel.util.IOHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.EntityResolver;
-
-import javax.xml.transform.*;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.stream.StreamSource;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-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 static org.apache.camel.util.ObjectHelper.notNull;
-
-// todo?: This class is just a copy from the XsltComponent because of minor but important different requirements. Refactoring of XsltComponent so that we can extend it?
-
-/**
- * Creates a <a href="http://camel.apache.org/processor.html">Processor</a>
- * which performs an XSLT transformation of the IN message body.
- * <p/>
- * Will by default output the result as a String. You can chose which kind of output
- * you want using the <tt>outputXXX</tt> methods.
- */
-public class XsltBuilder implements Processor {
-
-    private static final Logger LOG = LoggerFactory.getLogger(XsltBuilder.class);
-    private Map<String, Object> parameters = new HashMap<>();
-    private XMLConverterHelper converter = new XMLConverterHelper();
-    private Templates template;
-    private volatile BlockingQueue<Transformer> transformers;
-    private SourceHandlerFactory sourceHandlerFactory;
-    private ResultHandlerFactory resultHandlerFactory = new StringResultHandlerFactory();
-    private boolean failOnNullBody = true;
-    private URIResolver uriResolver;
-    private boolean deleteOutputFile;
-    private ErrorListener errorListener;
-    private boolean allowStAX = true;
-    private EntityResolver entityResolver;
-
-    public XsltBuilder() {
-    }
-
-    public XsltBuilder(Templates templates) {
-        this.template = templates;
-    }
-
-    @Override
-    public String toString() {
-        return "XSLT[" + template + "]";
-    }
-
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        notNull(getTemplate(), "template");
-
-        if (isDeleteOutputFile()) {
-            // add on completion so we can delete the file when the Exchange is done
-            String fileName = ExchangeHelper.getMandatoryHeader(exchange, Exchange.XSLT_FILE_NAME, String.class);
-            exchange.addOnCompletion(new XsltBuilderOnCompletion(fileName));
-        }
-
-        Transformer transformer = getTransformer();
-        configureTransformer(transformer, exchange);
-
-        ResultHandler resultHandler = resultHandlerFactory.createResult(exchange);
-        Result result = resultHandler.getResult();
-        // let's copy the headers before we invoke the transform in case they modify them
-        Message out = exchange.getOut();
-        out.copyFrom(exchange.getIn());
-
-        // the underlying input stream, which we need to close to avoid locking files or other resources
-        InputStream is = null;
-        try {
-            Source source = sourceHandlerFactory.getSource(exchange);
-            if (source instanceof SAXSource) {
-                tryAddEntityResolver((SAXSource) source);
-            }
-
-            LOG.trace("Using {} as source", source);
-            transformer.transform(source, result);
-            LOG.trace("Transform complete with result {}", result);
-            resultHandler.setBody(out);
-        } finally {
-            releaseTransformer(transformer);
-            // IOHelper can handle if is is null
-            IOHelper.close(is);
-        }
-    }
-
-    // Builder methods
-    // -------------------------------------------------------------------------
-
-    /**
-     * Creates an XSLT processor using the given templates instance
-     */
-    public static XsltBuilder xslt(Templates templates) {
-        return new XsltBuilder(templates);
-    }
-
-    /**
-     * Creates an XSLT processor using the given XSLT source
-     */
-    public static XsltBuilder xslt(Source xslt) throws TransformerConfigurationException {
-        notNull(xslt, "xslt");
-        XsltBuilder answer = new XsltBuilder();
-        answer.setTransformerSource(xslt);
-        return answer;
-    }
-
-    /**
-     * Creates an XSLT processor using the given XSLT source
-     */
-    public static XsltBuilder xslt(File xslt) throws TransformerConfigurationException {
-        notNull(xslt, "xslt");
-        return xslt(new StreamSource(xslt));
-    }
-
-    /**
-     * Creates an XSLT processor using the given XSLT source
-     */
-    public static XsltBuilder xslt(URL xslt) throws TransformerConfigurationException, IOException {
-        notNull(xslt, "xslt");
-        return xslt(xslt.openStream());
-    }
-
-    /**
-     * Creates an XSLT processor using the given XSLT source
-     */
-    public static XsltBuilder xslt(InputStream xslt) throws TransformerConfigurationException, IOException {
-        notNull(xslt, "xslt");
-        return xslt(new StreamSource(xslt));
-    }
-
-    /**
-     * Sets the output as being a byte[]
-     */
-    public XsltBuilder outputBytes() {
-        setResultHandlerFactory(new StreamResultHandlerFactory());
-        return this;
-    }
-
-    /**
-     * Sets the output as being a String
-     */
-    public XsltBuilder outputString() {
-        setResultHandlerFactory(new StringResultHandlerFactory());
-        return this;
-    }
-
-    /**
-     * Sets the output as being a DOM
-     */
-    public XsltBuilder outputDOM() {
-        setResultHandlerFactory(new DomResultHandlerFactory());
-        return this;
-    }
-
-    /**
-     * Sets the output as being a File where the filename
-     * must be provided in the {@link Exchange#XSLT_FILE_NAME} header.
-     */
-    public XsltBuilder outputFile() {
-        setResultHandlerFactory(new FileResultHandlerFactory());
-        return this;
-    }
-
-    /**
-     * Should the output file be deleted when the {@link Exchange} is done.
-     * <p/>
-     * This option should only be used if you use {@link #outputFile()} as well.
-     */
-    public XsltBuilder deleteOutputFile() {
-        this.deleteOutputFile = true;
-        return this;
-    }
-
-    public XsltBuilder parameter(String name, Object value) {
-        parameters.put(name, value);
-        return this;
-    }
-
-    /**
-     * Sets a custom URI resolver to be used
-     */
-    public XsltBuilder uriResolver(URIResolver uriResolver) {
-        setUriResolver(uriResolver);
-        return this;
-    }
-
-    /**
-     * Enables to allow using StAX.
-     * <p/>
-     * When enabled StAX is preferred as the first choice as {@link Source}.
-     */
-    public XsltBuilder allowStAX() {
-        setAllowStAX(true);
-        return this;
-    }
-
-    /**
-     * Used for caching {@link Transformer}s.
-     * <p/>
-     * By default no caching is in use.
-     *
-     * @param numberToCache the maximum number of transformers to cache
-     */
-    public XsltBuilder transformerCacheSize(int numberToCache) {
-        if (numberToCache > 0) {
-            transformers = new ArrayBlockingQueue<>(numberToCache);
-        } else {
-            transformers = null;
-        }
-        return this;
-    }
-
-    /**
-     * Uses a custom {@link ErrorListener}.
-     */
-    public XsltBuilder errorListener(ErrorListener errorListener) {
-        setErrorListener(errorListener);
-        return this;
-    }
-
-    // Properties
-    // -------------------------------------------------------------------------
-
-    public Map<String, Object> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(Map<String, Object> parameters) {
-        this.parameters = parameters;
-    }
-
-    public void setTemplate(Templates template) {
-        this.template = template;
-        if (transformers != null) {
-            transformers.clear();
-        }
-    }
-
-    public Templates getTemplate() {
-        return template;
-    }
-
-    public boolean isFailOnNullBody() {
-        return failOnNullBody;
-    }
-
-    public void setFailOnNullBody(boolean failOnNullBody) {
-        this.failOnNullBody = failOnNullBody;
-    }
-
-    public SourceHandlerFactory getSourceHandlerFactory() {
-        return sourceHandlerFactory;
-    }
-
-    public void setSourceHandlerFactory(SourceHandlerFactory sourceHandlerFactory) {
-        this.sourceHandlerFactory = sourceHandlerFactory;
-    }
-
-    public ResultHandlerFactory getResultHandlerFactory() {
-        return resultHandlerFactory;
-    }
-
-    public void setResultHandlerFactory(ResultHandlerFactory resultHandlerFactory) {
-        this.resultHandlerFactory = resultHandlerFactory;
-    }
-
-    public boolean isAllowStAX() {
-        return allowStAX;
-    }
-
-    public void setAllowStAX(boolean allowStAX) {
-        this.allowStAX = allowStAX;
-    }
-
-    /**
-     * Sets the XSLT transformer from a Source
-     *
-     * @param source the source
-     * @throws TransformerConfigurationException is thrown if creating a XSLT transformer failed.
-     */
-    public void setTransformerSource(Source source) throws TransformerConfigurationException {
-        TransformerFactory factory = converter.getTransformerFactory();
-        if (errorListener != null) {
-            factory.setErrorListener(errorListener);
-        } else {
-            // use a logger error listener so users can see from the logs what the error may be
-            factory.setErrorListener(new XsltErrorListener());
-        }
-        if (getUriResolver() != null) {
-            factory.setURIResolver(getUriResolver());
-        }
-
-        // Check that the call to newTemplates() returns a valid template instance.
-        // In case of an xslt parse error, it will return null and we should stop the
-        // deployment and raise an exception as the route will not be setup properly.
-        Templates templates = factory.newTemplates(source);
-        if (templates != null) {
-            setTemplate(templates);
-        } else {
-            throw new TransformerConfigurationException("Error creating XSLT template. "
-                    + "This is most likely be caused by a XML parse error. "
-                    + "Please verify your XSLT file configured.");
-        }
-    }
-
-    /**
-     * Sets the XSLT transformer from a File
-     */
-    public void setTransformerFile(File xslt) throws TransformerConfigurationException {
-        setTransformerSource(new StreamSource(xslt));
-    }
-
-    /**
-     * Sets the XSLT transformer from a URL
-     */
-    public void setTransformerURL(URL url) throws TransformerConfigurationException, IOException {
-        notNull(url, "url");
-        setTransformerInputStream(url.openStream());
-    }
-
-    /**
-     * Sets the XSLT transformer from the given input stream
-     */
-    public void setTransformerInputStream(InputStream in) throws TransformerConfigurationException, IOException {
-        notNull(in, "InputStream");
-        setTransformerSource(new StreamSource(in));
-    }
-
-    public URIResolver getUriResolver() {
-        return uriResolver;
-    }
-
-    public void setUriResolver(URIResolver uriResolver) {
-        this.uriResolver = uriResolver;
-    }
-
-    public void setEntityResolver(EntityResolver entityResolver) {
-        this.entityResolver = entityResolver;
-    }
-
-    public boolean isDeleteOutputFile() {
-        return deleteOutputFile;
-    }
-
-    public void setDeleteOutputFile(boolean deleteOutputFile) {
-        this.deleteOutputFile = deleteOutputFile;
-    }
-
-    public ErrorListener getErrorListener() {
-        return errorListener;
-    }
-
-    public void setErrorListener(ErrorListener errorListener) {
-        this.errorListener = errorListener;
-    }
-
-    // Implementation methods
-    // -------------------------------------------------------------------------
-    public void setTransformerFactory(TransformerFactory transformerFactory) {
-        this.converter.setTransformerFactory(transformerFactory);
-    }
-
-    private void releaseTransformer(Transformer transformer) {
-        if (transformers != null) {
-            transformer.reset();
-            transformers.offer(transformer);
-        }
-    }
-
-    private Transformer getTransformer() throws Exception {
-        Transformer t = null;
-        if (transformers != null) {
-            t = transformers.poll();
-        }
-        if (t == null) {
-            t = createTransformer();
-        }
-        return t;
-    }
-
-    protected Transformer createTransformer() throws Exception {
-        return getTemplate().newTransformer();
-    }
-
-    private void tryAddEntityResolver(SAXSource source) {
-        //expecting source to have not null XMLReader
-        if (this.entityResolver != null && source != null) {
-            source.getXMLReader().setEntityResolver(this.entityResolver);
-        }
-    }
-
-    /**
-     * Configures the transformer with exchange specific parameters
-     */
-    protected void configureTransformer(Transformer transformer, Exchange exchange) throws Exception {
-        if (uriResolver == null) {
-            uriResolver = new XsltUriResolver(exchange.getContext(), null);
-        }
-        transformer.setURIResolver(uriResolver);
-        if (errorListener == null) {
-            // set our error listener so we can capture errors and report them back on the exchange
-            transformer.setErrorListener(new DefaultTransformErrorHandler(exchange));
-        } else {
-            // use custom error listener
-            transformer.setErrorListener(errorListener);
-        }
-
-        transformer.clearParameters();
-        addParameters(transformer, exchange.getProperties());
-        addParameters(transformer, exchange.getIn().getHeaders());
-        addParameters(transformer, getParameters());
-        transformer.setParameter("exchange", exchange);
-        transformer.setParameter("in", exchange.getIn());
-        transformer.setParameter("out", exchange.getOut());
-    }
-
-    protected void addParameters(Transformer transformer, Map<String, Object> map) {
-        Set<Map.Entry<String, Object>> propertyEntries = map.entrySet();
-        for (Map.Entry<String, Object> entry : propertyEntries) {
-            String key = entry.getKey();
-            Object value = entry.getValue();
-            if (value != null) {
-                LOG.trace("Transformer set parameter {} -> {}", key, value);
-                transformer.setParameter(key, value);
-            }
-        }
-    }
-
-    private static final class XsltBuilderOnCompletion extends SynchronizationAdapter {
-        private final String fileName;
-
-        private XsltBuilderOnCompletion(String fileName) {
-            this.fileName = fileName;
-        }
-
-        @Override
-        public void onDone(Exchange exchange) {
-            FileUtil.deleteFile(new File(fileName));
-        }
-
-        @Override
-        public String toString() {
-            return "XsltBuilderOnCompletion";
-        }
-    }
-
-}
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltHelper.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltHelper.java
deleted file mode 100644
index 1034aef..0000000
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XsltHelper.java
+++ /dev/null
@@ -1,104 +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.component.xj;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.component.xslt.XsltComponent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.xml.XMLConstants;
-import javax.xml.transform.TransformerFactory;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-// todo 1:1 copy from XsltComponent
-
-final class XsltHelper {
-    private static final Logger LOG = LoggerFactory.getLogger(XsltHelper.class);
-
-    private static final String SAXON_CONFIGURATION_CLASS_NAME = "net.sf.saxon.Configuration";
-    private static final String SAXON_EXTENDED_FUNCTION_DEFINITION_CLASS_NAME = "net.sf.saxon.lib.ExtensionFunctionDefinition";
-
-    private XsltHelper() {
-    }
-
-    public static void registerSaxonConfiguration(
-            CamelContext camelContext, Class<?> factoryClass, TransformerFactory factory, Object saxonConfiguration) throws Exception {
-
-        if (saxonConfiguration != null) {
-            Class<?> configurationClass = camelContext.getClassResolver().resolveClass(SAXON_CONFIGURATION_CLASS_NAME);
-            if (configurationClass != null) {
-                Method method = factoryClass.getMethod("setConfiguration", configurationClass);
-                if (method != null) {
-                    method.invoke(factory, configurationClass.cast(saxonConfiguration));
-                }
-            }
-        }
-    }
-
-    public static void registerSaxonConfigurationProperties(
-            CamelContext camelContext, Class<?> factoryClass, TransformerFactory factory, Map<String, Object> saxonConfigurationProperties) throws Exception {
-
-        if (saxonConfigurationProperties != null && !saxonConfigurationProperties.isEmpty()) {
-            Method method = factoryClass.getMethod("getConfiguration");
-            if (method != null) {
-                Object configuration = method.invoke(factory);
-                if (configuration != null) {
-                    method = configuration.getClass().getMethod("setConfigurationProperty", String.class, Object.class);
-                    for (Map.Entry<String, Object> entry : saxonConfigurationProperties.entrySet()) {
-                        method.invoke(configuration, entry.getKey(), entry.getValue());
-                    }
-                }
-            }
-        }
-    }
-
-    public static void registerSaxonExtensionFunctions(
-            CamelContext camelContext, Class<?> factoryClass, TransformerFactory factory, List<Object> saxonExtensionFunctions) throws Exception {
-
-        if (saxonExtensionFunctions != null && !saxonExtensionFunctions.isEmpty()) {
-            Method method = factoryClass.getMethod("getConfiguration");
-            if (method != null) {
-                Object configuration = method.invoke(factory);
-                if (configuration != null) {
-                    Class<?> extensionClass = camelContext.getClassResolver().resolveMandatoryClass(
-                            SAXON_EXTENDED_FUNCTION_DEFINITION_CLASS_NAME, XsltComponent.class.getClassLoader()
-                    );
-
-                    method = configuration.getClass().getMethod("registerExtensionFunction", extensionClass);
-                    if (method != null) {
-                        factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-                        for (Object extensionFunction : saxonExtensionFunctions) {
-                            if (extensionClass.isInstance(extensionFunction)) {
-                                LOG.debug("Saxon.registerExtensionFunction {}", extensionFunction);
-                                method.invoke(configuration, extensionFunction);
-                            }
-                        }
-                    } else {
-                        LOG.warn("Unable to get reference to method registerExtensionFunction on {}", configuration.getClass().getName());
-                    }
-                } else {
-                    LOG.warn("Unable to get Saxon configuration ({}) on {}", SAXON_CONFIGURATION_CLASS_NAME, factory.getClass().getName());
-                }
-            } else {
-                LOG.warn("Unable to get reference to method getConfiguration on {}", factoryClass.getName());
-            }
-        }
-    }
-}
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/SourceHandlerFactory.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/SourceHandlerFactory.java
similarity index 72%
rename from components/camel-xj/src/main/java/org/apache/camel/component/xj/SourceHandlerFactory.java
rename to components/camel-xslt/src/main/java/org/apache/camel/component/xslt/SourceHandlerFactory.java
index 76898c1..7808a07 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/SourceHandlerFactory.java
+++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/SourceHandlerFactory.java
@@ -14,13 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.xj;
-
-import org.apache.camel.Exchange;
+package org.apache.camel.component.xslt;
 
 import javax.xml.transform.Source;
 
+import org.apache.camel.Exchange;
+
+/**
+ * Interface to be implemented by concrete source handlers/converters
+ */
 public interface SourceHandlerFactory {
 
+    /**
+     * Creates a specific {@link Source} depending on the current message exchanged
+     * @param exchange the exchange
+     * @return the source created from the message
+     * @throws Exception if the source couldn't be created
+     */
     Source getSource(Exchange exchange) throws Exception;
 }
diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlSourceHandlerFactoryImpl.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XmlSourceHandlerFactoryImpl.java
similarity index 86%
rename from components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlSourceHandlerFactoryImpl.java
rename to components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XmlSourceHandlerFactoryImpl.java
index 230459d..eead2c1 100644
--- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XmlSourceHandlerFactoryImpl.java
+++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XmlSourceHandlerFactoryImpl.java
@@ -14,14 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.component.xj;
+package org.apache.camel.component.xslt;
 
-import org.apache.camel.Exchange;
-import org.apache.camel.ExpectedBodyTypeException;
-import org.apache.camel.RuntimeTransformException;
-import org.apache.camel.TypeConverter;
-import org.apache.camel.support.builder.xml.XMLConverterHelper;
-import org.w3c.dom.Node;
+import java.io.InputStream;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Source;
@@ -30,21 +25,61 @@ import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.transform.stream.StreamSource;
-import java.io.InputStream;
 
+import org.w3c.dom.Node;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExpectedBodyTypeException;
+import org.apache.camel.RuntimeTransformException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.support.builder.xml.XMLConverterHelper;
+
+/**
+ * Handler for xml sources
+ */
 public class XmlSourceHandlerFactoryImpl implements SourceHandlerFactory {
 
     private XMLConverterHelper converter = new XMLConverterHelper();
     private boolean isFailOnNullBody = true;
+    private boolean allowStax = true;
+
+    /**
+     * Returns true if we fail when the body is null.
+     */
+    public boolean isFailOnNullBody() {
+        return isFailOnNullBody;
+    }
 
+    /**
+     * Set if we should fail when the body is null
+     *
+     * @param failOnNullBody
+     */
     public void setFailOnNullBody(boolean failOnNullBody) {
         isFailOnNullBody = failOnNullBody;
     }
 
-    public boolean isFailOnNullBody() {
-        return isFailOnNullBody;
+    /**
+     * Returns true if Stax is allowed
+     *
+     * @return
+     */
+    public boolean isAllowStax() {
+        return allowStax;
+    }
+
+    /**
+     * Sets if a {@link StAXSource} is allowed to read the document
+     *
+     * @param allowStax
+     */
+    public void setAllowStax(boolean allowStax) {
+        this.allowStax = allowStax;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Source getSource(Exchange exchange) throws Exception {
         // only convert to input stream if really needed
@@ -108,9 +143,10 @@ public class XmlSourceHandlerFactoryImpl implements SourceHandlerFactory {
         }
         Source source = null;
         if (body != null) {
-            // try StAX if enabled
-            source = exchange.getContext().getTypeConverter().tryConvertTo(StAXSource.class, exchange, body);
-
+            if (isAllowStax()) {
+                // try StAX if enabled
+                source = exchange.getContext().getTypeConverter().tryConvertTo(StAXSource.class, exchange, body);
+            }
             if (source == null) {
                 // then try SAX
                 source = exchange.getContext().getTypeConverter().tryConvertTo(SAXSource.class, exchange, body);
diff --git a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
index 95b6311..83a3c61 100644
--- a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
+++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java
@@ -25,30 +25,23 @@ 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;
 import javax.xml.transform.Source;
 import javax.xml.transform.Templates;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.URIResolver;
-import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.transform.stream.StreamSource;
 
-import org.w3c.dom.Node;
 import org.xml.sax.EntityResolver;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.ExpectedBodyTypeException;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
-import org.apache.camel.RuntimeTransformException;
-import org.apache.camel.TypeConverter;
 import org.apache.camel.support.ExchangeHelper;
 import org.apache.camel.support.SynchronizationAdapter;
 import org.apache.camel.support.builder.xml.StAX2SAXSource;
@@ -74,6 +67,7 @@ public class XsltBuilder implements Processor {
     private XMLConverterHelper converter = new XMLConverterHelper();
     private Templates template;
     private volatile BlockingQueue<Transformer> transformers;
+    private SourceHandlerFactory sourceHandlerFactory;
     private ResultHandlerFactory resultHandlerFactory = new StringResultHandlerFactory();
     private boolean failOnNullBody = true;
     private URIResolver uriResolver;
@@ -82,6 +76,8 @@ public class XsltBuilder implements Processor {
     private boolean allowStAX = true;
     private EntityResolver entityResolver;
 
+    private volatile Object sourceHandlerFactoryLock = new Object();
+
     public XsltBuilder() {
     }
 
@@ -116,17 +112,9 @@ public class XsltBuilder implements Processor {
         // the underlying input stream, which we need to close to avoid locking files or other resources
         InputStream is = null;
         try {
-            Source source;
-            // only convert to input stream if really needed
-            if (isInputStreamNeeded(exchange)) {
-                is = exchange.getIn().getBody(InputStream.class);
-                source = getSource(exchange, is);
-            } else {
-                Object body = exchange.getIn().getBody();
-                source = getSource(exchange, body);
-            }
+            Source source = getSourceHandlerFactory().getSource(exchange);
 
-            if (source instanceof StAXSource) {
+            if (!isAllowStAX() && 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
@@ -136,6 +124,10 @@ public class XsltBuilder implements Processor {
                 source = new StAX2SAXSource(((StAXSource) source).getXMLStreamReader());
             }
 
+            if (source instanceof SAXSource) {
+                tryAddEntityResolver((SAXSource) source);
+            }
+
             LOG.trace("Using {} as source", source);
             transformer.transform(source, result);
             LOG.trace("Transform complete with result {}", result);
@@ -311,6 +303,26 @@ public class XsltBuilder implements Processor {
         this.failOnNullBody = failOnNullBody;
     }
 
+    public SourceHandlerFactory getSourceHandlerFactory() {
+        if (this.sourceHandlerFactory == null) {
+            synchronized (this.sourceHandlerFactoryLock) {
+                if (this.sourceHandlerFactory == null) {
+                    final XmlSourceHandlerFactoryImpl xmlSourceHandlerFactory = new XmlSourceHandlerFactoryImpl();
+                    xmlSourceHandlerFactory.setFailOnNullBody(isFailOnNullBody());
+                    xmlSourceHandlerFactory.setAllowStax(isAllowStAX());
+
+                    this.sourceHandlerFactory = xmlSourceHandlerFactory;
+                }
+            }
+        }
+
+        return this.sourceHandlerFactory;
+    }
+
+    public void setSourceHandlerFactory(SourceHandlerFactory sourceHandlerFactory) {
+        this.sourceHandlerFactory = sourceHandlerFactory;
+    }
+
     public ResultHandlerFactory getResultHandlerFactory() {
         return resultHandlerFactory;
     }
@@ -437,97 +449,6 @@ public class XsltBuilder implements Processor {
         return getTemplate().newTransformer();
     }
 
-    /**
-     * Checks whether we need an {@link InputStream} to access the message body.
-     * <p/>
-     * Depending on the content in the message body, we may not need to convert
-     * to {@link InputStream}.
-     *
-     * @param exchange the current exchange
-     * @return <tt>true</tt> to convert to {@link InputStream} beforehand converting to {@link Source} afterwards.
-     */
-    protected boolean isInputStreamNeeded(Exchange exchange) {
-        Object body = exchange.getIn().getBody();
-        if (body == null) {
-            return false;
-        }
-
-        if (body instanceof InputStream) {
-            return true;
-        } else if (body instanceof Source) {
-            return false;
-        } else if (body instanceof String) {
-            return false;
-        } else if (body instanceof byte[]) {
-            return false;
-        } else if (body instanceof Node) {
-            return false;
-        } else if (exchange.getContext().getTypeConverterRegistry().lookup(Source.class, body.getClass()) != null) {
-            //there is a direct and hopefully optimized converter to Source 
-            return false;
-        }
-        // yes an input stream is needed
-        return true;
-    }
-
-    /**
-     * Converts the inbound body to a {@link Source}, if the body is <b>not</b> already a {@link Source}.
-     * <p/>
-     * This implementation will prefer to source in the following order:
-     * <ul>
-     *   <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) {
-        // body may already be a source
-        if (body instanceof Source) {
-            return (Source) body;
-        }
-        Source source = null;
-        if (body != null) {
-            if (isAllowStAX()) {
-                // try StAX if enabled
-                source = exchange.getContext().getTypeConverter().tryConvertTo(StAXSource.class, exchange, body);
-            }
-            if (source == null) {
-                // then try SAX
-                source = exchange.getContext().getTypeConverter().tryConvertTo(SAXSource.class, exchange, body);
-                tryAddEntityResolver((SAXSource)source);
-            }
-            if (source == null) {
-                // then try stream
-                source = exchange.getContext().getTypeConverter().tryConvertTo(StreamSource.class, exchange, body);
-            }
-            if (source == null) {
-                // and fallback to DOM
-                source = exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class, exchange, body);
-            }
-            // as the TypeConverterRegistry will look up source the converter differently if the type converter is loaded different
-            // now we just put the call of source converter at last
-            if (source == null) {
-                TypeConverter tc = exchange.getContext().getTypeConverterRegistry().lookup(Source.class, body.getClass());
-                if (tc != null) {
-                    source = tc.convertTo(Source.class, exchange, body);
-                }
-            }
-        }
-        if (source == null) {
-            if (isFailOnNullBody()) {
-                throw new ExpectedBodyTypeException(exchange, Source.class);
-            } else {
-                try {
-                    source = converter.toDOMSource(converter.createDocument());
-                } catch (ParserConfigurationException | TransformerException e) {
-                    throw new RuntimeTransformException(e);
-                }
-            }
-        }
-        return source;
-    }
-
     private void tryAddEntityResolver(SAXSource source) {
         //expecting source to have not null XMLReader
         if (this.entityResolver != null && source != null) {
diff --git a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltComponent.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltComponent.java
index 88147d6..eab98e7 100644
--- a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltComponent.java
+++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltComponent.java
@@ -150,7 +150,17 @@ public class XsltComponent extends DefaultComponent {
 
     @Override
     protected Endpoint createEndpoint(String uri, final String remaining, Map<String, Object> parameters) throws Exception {
-        XsltEndpoint endpoint = new XsltEndpoint(uri, this);
+        XsltEndpoint endpoint = createXsltEndpoint(uri);
+        configureEndpoint(endpoint, remaining, parameters);
+
+        return endpoint;
+    }
+
+    protected XsltEndpoint createXsltEndpoint(String uri) {
+        return new XsltEndpoint(uri, this);
+    }
+
+    protected void configureEndpoint(XsltEndpoint endpoint, final String remaining, Map<String, Object> parameters) throws Exception {
         endpoint.setContentCache(isContentCache());
         endpoint.setSaxon(isSaxon());
         endpoint.setSaxonConfiguration(saxonConfiguration);
@@ -162,7 +172,7 @@ public class XsltComponent extends DefaultComponent {
         if (resolver == null) {
             // not in endpoint then use component specific resolver
             resolver = getUriResolver();
-        }       
+        }
         if (resolver == null) {
             // lookup custom resolver factory to use
             XsltUriResolverFactory resolverFactory = resolveAndRemoveReferenceParameter(parameters, "uriResolverFactory", XsltUriResolverFactory.class);
@@ -174,7 +184,7 @@ public class XsltComponent extends DefaultComponent {
                 // fallback to use the Default URI resolver factory
                 resolverFactory = new DefaultXsltUriResolverFactory();
             }
-            
+
             resolver = resolverFactory.createUriResolver(getCamelContext(), remaining);
         }
         endpoint.setUriResolver(resolver);
@@ -193,8 +203,5 @@ public class XsltComponent extends DefaultComponent {
             // additional parameters need to be stored on endpoint as they can be used to configure xslt builder additionally
             endpoint.setParameters(parameters);
         }
-
-        return endpoint;
     }
-
 }
diff --git a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
index bfcac07..888770a 100644
--- a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
+++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java
@@ -116,7 +116,7 @@ public class XsltEndpoint extends ProcessorEndpoint {
     @Override
     protected void onExchange(Exchange exchange) throws Exception {
         if (!contentCache || cacheCleared) {
-            loadResource(resourceUri);
+            loadResource(resourceUri, xslt);
         }
         super.onExchange(exchange);
     }
@@ -382,7 +382,7 @@ public class XsltEndpoint extends ProcessorEndpoint {
      * @throws TransformerException is thrown if error loading resource
      * @throws IOException is thrown if error loading resource
      */
-    protected void loadResource(String resourceUri) throws TransformerException, IOException {
+    protected void loadResource(String resourceUri, XsltBuilder xslt) throws TransformerException, IOException {
         log.trace("{} loading schema resource: {}", this, resourceUri);
         Source source = xslt.getUriResolver().resolve(resourceUri, null);
         if (source == null) {
@@ -398,13 +398,19 @@ public class XsltEndpoint extends ProcessorEndpoint {
     protected void doStart() throws Exception {
         super.doStart();
 
+        // the processor is the xslt builder
+        setXslt(createXsltBuilder());
+        setProcessor(getXslt());
+    }
+
+    protected XsltBuilder createXsltBuilder() throws Exception {
         final CamelContext ctx = getCamelContext();
         final ClassResolver resolver = ctx.getClassResolver();
         final Injector injector = ctx.getInjector();
 
         log.debug("{} using schema resource: {}", this, resourceUri);
 
-        this.xslt = injector.newInstance(XsltBuilder.class);
+        final XsltBuilder xslt = injector.newInstance(XsltBuilder.class);
 
         boolean useSaxon = false;
         if (transformerFactoryClass == null && (saxon || saxonExtensionFunctions != null)) {
@@ -452,10 +458,9 @@ public class XsltEndpoint extends ProcessorEndpoint {
         }
 
         // must load resource first which sets a template and do a stylesheet compilation to catch errors early
-        loadResource(resourceUri);
+        loadResource(resourceUri, xslt);
 
-        // the processor is the xslt builder
-        setProcessor(xslt);
+        return xslt;
     }
 
     protected void configureOutput(XsltBuilder xslt, String output) throws Exception {
@@ -479,6 +484,6 @@ public class XsltEndpoint extends ProcessorEndpoint {
     @Override
     protected void doStop() throws Exception {
         super.doStop();
-        ServiceHelper.stopService(xslt);
+        ServiceHelper.stopService(getXslt());
     }
 }
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
index 1f978fa..f597047 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/XJEndpointBuilderFactory.java
@@ -39,6 +39,55 @@ public interface XJEndpointBuilderFactory {
             return (AdvancedXJEndpointBuilder) this;
         }
         /**
+         * Sets the transform direction.
+         * 
+         * The option is a:
+         * <code>org.apache.camel.component.xj.TransformDirection</code> type.
+         * 
+         * Required: true
+         * Group: producer
+         */
+        default XJEndpointBuilder transformDirection(
+                TransformDirection transformDirection) {
+            setProperty("transformDirection", transformDirection);
+            return this;
+        }
+        /**
+         * Sets the transform direction.
+         * 
+         * The option will be converted to a
+         * <code>org.apache.camel.component.xj.TransformDirection</code> type.
+         * 
+         * Required: true
+         * Group: producer
+         */
+        default XJEndpointBuilder transformDirection(String transformDirection) {
+            setProperty("transformDirection", transformDirection);
+            return this;
+        }
+        /**
+         * Whether to allow using StAX as the javax.xml.transform.Source.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Group: producer
+         */
+        default XJEndpointBuilder allowStAX(boolean allowStAX) {
+            setProperty("allowStAX", allowStAX);
+            return this;
+        }
+        /**
+         * Whether to allow using StAX as the javax.xml.transform.Source.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Group: producer
+         */
+        default XJEndpointBuilder allowStAX(String allowStAX) {
+            setProperty("allowStAX", allowStAX);
+            return this;
+        }
+        /**
          * Cache for the resource content (the stylesheet file) when it is
          * loaded. If set to false Camel will reload the stylesheet file on each
          * message processing. This is good for development. A cached stylesheet
@@ -181,33 +230,6 @@ public interface XJEndpointBuilderFactory {
             return this;
         }
         /**
-         * The transform direction. Either XML2JSON or JSON2XML.
-         * 
-         * The option is a:
-         * <code>org.apache.camel.component.xj.TransformDirection</code> type.
-         * 
-         * Required: true
-         * Group: producer
-         */
-        default XJEndpointBuilder transformDirection(
-                TransformDirection transformDirection) {
-            setProperty("transformDirection", transformDirection);
-            return this;
-        }
-        /**
-         * The transform direction. Either XML2JSON or JSON2XML.
-         * 
-         * The option will be converted to a
-         * <code>org.apache.camel.component.xj.TransformDirection</code> type.
-         * 
-         * Required: true
-         * Group: producer
-         */
-        default XJEndpointBuilder transformDirection(String transformDirection) {
-            setProperty("transformDirection", transformDirection);
-            return this;
-        }
-        /**
          * The number of javax.xml.transform.Transformer object that are cached
          * for reuse to avoid calls to Template.newTransformer().
          * 
@@ -502,6 +524,15 @@ public interface XJEndpointBuilderFactory {
     }
 
     /**
+     * Proxy enum for
+     * <code>org.apache.camel.component.xj.TransformDirection</code> enum.
+     */
+    enum TransformDirection {
+        XML2JSON,
+        JSON2XML;
+    }
+
+    /**
      * Proxy enum for <code>org.apache.camel.component.xslt.XsltOutput</code>
      * enum.
      */
@@ -511,21 +542,12 @@ public interface XJEndpointBuilderFactory {
         DOM,
         file;
     }
-
-    /**
-     * Proxy enum for
-     * <code>org.apache.camel.component.xj.TransformDirection</code> enum.
-     */
-    enum TransformDirection {
-        XML2JSON,
-        JSON2XML;
-    }
     /**
      * XJ (camel-xj)
      * Transforms json/xml message back and forth using a XSLT.
      * 
      * Category: transformation
-     * Available as of version: 2.25
+     * Available as of version: 3.0
      * Maven coordinates: org.apache.camel:camel-xj
      * 
      * Syntax: <code>xj:resourceUri</code>


Mime
View raw message