content: /*
   * 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;
  
  import java.util.Map;
  
  import javax.xml.transform.URIResolver;
  
  import org.apache.camel.Endpoint;
  import org.apache.camel.spi.Metadata;
  import org.apache.camel.spi.annotations.Component;
  import org.apache.camel.support.DefaultComponent;
  import org.apache.camel.support.ResourceHelper;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * The <a href="http://camel.apache.org/xslt.html">XSLT Component</a> is for performing XSLT transformations of messages
   */
  @Component("xslt")
  public class XsltComponent extends DefaultComponent {
  
      private static final Logger LOG = LoggerFactory.getLogger(XsltComponent.class);
  
      @Metadata(label = "advanced")
      private URIResolver uriResolver;
      @Metadata(label = "advanced")
      private XsltUriResolverFactory uriResolverFactory;
      @Metadata
      private boolean allowTemplateFromHeader;
      @Metadata(defaultValue = "true")
      private boolean contentCache = true;
      @Metadata(label = "advanced")
      private TransformerFactoryConfigurationStrategy transformerFactoryConfigurationStrategy;
      @Metadata(label = "advanced")
      private String transformerFactoryClass;
  
      public XsltComponent() {
      }
  
      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 isAllowTemplateFromHeader() {
          return allowTemplateFromHeader;
      }
  
      /**
       * Whether to allow to use resource template from header or not (default false).
       *
       * Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential
       * security vulnerability if the header is coming from a malicious user, so use this with care.
       */
      public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) {
          this.allowTemplateFromHeader = allowTemplateFromHeader;
      }
  
      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 TransformerFactoryConfigurationStrategy getTransformerFactoryConfigurationStrategy() {
          return transformerFactoryConfigurationStrategy;
      }
  
      /**
       * A configuration strategy to apply on freshly created instances of TransformerFactory.
       */
      public void setTransformerFactoryConfigurationStrategy(
              TransformerFactoryConfigurationStrategy transformerFactoryConfigurationStrategy) {
          this.transformerFactoryConfigurationStrategy = transformerFactoryConfigurationStrategy;
      }
  
      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;
      }
  
      @Override
      protected Endpoint createEndpoint(String uri, final String remaining, Map<String, Object> parameters) throws Exception {
          XsltEndpoint endpoint = createXsltEndpoint(uri);
          configureEndpoint(endpoint, remaining, parameters);
  
          return endpoint;
      }
  
      protected XsltEndpoint createXsltEndpoint(String uri) {
          return new XsltEndpoint(uri, this);
      }
  
      protected void configureEndpoint(Endpoint endpoint, final String remaining, Map<String, Object> parameters)
              throws Exception {
          XsltEndpoint xslt = (XsltEndpoint) endpoint;
          xslt.setContentCache(isContentCache());
          xslt.setAllowTemplateFromHeader(isAllowTemplateFromHeader());
  
          // 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);
          }
          xslt.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);
          xslt.setResourceUri(resourceUri);
  
          if (!parameters.isEmpty()) {
              // additional parameters need to be stored on endpoint as they can be used to configure xslt builder additionally
              xslt.setParameters(parameters);
          }
      }
  }
  