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 }