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.model;
018    
019    import java.util.List;
020    import javax.xml.bind.annotation.XmlAccessType;
021    import javax.xml.bind.annotation.XmlAccessorType;
022    import javax.xml.bind.annotation.XmlAttribute;
023    import javax.xml.bind.annotation.XmlRootElement;
024    
025    import org.apache.camel.Endpoint;
026    import org.apache.camel.Predicate;
027    import org.apache.camel.Processor;
028    import org.apache.camel.impl.InterceptSendToEndpoint;
029    import org.apache.camel.processor.InterceptEndpointProcessor;
030    import org.apache.camel.spi.EndpointStrategy;
031    import org.apache.camel.spi.RouteContext;
032    import org.apache.camel.util.EndpointHelper;
033    
034    /**
035     * Represents an XML <interceptToEndpoint/> element
036     *
037     * @version $Revision: 771296 $
038     */
039    @XmlRootElement(name = "interceptToEndpoint")
040    @XmlAccessorType(XmlAccessType.FIELD)
041    public class InterceptSendToEndpointDefinition extends OutputDefinition<ProcessorDefinition> {
042    
043        // TODO: Support lookup endpoint by ref (requires a bit more work)
044    
045        @XmlAttribute(required = true)
046        private String uri;
047        @XmlAttribute(required = false)
048        private Boolean skipSendToOriginalEndpoint = Boolean.FALSE;
049    
050        public InterceptSendToEndpointDefinition() {
051        }
052    
053        public InterceptSendToEndpointDefinition(String uri) {
054            this.uri = uri;
055        }
056    
057        @Override
058        public String toString() {
059            return "InterceptSendToEndpoint[" + uri + " -> " + getOutputs() + "]";
060        }
061    
062        @Override
063        public String getShortName() {
064            return "interceptEndpoint";
065        }
066    
067        @Override
068        public String getLabel() {
069            return "interceptEndpoint";
070        }
071    
072        @Override
073        public Processor createProcessor(RouteContext routeContext) throws Exception {
074            // create the detour
075            final Processor detour = routeContext.createProcessor(this);
076    
077            // register endpoint callback so we can proxy the endpoint
078            routeContext.getCamelContext().addRegisterEndpointCallback(new EndpointStrategy() {
079                public Endpoint registerEndpoint(String uri, Endpoint endpoint) {
080                    // only proxy if the uri is matched
081                    boolean match = getUri() == null || EndpointHelper.matchEndpoint(uri, getUri()); 
082                    if (match) {
083                        // decorate endpoint with our proxy
084                        boolean skip = skipSendToOriginalEndpoint != null ? skipSendToOriginalEndpoint : false;
085                        InterceptSendToEndpoint proxy = new InterceptSendToEndpoint(endpoint, skip);
086                        proxy.setDetour(detour);
087                        return proxy;
088                    } else {
089                        // no proxy so return regular endpoint
090                        return endpoint;
091                    }
092                }
093            });
094    
095    
096            // remove the original intercepted route from the outputs as we do not intercept as the regular interceptor
097            // instead we use the proxy endpoints producer do the triggering. That is we trigger when someone sends
098            // an exchange to the endpoint, see InterceptSendToEndpoint for details.
099            RouteDefinition route = routeContext.getRoute();
100            List<ProcessorDefinition> outputs = route.getOutputs();
101            outputs.remove(this);
102    
103            return new InterceptEndpointProcessor(uri, detour);
104        }
105    
106        /**
107         * Applies this interceptor only if the given predicate is true
108         *
109         * @param predicate  the predicate
110         * @return the builder
111         */
112        public ChoiceDefinition when(Predicate predicate) {
113            return choice().when(predicate);
114        }
115    
116        /**
117         * Skip sending the {@link org.apache.camel.Exchange} to the original intended endpoint
118         *
119         * @return the builder
120         */
121        public InterceptSendToEndpointDefinition skipSendToOriginalEndpoint() {
122            setSkipSendToOriginalEndpoint(Boolean.TRUE);
123            return this;
124        }
125    
126        /**
127         * This method is <b>only</b> for handling some post configuration
128         * that is needed from the Spring DSL side as JAXB does not invoke the fluent
129         * builders, so we need to manually handle this afterwards, and since this is
130         * an interceptor it has to do a bit of magic logic to fixup to handle predicates
131         * with or without proceed/stop set as well.
132         */
133        public void afterPropertiesSet() {
134            // okay the intercept endpoint works a bit differently than the regular interceptors
135            // so we must fix the route definiton yet again
136    
137            if (getOutputs().size() == 0) {
138                // no outputs
139                return;
140            }
141    
142            ProcessorDefinition first = getOutputs().get(0);
143            if (first instanceof WhenDefinition) {
144                WhenDefinition when = (WhenDefinition) first;
145                // move this outputs to the when, expect the first one
146                // as the first one is the interceptor itself
147                for (int i = 1; i < outputs.size(); i++) {
148                    ProcessorDefinition out = outputs.get(i);
149                    when.addOutput(out);
150                }
151                // remove the moved from the original output, by just keeping the first one
152                ProcessorDefinition keep = outputs.get(0);
153                clearOutput();
154                outputs.add(keep);
155            }
156        }
157    
158        public Boolean getSkipSendToOriginalEndpoint() {
159            return skipSendToOriginalEndpoint;
160        }
161    
162        public void setSkipSendToOriginalEndpoint(Boolean skipSendToOriginalEndpoint) {
163            this.skipSendToOriginalEndpoint = skipSendToOriginalEndpoint;
164        }
165    
166        public String getUri() {
167            return uri;
168        }
169    
170        public void setUri(String uri) {
171            this.uri = uri;
172        }
173    }