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    }