blob: 315fccab8cad603c531bc78fda0b56b831844b4f [file] [log] [blame]
/*
* 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.xslt.saxon;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.Configuration;
import net.sf.saxon.TransformerFactoryImpl;
import org.apache.camel.CamelContext;
import org.apache.camel.Component;
import org.apache.camel.api.management.ManagedAttribute;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.component.xslt.XsltEndpoint;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.Injector;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.support.EndpointHelper;
/**
* Transforms the message using a XSLT template using Saxon.
*/
@ManagedResource(description = "Managed XsltSaxonEndpoint")
@UriEndpoint(firstVersion = "3.0.0", scheme = "xslt-saxon", title = "XSLT Saxon", syntax = "xslt-saxon:resourceUri", producerOnly = true, label = "core,transformation")
public class XsltSaxonEndpoint extends XsltEndpoint {
@UriParam(label = "advanced")
private Configuration saxonConfiguration;
@Metadata(label = "advanced")
private Map<String, Object> saxonConfigurationProperties = new HashMap<>();
@UriParam(label = "advanced", javaType = "java.lang.String")
private List<Object> saxonExtensionFunctions;
@UriParam(displayName = "Allow StAX", defaultValue = "true")
private boolean allowStAX = true;
public XsltSaxonEndpoint(String endpointUri, Component component) {
super(endpointUri, component);
}
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 Configuration getSaxonConfiguration() {
return saxonConfiguration;
}
/**
* To use a custom Saxon configuration
*/
public void setSaxonConfiguration(Configuration 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;
}
@ManagedAttribute(description = "Whether to allow using StAX as the javax.xml.transform.Source")
public boolean isAllowStAX() {
return allowStAX;
}
/**
* Whether to allow using StAX as the javax.xml.transform.Source.
* You can enable this if the XSLT library supports StAX such as the Saxon library (camel-saxon).
* The Xalan library (default in JVM) does not support StAXSource.
*/
public void setAllowStAX(boolean allowStAX) {
this.allowStAX = allowStAX;
}
@Override
protected void doStart() throws Exception {
// the processor is the xslt builder
setXslt(createXsltBuilder());
setProcessor(getXslt());
}
protected XsltSaxonBuilder createXsltBuilder() throws Exception {
final CamelContext ctx = getCamelContext();
final ClassResolver resolver = ctx.getClassResolver();
final Injector injector = ctx.getInjector();
log.debug("{} using schema resource: {}", this, getResourceUri());
final XsltSaxonBuilder xslt = injector.newInstance(XsltSaxonBuilder.class);
TransformerFactory factory = getTransformerFactory();
if (factory == null) {
if (getTransformerFactoryClass() == null) {
// create new saxon factory
factory = new TransformerFactoryImpl();
} else {
// provide the class loader of this component to work in OSGi environments
Class<TransformerFactory> factoryClass = resolver.resolveMandatoryClass(getTransformerFactoryClass(), TransformerFactory.class, XsltSaxonComponent.class.getClassLoader());
log.debug("Using TransformerFactoryClass {}", factoryClass);
factory = injector.newInstance(factoryClass);
}
}
if (factory instanceof TransformerFactoryImpl) {
TransformerFactoryImpl tf = (TransformerFactoryImpl) factory;
XsltSaxonHelper.registerSaxonConfiguration(tf, saxonConfiguration);
XsltSaxonHelper.registerSaxonConfigurationProperties(tf, saxonConfigurationProperties);
XsltSaxonHelper.registerSaxonExtensionFunctions(tf, saxonExtensionFunctions);
}
if (factory != null) {
log.debug("Using TransformerFactory {}", factory);
xslt.setTransformerFactory(factory);
}
if (getResultHandlerFactory() != null) {
xslt.setResultHandlerFactory(getResultHandlerFactory());
}
if (getErrorListener() != null) {
xslt.errorListener(getErrorListener());
}
xslt.setFailOnNullBody(isFailOnNullBody());
xslt.transformerCacheSize(getTransformerCacheSize());
xslt.setUriResolver(getUriResolver());
xslt.setEntityResolver(getEntityResolver());
xslt.setAllowStAX(allowStAX);
xslt.setDeleteOutputFile(isDeleteOutputFile());
configureOutput(xslt, getOutput().name());
// any additional transformer parameters then make a copy to avoid side-effects
if (getParameters() != null) {
Map<String, Object> copy = new HashMap<>(getParameters());
xslt.setParameters(copy);
}
// must load resource first which sets a template and do a stylesheet compilation to catch errors early
loadResource(getResourceUri(), xslt);
return xslt;
}
}