001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.component.xslt; 018 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import javax.xml.transform.URIResolver; 023 024import org.apache.camel.Endpoint; 025import org.apache.camel.builder.xml.XsltUriResolver; 026import org.apache.camel.converter.jaxp.XmlConverter; 027import org.apache.camel.impl.UriEndpointComponent; 028import org.apache.camel.spi.Metadata; 029import org.apache.camel.spi.UriParam; 030import org.apache.camel.util.EndpointHelper; 031import org.apache.camel.util.ResourceHelper; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * The <a href="http://camel.apache.org/xslt.html">XSLT Component</a> is for performing XSLT transformations of messages 037 */ 038public class XsltComponent extends UriEndpointComponent { 039 040 private static final Logger LOG = LoggerFactory.getLogger(XsltComponent.class); 041 042 @Metadata(label = "advanced") 043 private XmlConverter xmlConverter; 044 @Metadata(label = "advanced", description = "To use a custom UriResolver. Should not be used together with the option 'uriResolverFactory'.") 045 private URIResolver uriResolver; 046 @Metadata(label = "advanced", description = "To use a custom UriResolver which depends on a dynamic endpoint resource URI. Should not be used together with the option 'uriResolver'.") 047 private XsltUriResolverFactory uriResolverFactory; 048 @Metadata(defaultValue = "true") 049 @UriParam(label = "advanced") 050 private Object saxonConfiguration; 051 @Metadata(label = "advanced") 052 private Map<String, Object> saxonConfigurationProperties = new HashMap<>(); 053 @UriParam(label = "advanced", javaType = "java.lang.String") 054 private List<Object> saxonExtensionFunctions; 055 private boolean contentCache = true; 056 private boolean saxon; 057 058 public XsltComponent() { 059 super(XsltEndpoint.class); 060 } 061 062 public XmlConverter getXmlConverter() { 063 return xmlConverter; 064 } 065 066 /** 067 * To use a custom implementation of {@link org.apache.camel.converter.jaxp.XmlConverter} 068 */ 069 public void setXmlConverter(XmlConverter xmlConverter) { 070 this.xmlConverter = xmlConverter; 071 } 072 073 074 075 public XsltUriResolverFactory getUriResolverFactory() { 076 return uriResolverFactory; 077 } 078 079 /** 080 * To use a custom javax.xml.transform.URIResolver which depends on a dynamic endpoint resource URI or which is a subclass of {@link XsltUriResolver}. 081 * Do not use in combination with uriResolver. 082 * See also {@link #setUriResolver(URIResolver)}. 083 */ 084 public void setUriResolverFactory(XsltUriResolverFactory uriResolverFactory) { 085 this.uriResolverFactory = uriResolverFactory; 086 } 087 088 public URIResolver getUriResolver() { 089 return uriResolver; 090 } 091 092 /** 093 * To use a custom javax.xml.transform.URIResolver. Do not use in combination with uriResolverFactory. 094 * See also {@link #setUriResolverFactory(XsltUriResolverFactory)}. 095 */ 096 public void setUriResolver(URIResolver uriResolver) { 097 this.uriResolver = uriResolver; 098 } 099 100 public boolean isContentCache() { 101 return contentCache; 102 } 103 104 /** 105 * Cache for the resource content (the stylesheet file) when it is loaded. 106 * If set to false Camel will reload the stylesheet file on each message processing. This is good for development. 107 * A cached stylesheet can be forced to reload at runtime via JMX using the clearCachedStylesheet operation. 108 */ 109 public void setContentCache(boolean contentCache) { 110 this.contentCache = contentCache; 111 } 112 113 public boolean isSaxon() { 114 return saxon; 115 } 116 117 /** 118 * Whether to use Saxon as the transformerFactoryClass. 119 * If enabled then the class net.sf.saxon.TransformerFactoryImpl. You would need to add Saxon to the classpath. 120 */ 121 public void setSaxon(boolean saxon) { 122 this.saxon = saxon; 123 } 124 125 public List<Object> getSaxonExtensionFunctions() { 126 return saxonExtensionFunctions; 127 } 128 129 /** 130 * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. 131 * You would need to add camel-saxon to the classpath. 132 * The function is looked up in the registry, where you can comma to separate multiple values to lookup. 133 */ 134 public void setSaxonExtensionFunctions(List<Object> extensionFunctions) { 135 this.saxonExtensionFunctions = extensionFunctions; 136 } 137 138 /** 139 * Allows you to use a custom net.sf.saxon.lib.ExtensionFunctionDefinition. 140 * You would need to add camel-saxon to the classpath. 141 * The function is looked up in the registry, where you can comma to separate multiple values to lookup. 142 */ 143 public void setSaxonExtensionFunctions(String extensionFunctions) { 144 this.saxonExtensionFunctions = EndpointHelper.resolveReferenceListParameter( 145 getCamelContext(), 146 extensionFunctions, 147 Object.class 148 ); 149 } 150 151 public Object getSaxonConfiguration() { 152 return saxonConfiguration; 153 } 154 155 /** 156 * To use a custom Saxon configuration 157 */ 158 public void setSaxonConfiguration(Object saxonConfiguration) { 159 this.saxonConfiguration = saxonConfiguration; 160 } 161 162 public Map<String, Object> getSaxonConfigurationProperties() { 163 return saxonConfigurationProperties; 164 } 165 166 /** 167 * To set custom Saxon configuration properties 168 */ 169 public void setSaxonConfigurationProperties(Map<String, Object> configurationProperties) { 170 this.saxonConfigurationProperties = configurationProperties; 171 } 172 173 @Override 174 protected Endpoint createEndpoint(String uri, final String remaining, Map<String, Object> parameters) throws Exception { 175 XsltEndpoint endpoint = new XsltEndpoint(uri, this); 176 endpoint.setConverter(getXmlConverter()); 177 endpoint.setContentCache(isContentCache()); 178 endpoint.setSaxon(isSaxon()); 179 endpoint.setSaxonConfiguration(saxonConfiguration); 180 endpoint.setSaxonConfigurationProperties(saxonConfigurationProperties); 181 endpoint.setSaxonExtensionFunctions(saxonExtensionFunctions); 182 183 String resourceUri = remaining; 184 185 // if its a http uri, then append additional parameters as they are part of the uri 186 if (ResourceHelper.isHttpUri(resourceUri)) { 187 resourceUri = ResourceHelper.appendParameters(resourceUri, parameters); 188 } 189 LOG.debug("{} using schema resource: {}", this, resourceUri); 190 endpoint.setResourceUri(resourceUri); 191 192 // lookup custom resolver to use 193 URIResolver resolver = resolveAndRemoveReferenceParameter(parameters, "uriResolver", URIResolver.class); 194 if (resolver == null) { 195 // not in endpoint then use component specific resolver 196 resolver = getUriResolver(); 197 } 198 if (resolver == null) { 199 // lookup custom resolver factory to use 200 XsltUriResolverFactory resolverFactory = resolveAndRemoveReferenceParameter(parameters, "uriResolverFactory", XsltUriResolverFactory.class); 201 if (resolverFactory == null) { 202 // not in endpoint then use component specific resolver factory 203 resolverFactory = getUriResolverFactory(); 204 } 205 if (resolverFactory == null) { 206 // fallback to use the Default URI resolver factory 207 resolverFactory = new DefaultXsltUriResolverFactory(); 208 } 209 210 resolver = resolverFactory.createUriResolver(getCamelContext(), remaining); 211 } 212 endpoint.setUriResolver(resolver); 213 214 setProperties(endpoint, parameters); 215 if (!parameters.isEmpty()) { 216 // additional parameters need to be stored on endpoint as they can be used to configure xslt builder additionally 217 endpoint.setParameters(parameters); 218 } 219 220 return endpoint; 221 } 222 223}