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.Collections; 020import java.util.List; 021 022import javax.xml.bind.annotation.XmlAccessType; 023import javax.xml.bind.annotation.XmlAccessorType; 024import javax.xml.bind.annotation.XmlAttribute; 025import javax.xml.bind.annotation.XmlRootElement; 026 027import org.apache.camel.AsyncProcessor; 028import org.apache.camel.ErrorHandlerFactory; 029import org.apache.camel.Expression; 030import org.apache.camel.Processor; 031import org.apache.camel.model.language.ExpressionDefinition; 032import org.apache.camel.model.language.HeaderExpression; 033import org.apache.camel.processor.RoutingSlip; 034import org.apache.camel.spi.Metadata; 035import org.apache.camel.spi.RouteContext; 036 037/** 038 * Routes a message through a series of steps that are pre-determined (the slip) 039 */ 040@Metadata(label = "eip,endpoint,routing") 041@XmlRootElement(name = "routingSlip") 042@XmlAccessorType(XmlAccessType.FIELD) 043public class RoutingSlipDefinition<Type extends ProcessorDefinition<Type>> extends NoOutputExpressionNode { 044 public static final String DEFAULT_DELIMITER = ","; 045 046 @XmlAttribute @Metadata(defaultValue = ",") 047 private String uriDelimiter; 048 @XmlAttribute 049 private Boolean ignoreInvalidEndpoints; 050 @XmlAttribute 051 private Integer cacheSize; 052 053 public RoutingSlipDefinition() { 054 this((String)null, DEFAULT_DELIMITER); 055 } 056 057 public RoutingSlipDefinition(String headerName) { 058 this(headerName, DEFAULT_DELIMITER); 059 } 060 061 public RoutingSlipDefinition(String headerName, String uriDelimiter) { 062 super(new HeaderExpression(headerName)); 063 setUriDelimiter(uriDelimiter); 064 } 065 066 public RoutingSlipDefinition(Expression expression, String uriDelimiter) { 067 super(expression); 068 setUriDelimiter(uriDelimiter); 069 } 070 071 public RoutingSlipDefinition(Expression expression) { 072 this(expression, DEFAULT_DELIMITER); 073 } 074 075 @Override 076 public String toString() { 077 return "RoutingSlip[" + getExpression() + "]"; 078 } 079 080 @Override 081 public String getShortName() { 082 return "routingSlip"; 083 } 084 085 @Override 086 public String getLabel() { 087 return "routingSlip[" + getExpression() + "]"; 088 } 089 090 @Override 091 public Processor createProcessor(RouteContext routeContext) throws Exception { 092 Expression expression = getExpression().createExpression(routeContext); 093 String delimiter = getUriDelimiter() != null ? getUriDelimiter() : DEFAULT_DELIMITER; 094 095 RoutingSlip routingSlip = new RoutingSlip(routeContext.getCamelContext(), expression, delimiter); 096 if (getIgnoreInvalidEndpoints() != null) { 097 routingSlip.setIgnoreInvalidEndpoints(getIgnoreInvalidEndpoints()); 098 } 099 if (getCacheSize() != null) { 100 routingSlip.setCacheSize(getCacheSize()); 101 } 102 103 // and wrap this in an error handler 104 ErrorHandlerFactory builder = routeContext.getRoute().getErrorHandlerBuilder(); 105 // create error handler (create error handler directly to keep it light weight, 106 // instead of using ProcessorDefinition.wrapInErrorHandler) 107 AsyncProcessor errorHandler = (AsyncProcessor) builder.createErrorHandler(routeContext, routingSlip.newRoutingSlipProcessorForErrorHandler()); 108 routingSlip.setErrorHandler(errorHandler); 109 110 return routingSlip; 111 } 112 113 @Override 114 public List<ProcessorDefinition<?>> getOutputs() { 115 return Collections.emptyList(); 116 } 117 118 /** 119 * Expression to define the routing slip, which defines which endpoints to route the message in a pipeline style. 120 * Notice the expression is evaluated once, if you want a more dynamic style, then the dynamic router eip is a better choice. 121 */ 122 @Override 123 public void setExpression(ExpressionDefinition expression) { 124 // override to include javadoc what the expression is used for 125 super.setExpression(expression); 126 } 127 128 public void setUriDelimiter(String uriDelimiter) { 129 this.uriDelimiter = uriDelimiter; 130 } 131 132 public String getUriDelimiter() { 133 return uriDelimiter; 134 } 135 136 public void setIgnoreInvalidEndpoints(Boolean ignoreInvalidEndpoints) { 137 this.ignoreInvalidEndpoints = ignoreInvalidEndpoints; 138 } 139 140 public Boolean getIgnoreInvalidEndpoints() { 141 return ignoreInvalidEndpoints; 142 } 143 144 public Integer getCacheSize() { 145 return cacheSize; 146 } 147 148 public void setCacheSize(Integer cacheSize) { 149 this.cacheSize = cacheSize; 150 } 151 152 // Fluent API 153 // ------------------------------------------------------------------------- 154 155 @Override 156 @SuppressWarnings("unchecked") 157 public Type end() { 158 // allow end() to return to previous type so you can continue in the DSL 159 return (Type) super.end(); 160 } 161 162 /** 163 * Ignore the invalidate endpoint exception when try to create a producer with that endpoint 164 * 165 * @return the builder 166 */ 167 public RoutingSlipDefinition<Type> ignoreInvalidEndpoints() { 168 setIgnoreInvalidEndpoints(true); 169 return this; 170 } 171 172 /** 173 * Sets the uri delimiter to use 174 * 175 * @param uriDelimiter the delimiter 176 * @return the builder 177 */ 178 public RoutingSlipDefinition<Type> uriDelimiter(String uriDelimiter) { 179 setUriDelimiter(uriDelimiter); 180 return this; 181 } 182 183 /** 184 * Sets the maximum size used by the {@link org.apache.camel.impl.ProducerCache} which is used 185 * to cache and reuse producers when using this routing slip, when uris are reused. 186 * 187 * @param cacheSize the cache size, use <tt>0</tt> for default cache size, or <tt>-1</tt> to turn cache off. 188 * @return the builder 189 */ 190 public RoutingSlipDefinition<Type> cacheSize(int cacheSize) { 191 setCacheSize(cacheSize); 192 return this; 193 } 194 195}