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