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.ArrayList; 020 import java.util.List; 021 import javax.xml.bind.annotation.XmlAccessType; 022 import javax.xml.bind.annotation.XmlAccessorType; 023 import javax.xml.bind.annotation.XmlRootElement; 024 import javax.xml.bind.annotation.XmlTransient; 025 026 import org.apache.camel.Predicate; 027 import org.apache.camel.Processor; 028 import org.apache.camel.processor.Pipeline; 029 import org.apache.camel.spi.InterceptStrategy; 030 import org.apache.camel.spi.RouteContext; 031 032 /** 033 * Represents an XML <intercept/> element 034 * 035 * @version $Revision: 788663 $ 036 */ 037 @XmlRootElement(name = "intercept") 038 @XmlAccessorType(XmlAccessType.FIELD) 039 public class InterceptDefinition extends OutputDefinition<ProcessorDefinition> { 040 041 // TODO: support stop later (its a bit hard as it needs to break entire processing of route) 042 043 @XmlTransient 044 protected Processor output; 045 046 @XmlTransient 047 protected final List<Processor> intercepted = new ArrayList<Processor>(); 048 049 public InterceptDefinition() { 050 } 051 052 @Override 053 public String toString() { 054 return "Intercept[" + getOutputs() + "]"; 055 } 056 057 @Override 058 public String getShortName() { 059 return "intercept"; 060 } 061 062 @Override 063 public String getLabel() { 064 return "intercept"; 065 } 066 067 @Override 068 public Processor createProcessor(final RouteContext routeContext) throws Exception { 069 // create the output processor 070 output = createOutputsProcessor(routeContext); 071 072 // add the output as a intercept strategy to the route context so its invoked on each processing step 073 routeContext.getInterceptStrategies().add(new InterceptStrategy() { 074 private Processor interceptedTarget; 075 076 public Processor wrapProcessorInInterceptors(ProcessorDefinition processorDefinition, Processor target, Processor nextTarget) throws Exception { 077 // prefer next target over taget as next target is the real target 078 interceptedTarget = nextTarget != null ? nextTarget : target; 079 080 // remember the target that was intercepted 081 intercepted.add(interceptedTarget); 082 083 if (interceptedTarget != null) { 084 // wrap in a pipeline so we continue routing to the next 085 List<Processor> list = new ArrayList<Processor>(2); 086 list.add(output); 087 list.add(interceptedTarget); 088 return new Pipeline(list); 089 } else { 090 return output; 091 } 092 } 093 094 @Override 095 public String toString() { 096 return "intercept[" + (interceptedTarget != null ? interceptedTarget : output) + "]"; 097 } 098 }); 099 100 // remove me from the route so I am not invoked in a regular route path 101 routeContext.getRoute().getOutputs().remove(this); 102 // and return no processor to invoke next from me 103 return null; 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 * This method is <b>only</b> for handling some post configuration 118 * that is needed from the Spring DSL side as JAXB does not invoke the fluent 119 * builders, so we need to manually handle this afterwards, and since this is 120 * an interceptor it has to do a bit of magic logic to fixup to handle predicates 121 * with or without proceed/stop set as well. 122 */ 123 public void afterPropertiesSet() { 124 if (getOutputs().size() == 0) { 125 // no outputs 126 return; 127 } 128 129 ProcessorDefinition first = getOutputs().get(0); 130 if (first instanceof WhenDefinition) { 131 WhenDefinition when = (WhenDefinition) first; 132 // move this outputs to the when, expect the first one 133 // as the first one is the interceptor itself 134 for (int i = 1; i < outputs.size(); i++) { 135 ProcessorDefinition out = outputs.get(i); 136 when.addOutput(out); 137 } 138 // remove the moved from the original output, by just keeping the first one 139 ProcessorDefinition keep = outputs.get(0); 140 clearOutput(); 141 outputs.add(keep); 142 } 143 } 144 145 public Processor getInterceptedProcessor(int index) { 146 // avoid out of bounds 147 if (index <= intercepted.size() - 1) { 148 return intercepted.get(index); 149 } else { 150 return null; 151 } 152 } 153 154 }