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 }