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.reifier;
018
019import java.util.List;
020
021import org.apache.camel.CamelContext;
022import org.apache.camel.Endpoint;
023import org.apache.camel.ExtendedCamelContext;
024import org.apache.camel.Processor;
025import org.apache.camel.impl.engine.DefaultInterceptSendToEndpoint;
026import org.apache.camel.model.InterceptSendToEndpointDefinition;
027import org.apache.camel.model.ProcessorDefinition;
028import org.apache.camel.model.RouteDefinition;
029import org.apache.camel.model.ToDefinition;
030import org.apache.camel.processor.InterceptEndpointProcessor;
031import org.apache.camel.spi.EndpointStrategy;
032import org.apache.camel.spi.RouteContext;
033import org.apache.camel.support.EndpointHelper;
034import org.apache.camel.util.URISupport;
035
036public class InterceptSendToEndpointReifier extends ProcessorReifier<InterceptSendToEndpointDefinition> {
037
038    public InterceptSendToEndpointReifier(ProcessorDefinition<?> definition) {
039        super((InterceptSendToEndpointDefinition)definition);
040    }
041
042    @Override
043    public Processor createProcessor(final RouteContext routeContext) throws Exception {
044        // create the before
045        final Processor before = this.createChildProcessor(routeContext, true);
046        // create the after
047        Processor afterProcessor = null;
048        if (definition.getAfterUri() != null) {
049            ToDefinition to = new ToDefinition(definition.getAfterUri());
050            // at first use custom factory
051            if (routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory() != null) {
052                afterProcessor = routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory().createProcessor(routeContext, to);
053            }
054            // fallback to default implementation if factory did not create the
055            // processor
056            if (afterProcessor == null) {
057                afterProcessor = reifier(to).createProcessor(routeContext);
058            }
059        }
060        final Processor after = afterProcessor;
061        final String matchURI = definition.getUri();
062
063        // register endpoint callback so we can proxy the endpoint
064        routeContext.getCamelContext().adapt(ExtendedCamelContext.class).registerEndpointCallback(new EndpointStrategy() {
065            public Endpoint registerEndpoint(String uri, Endpoint endpoint) {
066                if (endpoint instanceof DefaultInterceptSendToEndpoint) {
067                    // endpoint already decorated
068                    return endpoint;
069                } else if (matchURI == null || matchPattern(routeContext.getCamelContext(), uri, matchURI)) {
070                    // only proxy if the uri is matched decorate endpoint with
071                    // our proxy
072                    // should be false by default
073                    boolean skip = definition.getSkipSendToOriginalEndpoint() != null && definition.getSkipSendToOriginalEndpoint();
074                    DefaultInterceptSendToEndpoint proxy = new DefaultInterceptSendToEndpoint(endpoint, skip);
075                    proxy.setBefore(before);
076                    proxy.setAfter(after);
077                    return proxy;
078                } else {
079                    // no proxy so return regular endpoint
080                    return endpoint;
081                }
082            }
083        });
084
085        // remove the original intercepted route from the outputs as we do not
086        // intercept as the regular interceptor
087        // instead we use the proxy endpoints producer do the triggering. That
088        // is we trigger when someone sends
089        // an exchange to the endpoint, see InterceptSendToEndpoint for details.
090        RouteDefinition route = (RouteDefinition)routeContext.getRoute();
091        List<ProcessorDefinition<?>> outputs = route.getOutputs();
092        outputs.remove(this);
093
094        return new InterceptEndpointProcessor(matchURI, before);
095    }
096
097    /**
098     * Does the uri match the pattern.
099     *
100     * @param camelContext the CamelContext
101     * @param uri the uri
102     * @param pattern the pattern, which can be an endpoint uri as well
103     * @return <tt>true</tt> if matched and we should intercept, <tt>false</tt>
104     *         if not matched, and not intercept.
105     */
106    protected boolean matchPattern(CamelContext camelContext, String uri, String pattern) {
107        // match using the pattern as-is
108        boolean match = EndpointHelper.matchEndpoint(camelContext, uri, pattern);
109        if (!match) {
110            try {
111                // the pattern could be an uri, so we need to normalize it
112                // before matching again
113                pattern = URISupport.normalizeUri(pattern);
114                match = EndpointHelper.matchEndpoint(camelContext, uri, pattern);
115            } catch (Exception e) {
116                // ignore
117            }
118        }
119        return match;
120    }
121
122}