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 java.util.concurrent.ExecutorService; 022 023import javax.xml.bind.annotation.XmlAccessType; 024import javax.xml.bind.annotation.XmlAccessorType; 025import javax.xml.bind.annotation.XmlAttribute; 026import javax.xml.bind.annotation.XmlElement; 027import javax.xml.bind.annotation.XmlElementRef; 028import javax.xml.bind.annotation.XmlRootElement; 029import javax.xml.bind.annotation.XmlTransient; 030 031import org.apache.camel.ExchangePattern; 032import org.apache.camel.Expression; 033import org.apache.camel.Processor; 034import org.apache.camel.spi.Metadata; 035 036/** 037 * Routes a copy of a message (or creates a new message) to a secondary 038 * destination while continue routing the original message. 039 */ 040@Metadata(label = "eip,endpoint,routing") 041@XmlRootElement(name = "wireTap") 042@XmlAccessorType(XmlAccessType.FIELD) 043public class WireTapDefinition<Type extends ProcessorDefinition<Type>> extends ToDynamicDefinition implements ExecutorServiceAwareDefinition<WireTapDefinition<Type>> { 044 @XmlTransient 045 private Processor newExchangeProcessor; 046 @XmlAttribute(name = "processorRef") 047 private String newExchangeProcessorRef; 048 @XmlElement(name = "body") 049 private ExpressionSubElementDefinition newExchangeExpression; 050 @XmlElementRef 051 private List<SetHeaderDefinition> headers = new ArrayList<>(); 052 @XmlTransient 053 private ExecutorService executorService; 054 @XmlAttribute 055 private String executorServiceRef; 056 @XmlAttribute 057 @Metadata(defaultValue = "true", javaType = "java.lang.Boolean") 058 private String copy; 059 @XmlAttribute 060 @Metadata(defaultValue = "true", javaType = "java.lang.Boolean") 061 private String dynamicUri; 062 @XmlAttribute 063 private String onPrepareRef; 064 @XmlTransient 065 private Processor onPrepare; 066 067 public WireTapDefinition() { 068 } 069 070 @Override 071 public String getPattern() { 072 return ExchangePattern.InOnly.name(); 073 } 074 075 @Override 076 public String toString() { 077 return "WireTap[" + getUri() + "]"; 078 } 079 080 @Override 081 public String getShortName() { 082 return "wireTap"; 083 } 084 085 @Override 086 public String getLabel() { 087 return "wireTap[" + getUri() + "]"; 088 } 089 090 @Override 091 @SuppressWarnings("unchecked") 092 public Type end() { 093 // allow end() to return to previous type so you can continue in the DSL 094 return (Type)super.end(); 095 } 096 097 @Override 098 public void addOutput(ProcessorDefinition<?> output) { 099 // add outputs on parent as this wiretap does not support outputs 100 getParent().addOutput(output); 101 } 102 103 // Fluent API 104 // ------------------------------------------------------------------------- 105 106 /** 107 * Uses a custom thread pool 108 * 109 * @param executorService a custom {@link ExecutorService} to use as thread 110 * pool for sending tapped exchanges 111 * @return the builder 112 */ 113 @Override 114 public WireTapDefinition<Type> executorService(ExecutorService executorService) { 115 setExecutorService(executorService); 116 return this; 117 } 118 119 /** 120 * Uses a custom thread pool 121 * 122 * @param executorServiceRef reference to lookup a custom 123 * {@link ExecutorService} to use as thread pool for sending 124 * tapped exchanges 125 * @return the builder 126 */ 127 @Override 128 public WireTapDefinition<Type> executorServiceRef(String executorServiceRef) { 129 setExecutorServiceRef(executorServiceRef); 130 return this; 131 } 132 133 /** 134 * Uses a copy of the original exchange 135 * 136 * @return the builder 137 */ 138 public WireTapDefinition<Type> copy() { 139 return copy(true); 140 } 141 142 /** 143 * Uses a copy of the original exchange 144 * 145 * @param copy if it is true camel will copy the original exchange, if it is 146 * false camel will not copy the original exchange 147 * @return the builder 148 */ 149 public WireTapDefinition<Type> copy(boolean copy) { 150 return copy(Boolean.toString(copy)); 151 } 152 153 /** 154 * Uses a copy of the original exchange 155 * 156 * @param copy if it is true camel will copy the original exchange, if it is 157 * false camel will not copy the original exchange 158 * @return the builder 159 */ 160 public WireTapDefinition<Type> copy(String copy) { 161 setCopy(copy); 162 return this; 163 } 164 165 /** 166 * Whether the uri is dynamic or static. If the uri is dynamic then the 167 * simple language is used to evaluate a dynamic uri to use as the wire-tap 168 * destination, for each incoming message. This works similar to how the 169 * <tt>toD</tt> EIP pattern works. If static then the uri is used as-is as 170 * the wire-tap destination. 171 * 172 * @param dynamicUri whether to use dynamic or static uris 173 * @return the builder 174 */ 175 public WireTapDefinition<Type> dynamicUri(boolean dynamicUri) { 176 return dynamicUri(Boolean.toString(dynamicUri)); 177 } 178 179 /** 180 * Whether the uri is dynamic or static. If the uri is dynamic then the 181 * simple language is used to evaluate a dynamic uri to use as the wire-tap 182 * destination, for each incoming message. This works similar to how the 183 * <tt>toD</tt> EIP pattern works. If static then the uri is used as-is as 184 * the wire-tap destination. 185 * 186 * @param dynamicUri whether to use dynamic or static uris 187 * @return the builder 188 */ 189 public WireTapDefinition<Type> dynamicUri(String dynamicUri) { 190 setDynamicUri(dynamicUri); 191 return this; 192 } 193 194 /** 195 * Sends a <i>new</i> Exchange, instead of tapping an existing, using 196 * {@link ExchangePattern#InOnly} 197 * 198 * @param expression expression that creates the new body to send 199 * @return the builder 200 * @see #newExchangeHeader(String, org.apache.camel.Expression) 201 */ 202 public WireTapDefinition<Type> newExchangeBody(Expression expression) { 203 setNewExchangeExpression(new ExpressionSubElementDefinition(expression)); 204 return this; 205 } 206 207 /** 208 * Sends a <i>new</i> Exchange, instead of tapping an existing, using 209 * {@link ExchangePattern#InOnly} 210 * 211 * @param ref reference to the {@link Processor} to lookup in the 212 * {@link org.apache.camel.spi.Registry} to be used for preparing 213 * the new exchange to send 214 * @return the builder 215 */ 216 public WireTapDefinition<Type> newExchangeRef(String ref) { 217 setNewExchangeProcessorRef(ref); 218 return this; 219 } 220 221 /** 222 * Sends a <i>new</i> Exchange, instead of tapping an existing, using 223 * {@link ExchangePattern#InOnly} 224 * 225 * @param processor processor preparing the new exchange to send 226 * @return the builder 227 * @see #newExchangeHeader(String, org.apache.camel.Expression) 228 */ 229 public WireTapDefinition<Type> newExchange(Processor processor) { 230 setNewExchangeProcessor(processor); 231 return this; 232 } 233 234 /** 235 * Sets a header on the <i>new</i> Exchange, instead of tapping an existing, 236 * using {@link ExchangePattern#InOnly}. 237 * <p/> 238 * Use this together with the 239 * {@link #newExchangeBody(org.apache.camel.Expression)} or 240 * {@link #newExchange(org.apache.camel.Processor)} methods. 241 * 242 * @param headerName the header name 243 * @param expression the expression setting the header value 244 * @return the builder 245 */ 246 public WireTapDefinition<Type> newExchangeHeader(String headerName, Expression expression) { 247 headers.add(new SetHeaderDefinition(headerName, expression)); 248 return this; 249 } 250 251 /** 252 * Uses the {@link Processor} when preparing the 253 * {@link org.apache.camel.Exchange} to be send. This can be used to 254 * deep-clone messages that should be send, or any custom logic needed 255 * before the exchange is send. 256 * 257 * @param onPrepare the processor 258 * @return the builder 259 */ 260 public WireTapDefinition<Type> onPrepare(Processor onPrepare) { 261 setOnPrepare(onPrepare); 262 return this; 263 } 264 265 /** 266 * Uses the {@link Processor} when preparing the 267 * {@link org.apache.camel.Exchange} to be send. This can be used to 268 * deep-clone messages that should be send, or any custom logic needed 269 * before the exchange is send. 270 * 271 * @param onPrepareRef reference to the processor to lookup in the 272 * {@link org.apache.camel.spi.Registry} 273 * @return the builder 274 */ 275 public WireTapDefinition<Type> onPrepareRef(String onPrepareRef) { 276 setOnPrepareRef(onPrepareRef); 277 return this; 278 } 279 280 /** 281 * Sets the maximum size used by the 282 * {@link org.apache.camel.spi.ProducerCache} which is used to cache and 283 * reuse producers, when uris are reused. 284 * 285 * Beware that when using dynamic endpoints then it affects how well the cache can be utilized. 286 * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which 287 * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped 288 * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints 289 * are stored in memory in the caches. 290 * 291 * However if there are a high degree of dynamic endpoints that have been used before, then it can 292 * benefit to use the cache to reuse both producers and endpoints and therefore the cache size 293 * can be set accordingly or rely on the default size (1000). 294 * 295 * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size 296 * can help reduce memory usage to avoid storing too many non frequent used producers. 297 * 298 * @param cacheSize the cache size, use <tt>0</tt> for default cache size, 299 * or <tt>-1</tt> to turn cache off. 300 * @return the builder 301 */ 302 @Override 303 public WireTapDefinition<Type> cacheSize(int cacheSize) { 304 return cacheSize(Integer.toString(cacheSize)); 305 } 306 307 /** 308 * Sets the maximum size used by the 309 * {@link org.apache.camel.spi.ProducerCache} which is used to cache and 310 * reuse producers, when uris are reused. 311 * 312 * Beware that when using dynamic endpoints then it affects how well the cache can be utilized. 313 * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which 314 * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped 315 * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints 316 * are stored in memory in the caches. 317 * 318 * However if there are a high degree of dynamic endpoints that have been used before, then it can 319 * benefit to use the cache to reuse both producers and endpoints and therefore the cache size 320 * can be set accordingly or rely on the default size (1000). 321 * 322 * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size 323 * can help reduce memory usage to avoid storing too many non frequent used producers. 324 * 325 * @param cacheSize the cache size, use <tt>0</tt> for default cache size, 326 * or <tt>-1</tt> to turn cache off. 327 * @return the builder 328 */ 329 @Override 330 public WireTapDefinition<Type> cacheSize(String cacheSize) { 331 setCacheSize(cacheSize); 332 return this; 333 } 334 335 /** 336 * Ignore the invalidate endpoint exception when try to create a producer 337 * with that endpoint 338 * 339 * @return the builder 340 */ 341 public WireTapDefinition<Type> ignoreInvalidEndpoint() { 342 setIgnoreInvalidEndpoint(Boolean.toString(true)); 343 return this; 344 } 345 346 // Properties 347 // ------------------------------------------------------------------------- 348 349 @Override 350 public String getUri() { 351 return super.getUri(); 352 } 353 354 /** 355 * The uri of the endpoint to wiretap to. The uri can be dynamic computed 356 * using the {@link org.apache.camel.language.simple.SimpleLanguage} 357 * expression. 358 */ 359 @Override 360 public void setUri(String uri) { 361 super.setUri(uri); 362 } 363 364 public Processor getNewExchangeProcessor() { 365 return newExchangeProcessor; 366 } 367 368 /** 369 * To use a Processor for creating a new body as the message to use for wire 370 * tapping 371 */ 372 public void setNewExchangeProcessor(Processor processor) { 373 this.newExchangeProcessor = processor; 374 } 375 376 public String getNewExchangeProcessorRef() { 377 return newExchangeProcessorRef; 378 } 379 380 /** 381 * Reference to a Processor to use for creating a new body as the message to 382 * use for wire tapping 383 */ 384 public void setNewExchangeProcessorRef(String ref) { 385 this.newExchangeProcessorRef = ref; 386 } 387 388 public ExpressionSubElementDefinition getNewExchangeExpression() { 389 return newExchangeExpression; 390 } 391 392 /** 393 * Uses the expression for creating a new body as the message to use for 394 * wire tapping 395 */ 396 public void setNewExchangeExpression(ExpressionSubElementDefinition newExchangeExpression) { 397 this.newExchangeExpression = newExchangeExpression; 398 } 399 400 @Override 401 public ExecutorService getExecutorService() { 402 return executorService; 403 } 404 405 @Override 406 public void setExecutorService(ExecutorService executorService) { 407 this.executorService = executorService; 408 } 409 410 @Override 411 public String getExecutorServiceRef() { 412 return executorServiceRef; 413 } 414 415 @Override 416 public void setExecutorServiceRef(String executorServiceRef) { 417 this.executorServiceRef = executorServiceRef; 418 } 419 420 public String getCopy() { 421 return copy; 422 } 423 424 public void setCopy(String copy) { 425 this.copy = copy; 426 } 427 428 public String getDynamicUri() { 429 return dynamicUri; 430 } 431 432 public void setDynamicUri(String dynamicUri) { 433 this.dynamicUri = dynamicUri; 434 } 435 436 public String getOnPrepareRef() { 437 return onPrepareRef; 438 } 439 440 public void setOnPrepareRef(String onPrepareRef) { 441 this.onPrepareRef = onPrepareRef; 442 } 443 444 public Processor getOnPrepare() { 445 return onPrepare; 446 } 447 448 public void setOnPrepare(Processor onPrepare) { 449 this.onPrepare = onPrepare; 450 } 451 452 public List<SetHeaderDefinition> getHeaders() { 453 return headers; 454 } 455 456 public void setHeaders(List<SetHeaderDefinition> headers) { 457 this.headers = headers; 458 } 459 460}