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