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 */
017 package org.apache.camel.component.xslt;
018
019 import java.io.IOException;
020 import java.net.URL;
021
022 import javax.xml.transform.TransformerConfigurationException;
023
024 import org.apache.camel.Component;
025 import org.apache.camel.Exchange;
026 import org.apache.camel.api.management.ManagedAttribute;
027 import org.apache.camel.api.management.ManagedOperation;
028 import org.apache.camel.api.management.ManagedResource;
029 import org.apache.camel.builder.xml.XsltBuilder;
030 import org.apache.camel.impl.ProcessorEndpoint;
031 import org.apache.camel.util.ResourceHelper;
032 import org.slf4j.Logger;
033 import org.slf4j.LoggerFactory;
034
035 @ManagedResource(description = "Managed XsltEndpoint")
036 public class XsltEndpoint extends ProcessorEndpoint {
037
038 private static final transient Logger LOG = LoggerFactory.getLogger(XsltEndpoint.class);
039
040 private XsltBuilder xslt;
041 private String resourceUri;
042 private boolean cacheStylesheet;
043 private volatile boolean cacheCleared;
044
045 public XsltEndpoint(String endpointUri, Component component, XsltBuilder xslt, String resourceUri,
046 boolean cacheStylesheet) throws Exception {
047 super(endpointUri, component, xslt);
048 this.xslt = xslt;
049 this.resourceUri = resourceUri;
050 this.cacheStylesheet = cacheStylesheet;
051 loadResource(xslt, resourceUri);
052 }
053
054 @ManagedOperation(description = "Clears the cached XSLT stylesheet, forcing to re-load the stylesheet on next request")
055 public void clearCachedStylesheet() {
056 this.cacheCleared = true;
057 }
058
059 @ManagedAttribute(description = "Whether the XSLT stylesheet is cached")
060 public boolean isCacheStylesheet() {
061 return cacheStylesheet;
062 }
063
064 private synchronized void loadResource(XsltBuilder xslt, String resourceUri) throws TransformerConfigurationException, IOException {
065 LOG.trace("{} loading schema resource: {}", this, resourceUri);
066 // prefer to use URL over InputStream as it loads better with http
067 URL url = ResourceHelper.resolveMandatoryResourceAsUrl(getCamelContext().getClassResolver(), resourceUri);
068 xslt.setTransformerURL(url);
069 // now loaded so clear flag
070 cacheCleared = false;
071 }
072
073 public XsltEndpoint findOrCreateEndpoint(String uri, String newResourceUri) {
074 String newUri = uri.replace(resourceUri, newResourceUri);
075 LOG.trace("Getting endpoint with URI: {}", newUri);
076 return getCamelContext().getEndpoint(newUri, XsltEndpoint.class);
077 }
078
079 @Override
080 protected void onExchange(Exchange exchange) throws Exception {
081 String newResourceUri = exchange.getIn().getHeader(XsltConstants.XSLT_RESOURCE_URI, String.class);
082 if (newResourceUri != null) {
083 exchange.getIn().removeHeader(XsltConstants.XSLT_RESOURCE_URI);
084
085 LOG.trace("{} set to {} creating new endpoint to handle exchange", XsltConstants.XSLT_RESOURCE_URI, newResourceUri);
086 XsltEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri);
087 newEndpoint.onExchange(exchange);
088 return;
089 } else {
090 if (!cacheStylesheet || cacheCleared) {
091 loadResource(xslt, resourceUri);
092 }
093 super.onExchange(exchange);
094 }
095 }
096
097 }