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.Arrays; 021 import java.util.Collection; 022 import java.util.Collections; 023 import java.util.HashSet; 024 import java.util.LinkedList; 025 import java.util.List; 026 import java.util.Set; 027 import java.util.concurrent.ThreadPoolExecutor; 028 029 import javax.xml.bind.annotation.XmlAccessType; 030 import javax.xml.bind.annotation.XmlAccessorType; 031 import javax.xml.bind.annotation.XmlAttribute; 032 import javax.xml.bind.annotation.XmlTransient; 033 034 import org.apache.camel.CamelContext; 035 import org.apache.camel.CamelException; 036 import org.apache.camel.Endpoint; 037 import org.apache.camel.Exchange; 038 import org.apache.camel.Expression; 039 import org.apache.camel.Predicate; 040 import org.apache.camel.Processor; 041 import org.apache.camel.Route; 042 import org.apache.camel.builder.DataFormatClause; 043 import org.apache.camel.builder.DeadLetterChannelBuilder; 044 import org.apache.camel.builder.ErrorHandlerBuilder; 045 import org.apache.camel.builder.ErrorHandlerBuilderRef; 046 import org.apache.camel.builder.ExpressionClause; 047 import org.apache.camel.builder.NoErrorHandlerBuilder; 048 import org.apache.camel.builder.ProcessorBuilder; 049 import org.apache.camel.impl.DefaultCamelContext; 050 import org.apache.camel.model.dataformat.DataFormatType; 051 import org.apache.camel.model.language.ConstantExpression; 052 import org.apache.camel.model.language.ExpressionType; 053 import org.apache.camel.model.language.LanguageExpression; 054 import org.apache.camel.processor.ConvertBodyProcessor; 055 import org.apache.camel.processor.DelegateProcessor; 056 import org.apache.camel.processor.Pipeline; 057 import org.apache.camel.processor.aggregate.AggregationCollection; 058 import org.apache.camel.processor.aggregate.AggregationStrategy; 059 import org.apache.camel.processor.idempotent.MessageIdRepository; 060 import org.apache.camel.spi.DataFormat; 061 import org.apache.camel.spi.ErrorHandlerWrappingStrategy; 062 import org.apache.camel.spi.InterceptStrategy; 063 import org.apache.camel.spi.Policy; 064 import org.apache.camel.spi.RouteContext; 065 import org.apache.commons.logging.Log; 066 import org.apache.commons.logging.LogFactory; 067 068 /** 069 * Base class for processor types that most XML types extend. 070 * 071 * @version $Revision: 61170 $ 072 */ 073 @XmlAccessorType(XmlAccessType.PROPERTY) 074 public abstract class ProcessorType<Type extends ProcessorType> extends OptionalIdentifiedType<Type> implements Block { 075 public static final String DEFAULT_TRACE_CATEGORY = "org.apache.camel.TRACE"; 076 private static final transient Log LOG = LogFactory.getLog(ProcessorType.class); 077 private ErrorHandlerBuilder errorHandlerBuilder; 078 private Boolean inheritErrorHandlerFlag; 079 private NodeFactory nodeFactory; 080 private LinkedList<Block> blocks = new LinkedList<Block>(); 081 private ProcessorType<? extends ProcessorType> parent; 082 private List<InterceptorType> interceptors = new ArrayList<InterceptorType>(); 083 private String errorHandlerRef; 084 085 // else to use an optional attribute in JAXB2 086 public abstract List<ProcessorType<?>> getOutputs(); 087 088 089 public Processor createProcessor(RouteContext routeContext) throws Exception { 090 throw new UnsupportedOperationException("Not implemented yet for class: " + getClass().getName()); 091 } 092 093 public Processor createOutputsProcessor(RouteContext routeContext) throws Exception { 094 Collection<ProcessorType<?>> outputs = getOutputs(); 095 return createOutputsProcessor(routeContext, outputs); 096 } 097 098 public void addRoutes(RouteContext routeContext, Collection<Route> routes) throws Exception { 099 Processor processor = makeProcessor(routeContext); 100 if (!routeContext.isRouteAdded()) { 101 routeContext.addEventDrivenProcessor(processor); 102 } 103 } 104 105 /** 106 * Wraps the child processor in whatever necessary interceptors and error 107 * handlers 108 */ 109 public Processor wrapProcessor(RouteContext routeContext, Processor processor) throws Exception { 110 processor = wrapProcessorInInterceptors(routeContext, processor); 111 return wrapInErrorHandler(routeContext, processor); 112 } 113 114 // Fluent API 115 // ------------------------------------------------------------------------- 116 117 /** 118 * Sends the exchange to the given endpoint URI 119 */ 120 public Type to(String uri) { 121 addOutput(new ToType(uri)); 122 return (Type) this; 123 } 124 125 /** 126 * Sends the exchange to the given endpoint 127 */ 128 public Type to(Endpoint endpoint) { 129 addOutput(new ToType(endpoint)); 130 return (Type) this; 131 } 132 133 /** 134 * Sends the exchange to a list of endpoints 135 */ 136 public Type to(String... uris) { 137 for (String uri : uris) { 138 addOutput(new ToType(uri)); 139 } 140 return (Type) this; 141 } 142 143 /** 144 * Sends the exchange to a list of endpoints 145 */ 146 public Type to(Endpoint... endpoints) { 147 for (Endpoint endpoint : endpoints) { 148 addOutput(new ToType(endpoint)); 149 } 150 return (Type) this; 151 } 152 153 /** 154 * Sends the exchange to a list of endpoint 155 */ 156 public Type to(Collection<Endpoint> endpoints) { 157 for (Endpoint endpoint : endpoints) { 158 addOutput(new ToType(endpoint)); 159 } 160 return (Type) this; 161 } 162 163 /** 164 * Multicasts messages to all its child outputs; so that each processor and 165 * destination gets a copy of the original message to avoid the processors 166 * interfering with each other. 167 */ 168 public MulticastType multicast() { 169 MulticastType answer = new MulticastType(); 170 addOutput(answer); 171 return answer; 172 } 173 174 /** 175 * Multicasts messages to all its child outputs; so that each processor and 176 * destination gets a copy of the original message to avoid the processors 177 * interfering with each other. 178 * @param aggregationStrategy the strategy used to aggregate responses for 179 * every part 180 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 181 * @return the multicast type 182 */ 183 public MulticastType multicast(AggregationStrategy aggregationStrategy, boolean parallelProcessing) { 184 MulticastType answer = new MulticastType(); 185 addOutput(answer); 186 answer.setAggregationStrategy(aggregationStrategy); 187 answer.setParallelProcessing(parallelProcessing); 188 return answer; 189 } 190 191 /** 192 * Multicasts messages to all its child outputs; so that each processor and 193 * destination gets a copy of the original message to avoid the processors 194 * interfering with each other. 195 * @param aggregationStrategy the strategy used to aggregate responses for 196 * every part 197 * @return the multicast type 198 */ 199 public MulticastType multicast(AggregationStrategy aggregationStrategy) { 200 MulticastType answer = new MulticastType(); 201 addOutput(answer); 202 answer.setAggregationStrategy(aggregationStrategy); 203 return answer; 204 } 205 206 /** 207 * Creates a {@link Pipeline} of the list of endpoints so that the message 208 * will get processed by each endpoint in turn and for request/response the 209 * output of one endpoint will be the input of the next endpoint 210 */ 211 public Type pipeline(String... uris) { 212 // TODO pipeline v mulicast 213 return to(uris); 214 } 215 216 /** 217 * Creates a {@link Pipeline} of the list of endpoints so that the message 218 * will get processed by each endpoint in turn and for request/response the 219 * output of one endpoint will be the input of the next endpoint 220 */ 221 public Type pipeline(Endpoint... endpoints) { 222 // TODO pipeline v mulicast 223 return to(endpoints); 224 } 225 226 /** 227 * Creates a {@link Pipeline} of the list of endpoints so that the message 228 * will get processed by each endpoint in turn and for request/response the 229 * output of one endpoint will be the input of the next endpoint 230 */ 231 public Type pipeline(Collection<Endpoint> endpoints) { 232 // TODO pipeline v mulicast 233 return to(endpoints); 234 } 235 236 /** 237 * Ends the current block 238 */ 239 public ProcessorType<? extends ProcessorType> end() { 240 if (blocks.isEmpty()) { 241 if (parent == null) { 242 throw new IllegalArgumentException("Root node with no active block"); 243 } 244 return parent; 245 } 246 popBlock(); 247 return this; 248 } 249 250 /** 251 * Causes subsequent processors to be called asynchronously 252 * 253 * @param coreSize the number of threads that will be used to process 254 * messages in subsequent processors. 255 * @return a ThreadType builder that can be used to further configure the 256 * the thread pool. 257 */ 258 public ThreadType thread(int coreSize) { 259 ThreadType answer = new ThreadType(coreSize); 260 addOutput(answer); 261 return answer; 262 } 263 264 /** 265 * Causes subsequent processors to be called asynchronously 266 * 267 * @param executor the executor that will be used to process 268 * messages in subsequent processors. 269 * @return a ThreadType builder that can be used to further configure the 270 * the thread pool. 271 */ 272 public ProcessorType<Type> thread(ThreadPoolExecutor executor) { 273 ThreadType answer = new ThreadType(executor); 274 addOutput(answer); 275 return this; 276 } 277 278 /** 279 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer} 280 * to avoid duplicate messages 281 */ 282 public IdempotentConsumerType idempotentConsumer(Expression messageIdExpression, 283 MessageIdRepository messageIdRepository) { 284 IdempotentConsumerType answer = new IdempotentConsumerType(messageIdExpression, messageIdRepository); 285 addOutput(answer); 286 return answer; 287 } 288 289 /** 290 * Creates an {@link org.apache.camel.processor.idempotent.IdempotentConsumer} 291 * to avoid duplicate messages 292 * 293 * @return the builder used to create the expression 294 */ 295 public ExpressionClause<IdempotentConsumerType> idempotentConsumer(MessageIdRepository messageIdRepository) { 296 IdempotentConsumerType answer = new IdempotentConsumerType(); 297 answer.setMessageIdRepository(messageIdRepository); 298 addOutput(answer); 299 return ExpressionClause.createAndSetExpression(answer); 300 } 301 302 /** 303 * Creates a predicate expression which only if it is true then the 304 * exchange is forwarded to the destination 305 * 306 * @return the clause used to create the filter expression 307 */ 308 public ExpressionClause<FilterType> filter() { 309 FilterType filter = new FilterType(); 310 addOutput(filter); 311 return ExpressionClause.createAndSetExpression(filter); 312 } 313 314 /** 315 * Creates a predicate which is applied and only if it is true then the 316 * exchange is forwarded to the destination 317 * 318 * @return the builder for a predicate 319 */ 320 public FilterType filter(Predicate predicate) { 321 FilterType filter = new FilterType(predicate); 322 addOutput(filter); 323 return filter; 324 } 325 326 public FilterType filter(ExpressionType expression) { 327 FilterType filter = getNodeFactory().createFilter(); 328 filter.setExpression(expression); 329 addOutput(filter); 330 return filter; 331 } 332 333 public FilterType filter(String language, String expression) { 334 return filter(new LanguageExpression(language, expression)); 335 } 336 337 public LoadBalanceType loadBalance() { 338 LoadBalanceType answer = new LoadBalanceType(); 339 addOutput(answer); 340 return answer; 341 } 342 343 344 /** 345 * Creates a choice of one or more predicates with an otherwise clause 346 * 347 * @return the builder for a choice expression 348 */ 349 public ChoiceType choice() { 350 ChoiceType answer = new ChoiceType(); 351 addOutput(answer); 352 return answer; 353 } 354 355 /** 356 * Creates a try/catch block 357 * 358 * @return the builder for a tryBlock expression 359 */ 360 public TryType tryBlock() { 361 TryType answer = new TryType(); 362 addOutput(answer); 363 return answer; 364 } 365 366 /** 367 * Creates a dynamic <a 368 * href="http://activemq.apache.org/camel/recipient-list.html">Recipient 369 * List</a> pattern. 370 * 371 * @param recipients is the builder of the expression used in the 372 * {@link org.apache.camel.processor.RecipientList} 373 * to decide the destinations 374 */ 375 public Type recipientList(Expression recipients) { 376 RecipientListType answer = new RecipientListType(recipients); 377 addOutput(answer); 378 return (Type) this; 379 } 380 381 /** 382 * Creates a dynamic <a 383 * href="http://activemq.apache.org/camel/recipient-list.html">Recipient 384 * List</a> pattern. 385 * 386 * @return the expression clause for the expression used in the 387 * {@link org.apache.camel.processor.RecipientList} 388 * to decide the destinations 389 */ 390 public ExpressionClause<ProcessorType<Type>> recipientList() { 391 RecipientListType answer = new RecipientListType(); 392 addOutput(answer); 393 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 394 answer.setExpression(clause); 395 return clause; 396 } 397 398 /** 399 * Creates a <a 400 * href="http://activemq.apache.org/camel/routing-slip.html">Routing 401 * Slip</a> pattern. 402 * 403 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip} 404 * class will look in for the list of URIs to route the message to. 405 * @param uriDelimiter is the delimiter that will be used to split up 406 * the list of URIs in the routing slip. 407 */ 408 public Type routingSlip(String header, String uriDelimiter) { 409 RoutingSlipType answer = new RoutingSlipType(header, uriDelimiter); 410 addOutput(answer); 411 return (Type) this; 412 } 413 414 /** 415 * Creates a <a 416 * href="http://activemq.apache.org/camel/routing-slip.html">Routing 417 * Slip</a> pattern. 418 * 419 * @param header is the header that the {@link org.apache.camel.processor.RoutingSlip RoutingSlip} 420 * class will look in for the list of URIs to route the message to. The list of URIs 421 * will be split based on the default delimiter 422 * {@link RoutingSlipType#DEFAULT_DELIMITER}. 423 */ 424 public Type routingSlip(String header) { 425 RoutingSlipType answer = new RoutingSlipType(header); 426 addOutput(answer); 427 return (Type) this; 428 } 429 430 /** 431 * Creates a <a 432 * href="http://activemq.apache.org/camel/routing-slip.html">Routing 433 * Slip</a> pattern with the default header {@link RoutingSlipType#ROUTING_SLIP_HEADER}. 434 * The list of URIs in the header will be split based on the default delimiter 435 * {@link RoutingSlipType#DEFAULT_DELIMITER}. 436 */ 437 public Type routingSlip() { 438 RoutingSlipType answer = new RoutingSlipType(); 439 addOutput(answer); 440 return (Type) this; 441 } 442 443 /** 444 * Creates the <a 445 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 446 * pattern where an expression is evaluated to iterate through each of the 447 * parts of a message and then each part is then send to some endpoint. 448 * This splitter responds with the latest message returned from destination 449 * endpoint. 450 * 451 * @param recipients the expression on which to split 452 * @return the builder 453 */ 454 public SplitterType splitter(Expression recipients) { 455 SplitterType answer = new SplitterType(recipients); 456 addOutput(answer); 457 return answer; 458 } 459 460 /** 461 * Creates the <a 462 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 463 * pattern where an expression is evaluated to iterate through each of the 464 * parts of a message and then each part is then send to some endpoint. 465 * This splitter responds with the latest message returned from destination 466 * endpoint. 467 * 468 * @return the expression clause for the expression on which to split 469 */ 470 public ExpressionClause<SplitterType> splitter() { 471 SplitterType answer = new SplitterType(); 472 addOutput(answer); 473 return ExpressionClause.createAndSetExpression(answer); 474 } 475 476 /** 477 * Creates the <a 478 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 479 * pattern where an expression is evaluated to iterate through each of the 480 * parts of a message and then each part is then send to some endpoint. 481 * Answer from the splitter is produced using given {@link AggregationStrategy} 482 * @param partsExpression the expression on which to split 483 * @param aggregationStrategy the strategy used to aggregate responses for 484 * every part 485 * @return the builder 486 */ 487 public SplitterType splitter(Expression partsExpression, AggregationStrategy aggregationStrategy) { 488 SplitterType answer = new SplitterType(partsExpression); 489 addOutput(answer); 490 answer.setAggregationStrategy(aggregationStrategy); 491 return answer; 492 } 493 494 /** 495 * Creates the <a 496 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 497 * pattern where an expression is evaluated to iterate through each of the 498 * parts of a message and then each part is then send to some endpoint. 499 * Answer from the splitter is produced using given {@link AggregationStrategy} 500 * @param aggregationStrategy the strategy used to aggregate responses for 501 * every part 502 * @return the expression clause for the expression on which to split 503 */ 504 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy) { 505 SplitterType answer = new SplitterType(); 506 addOutput(answer); 507 answer.setAggregationStrategy(aggregationStrategy); 508 return ExpressionClause.createAndSetExpression(answer); 509 } 510 511 /** 512 * Creates the <a 513 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 514 * pattern where an expression is evaluated to iterate through each of the 515 * parts of a message and then each part is then send to some endpoint. 516 * This splitter responds with the latest message returned from destination 517 * endpoint. 518 * 519 * @param recipients the expression on which to split 520 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 521 * @return the builder 522 */ 523 public SplitterType splitter(Expression recipients, boolean parallelProcessing) { 524 SplitterType answer = new SplitterType(recipients); 525 addOutput(answer); 526 answer.setParallelProcessing(parallelProcessing); 527 return answer; 528 } 529 530 /** 531 * Creates the <a 532 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 533 * pattern where an expression is evaluated to iterate through each of the 534 * parts of a message and then each part is then send to some endpoint. 535 * This splitter responds with the latest message returned from destination 536 * endpoint. 537 * 538 * @param recipients the expression on which to split 539 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 540 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 541 * @return the builder 542 */ 543 public SplitterType splitter(Expression recipients, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) { 544 SplitterType answer = new SplitterType(recipients); 545 addOutput(answer); 546 answer.setParallelProcessing(parallelProcessing); 547 answer.setThreadPoolExecutor(threadPoolExecutor); 548 return answer; 549 } 550 551 /** 552 * Creates the <a 553 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 554 * pattern where an expression is evaluated to iterate through each of the 555 * parts of a message and then each part is then send to some endpoint. 556 * This splitter responds with the latest message returned from destination 557 * endpoint. 558 * 559 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 560 * @return the expression clause for the expression on which to split 561 */ 562 public ExpressionClause<SplitterType> splitter(boolean parallelProcessing) { 563 SplitterType answer = new SplitterType(); 564 addOutput(answer); 565 answer.setParallelProcessing(parallelProcessing); 566 return ExpressionClause.createAndSetExpression(answer); 567 } 568 569 /** 570 * Creates the <a 571 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 572 * pattern where an expression is evaluated to iterate through each of the 573 * parts of a message and then each part is then send to some endpoint. 574 * This splitter responds with the latest message returned from destination 575 * endpoint. 576 * 577 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 578 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 579 * @return the expression clause for the expression on which to split 580 */ 581 public ExpressionClause<SplitterType> splitter(boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) { 582 SplitterType answer = new SplitterType(); 583 addOutput(answer); 584 answer.setParallelProcessing(parallelProcessing); 585 answer.setThreadPoolExecutor(threadPoolExecutor); 586 return ExpressionClause.createAndSetExpression(answer); 587 } 588 589 /** 590 * Creates the <a 591 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 592 * pattern where an expression is evaluated to iterate through each of the 593 * parts of a message and then each part is then send to some endpoint. 594 * Answer from the splitter is produced using given {@link AggregationStrategy} 595 * @param partsExpression the expression on which to split 596 * @param aggregationStrategy the strategy used to aggregate responses for 597 * every part 598 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 599 * @return the builder 600 */ 601 public SplitterType splitter(Expression partsExpression, 602 AggregationStrategy aggregationStrategy, boolean parallelProcessing) { 603 SplitterType answer = new SplitterType(partsExpression); 604 addOutput(answer); 605 answer.setAggregationStrategy(aggregationStrategy); 606 answer.setParallelProcessing(parallelProcessing); 607 return answer; 608 } 609 610 /** 611 * Creates the <a 612 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 613 * pattern where an expression is evaluated to iterate through each of the 614 * parts of a message and then each part is then send to some endpoint. 615 * Answer from the splitter is produced using given {@link AggregationStrategy} 616 * @param partsExpression the expression on which to split 617 * @param aggregationStrategy the strategy used to aggregate responses for 618 * every part 619 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 620 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 621 * @return the builder 622 */ 623 public SplitterType splitter(Expression partsExpression, 624 AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) { 625 SplitterType answer = new SplitterType(partsExpression); 626 addOutput(answer); 627 answer.setAggregationStrategy(aggregationStrategy); 628 answer.setParallelProcessing(parallelProcessing); 629 answer.setThreadPoolExecutor(threadPoolExecutor); 630 return answer; 631 } 632 633 /** 634 * Creates the <a 635 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 636 * pattern where an expression is evaluated to iterate through each of the 637 * parts of a message and then each part is then send to some endpoint. 638 * Answer from the splitter is produced using given {@link AggregationStrategy} 639 * @param aggregationStrategy the strategy used to aggregate responses for 640 * every part 641 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 642 * @return the expression clause for the expression on which to split 643 */ 644 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing) { 645 SplitterType answer = new SplitterType(); 646 addOutput(answer); 647 answer.setAggregationStrategy(aggregationStrategy); 648 answer.setParallelProcessing(parallelProcessing); 649 return ExpressionClause.createAndSetExpression(answer); 650 } 651 652 /** 653 * Creates the <a 654 * href="http://activemq.apache.org/camel/splitter.html">Splitter</a> 655 * pattern where an expression is evaluated to iterate through each of the 656 * parts of a message and then each part is then send to some endpoint. 657 * Answer from the splitter is produced using given {@link AggregationStrategy} 658 * @param aggregationStrategy the strategy used to aggregate responses for 659 * every part 660 * @param parallelProcessing if is <tt>true</tt> camel will fork thread to call the endpoint producer 661 * @param threadPoolExecutor override the default {@link ThreadPoolExecutor} 662 * @return the expression clause for the expression on which to split 663 */ 664 public ExpressionClause<SplitterType> splitter(AggregationStrategy aggregationStrategy, boolean parallelProcessing, ThreadPoolExecutor threadPoolExecutor) { 665 SplitterType answer = new SplitterType(); 666 addOutput(answer); 667 answer.setAggregationStrategy(aggregationStrategy); 668 answer.setParallelProcessing(parallelProcessing); 669 answer.setThreadPoolExecutor(threadPoolExecutor); 670 return ExpressionClause.createAndSetExpression(answer); 671 } 672 673 /** 674 * Creates the <a 675 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a> 676 * pattern where a list of expressions are evaluated to be able to compare 677 * the message exchanges to reorder them. e.g. you may wish to sort by some 678 * headers 679 * 680 * @return the expression clause for the expressions on which to compare messages in order 681 */ 682 public ExpressionClause<ResequencerType> resequencer() { 683 ResequencerType answer = new ResequencerType(); 684 addOutput(answer); 685 ExpressionClause<ResequencerType> clause = new ExpressionClause<ResequencerType>(answer); 686 answer.expression(clause); 687 return clause; 688 } 689 690 /** 691 * Creates the <a 692 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a> 693 * pattern where an expression is evaluated to be able to compare the 694 * message exchanges to reorder them. e.g. you may wish to sort by some 695 * header 696 * 697 * @param expression the expression on which to compare messages in order 698 * @return the builder 699 */ 700 public ResequencerType resequencer(Expression<Exchange> expression) { 701 return resequencer(Collections.<Expression>singletonList(expression)); 702 } 703 704 /** 705 * Creates the <a 706 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a> 707 * pattern where a list of expressions are evaluated to be able to compare 708 * the message exchanges to reorder them. e.g. you may wish to sort by some 709 * headers 710 * 711 * @param expressions the expressions on which to compare messages in order 712 * @return the builder 713 */ 714 public ResequencerType resequencer(List<Expression> expressions) { 715 ResequencerType answer = new ResequencerType(expressions); 716 addOutput(answer); 717 return answer; 718 } 719 720 /** 721 * Creates the <a 722 * href="http://activemq.apache.org/camel/resequencer.html">Resequencer</a> 723 * pattern where a list of expressions are evaluated to be able to compare 724 * the message exchanges to reorder them. e.g. you may wish to sort by some 725 * headers 726 * 727 * @param expressions the expressions on which to compare messages in order 728 * @return the builder 729 */ 730 public ResequencerType resequencer(Expression... expressions) { 731 List<Expression> list = new ArrayList<Expression>(); 732 list.addAll(Arrays.asList(expressions)); 733 return resequencer(list); 734 } 735 736 /** 737 * Creates an <a 738 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a> 739 * pattern where a batch of messages are processed (up to a maximum amount 740 * or until some timeout is reached) and messages for the same correlation 741 * key are combined together using some kind of {@link AggregationStrategy} 742 * (by default the latest message is used) to compress many message exchanges 743 * into a smaller number of exchanges. 744 * <p/> 745 * A good example of this is stock market data; you may be receiving 30,000 746 * messages/second and you may want to throttle it right down so that multiple 747 * messages for the same stock are combined (or just the latest message is used 748 * and older prices are discarded). Another idea is to combine line item messages 749 * together into a single invoice message. 750 */ 751 public ExpressionClause<AggregatorType> aggregator() { 752 if (!getOutputs().isEmpty()) { 753 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this); 754 } 755 AggregatorType answer = new AggregatorType(); 756 addOutput(answer); 757 return ExpressionClause.createAndSetExpression(answer); 758 } 759 760 /** 761 * Creates an <a 762 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a> 763 * pattern where a batch of messages are processed (up to a maximum amount 764 * or until some timeout is reached) and messages for the same correlation 765 * key are combined together using some kind of {@link AggregationStrategy} 766 * (by default the latest message is used) to compress many message exchanges 767 * into a smaller number of exchanges. 768 * <p/> 769 * A good example of this is stock market data; you may be receiving 30,000 770 * messages/second and you may want to throttle it right down so that multiple 771 * messages for the same stock are combined (or just the latest message is used 772 * and older prices are discarded). Another idea is to combine line item messages 773 * together into a single invoice message. 774 * 775 * @param aggregationStrategy the strategy used for the aggregation 776 */ 777 public ExpressionClause<AggregatorType> aggregator(AggregationStrategy aggregationStrategy) { 778 if (!getOutputs().isEmpty()) { 779 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this); 780 } 781 AggregatorType answer = new AggregatorType(); 782 answer.setAggregationStrategy(aggregationStrategy); 783 addOutput(answer); 784 return ExpressionClause.createAndSetExpression(answer); 785 } 786 787 /** 788 * Creates an <a 789 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a> 790 * pattern using a custom aggregation collection implementation. The aggregation collection must 791 * be configued with the strategy and correlation expression that this aggregator should use. 792 * This avoids duplicating this configuration on both the collection and the aggregator itself. 793 * 794 * @param aggregationCollection the collection used to perform the aggregation 795 */ 796 public AggregatorType aggregator(AggregationCollection aggregationCollection) { 797 if (!getOutputs().isEmpty()) { 798 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this); 799 } 800 AggregatorType answer = new AggregatorType(); 801 answer.setAggregationCollection(aggregationCollection); 802 addOutput(answer); 803 return answer; 804 } 805 806 /** 807 * Creates an <a 808 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a> 809 * pattern where a batch of messages are processed (up to a maximum amount 810 * or until some timeout is reached) and messages for the same correlation 811 * key are combined together using some kind of {@link AggregationStrategy} 812 * (by default the latest message is used) to compress many message exchanges 813 * into a smaller number of exchanges. 814 * <p/> 815 * A good example of this is stock market data; you may be receiving 30,000 816 * messages/second and you may want to throttle it right down so that multiple 817 * messages for the same stock are combined (or just the latest message is used 818 * and older prices are discarded). Another idea is to combine line item messages 819 * together into a single invoice message. 820 * 821 * @param correlationExpression the expression used to calculate the 822 * correlation key. For a JMS message this could be the 823 * expression <code>header("JMSDestination")</code> or 824 * <code>header("JMSCorrelationID")</code> 825 */ 826 public AggregatorType aggregator(Expression correlationExpression) { 827 if (!getOutputs().isEmpty()) { 828 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this); 829 } 830 AggregatorType answer = new AggregatorType(correlationExpression); 831 addOutput(answer); 832 return answer; 833 } 834 835 /** 836 * Creates an <a 837 * href="http://activemq.apache.org/camel/aggregator.html">Aggregator</a> 838 * pattern where a batch of messages are processed (up to a maximum amount 839 * or until some timeout is reached) and messages for the same correlation 840 * key are combined together using some kind of {@link AggregationStrategy} 841 * (by default the latest message is used) to compress many message exchanges 842 * into a smaller number of exchanges. 843 * <p/> 844 * A good example of this is stock market data; you may be receiving 30,000 845 * messages/second and you may want to throttle it right down so that multiple 846 * messages for the same stock are combined (or just the latest message is used 847 * and older prices are discarded). Another idea is to combine line item messages 848 * together into a single invoice message. 849 * 850 * @param correlationExpression the expression used to calculate the 851 * correlation key. For a JMS message this could be the 852 * expression <code>header("JMSDestination")</code> or 853 * <code>header("JMSCorrelationID")</code> 854 */ 855 public AggregatorType aggregator(Expression correlationExpression, AggregationStrategy aggregationStrategy) { 856 if (!getOutputs().isEmpty()) { 857 throw new IllegalArgumentException("Aggregator must be the only output added to the route: " + this); 858 } 859 AggregatorType answer = new AggregatorType(correlationExpression, aggregationStrategy); 860 addOutput(answer); 861 return answer; 862 } 863 864 /** 865 * Creates the <a 866 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern 867 * where an expression is used to calculate the time which the message will 868 * be dispatched on 869 * 870 * @param processAtExpression an expression to calculate the time at which 871 * the messages should be processed 872 * @return the builder 873 */ 874 public DelayerType delayer(Expression<Exchange> processAtExpression) { 875 return delayer(processAtExpression, 0L); 876 } 877 878 /** 879 * Creates the <a 880 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern 881 * where an expression is used to calculate the time which the message will 882 * be dispatched on 883 * 884 * @param processAtExpression an expression to calculate the time at which 885 * the messages should be processed 886 * @param delay the delay in milliseconds which is added to the 887 * processAtExpression to determine the time the message 888 * should be processed 889 * @return the builder 890 */ 891 public DelayerType delayer(Expression<Exchange> processAtExpression, long delay) { 892 DelayerType answer = new DelayerType(processAtExpression, delay); 893 addOutput(answer); 894 return answer; 895 } 896 897 /** 898 * Creates the <a 899 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern 900 * where an expression is used to calculate the time which the message will 901 * be dispatched on 902 * @return the expression clause to create the expression 903 */ 904 public ExpressionClause<DelayerType> delayer() { 905 DelayerType answer = new DelayerType(); 906 addOutput(answer); 907 return ExpressionClause.createAndSetExpression(answer); 908 } 909 910 /** 911 * Creates the <a 912 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern 913 * where a fixed amount of milliseconds are used to delay processing of a 914 * message exchange 915 * 916 * @param delay the default delay in milliseconds 917 * @return the builder 918 */ 919 public DelayerType delayer(long delay) { 920 return delayer(null, delay); 921 } 922 923 /** 924 * Creates the <a 925 * href="http://activemq.apache.org/camel/delayer.html">Delayer</a> pattern 926 * where an expression is used to calculate the time which the message will 927 * be dispatched on 928 * 929 * @return the builder 930 */ 931 public ThrottlerType throttler(long maximumRequestCount) { 932 ThrottlerType answer = new ThrottlerType(maximumRequestCount); 933 addOutput(answer); 934 return answer; 935 } 936 937 /** 938 * Creates a expression which must evaluate to an integer that determines 939 * how many times the exchange should be sent down the rest of the route. 940 * 941 * @return the clause used to create the loop expression 942 */ 943 public ExpressionClause<LoopType> loop() { 944 LoopType loop = new LoopType(); 945 addOutput(loop); 946 return ExpressionClause.createAndSetExpression(loop); 947 } 948 949 public LoopType loop(Expression<?> expression) { 950 LoopType loop = getNodeFactory().createLoop(); 951 loop.setExpression(expression); 952 addOutput(loop); 953 return loop; 954 } 955 956 public LoopType loop(int count) { 957 LoopType loop = getNodeFactory().createLoop(); 958 loop.setExpression(new ConstantExpression(Integer.toString(count))); 959 addOutput(loop); 960 return loop; 961 } 962 963 public Type throwFault(Throwable fault) { 964 ThrowFaultType answer = new ThrowFaultType(); 965 answer.setFault(fault); 966 addOutput(answer); 967 return (Type) this; 968 } 969 970 public Type throwFault(String message) { 971 return throwFault(new CamelException(message)); 972 } 973 974 /** 975 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement) 976 */ 977 public Type interceptor(String ref) { 978 InterceptorRef interceptor = new InterceptorRef(ref); 979 intercept(interceptor); 980 return (Type) this; 981 } 982 983 /** 984 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement) 985 */ 986 public Type intercept(DelegateProcessor interceptor) { 987 intercept(new InterceptorRef(interceptor)); 988 //lastInterceptor = interceptor; 989 return (Type) this; 990 } 991 992 /** 993 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement) 994 */ 995 public InterceptType intercept() { 996 InterceptType answer = new InterceptType(); 997 addOutput(answer); 998 return answer; 999 } 1000 1001 /** 1002 * Intercepts outputs added to this node in the future (i.e. intercepts outputs added after this statement) 1003 */ 1004 public void intercept(InterceptorType interceptor) { 1005 addOutput(interceptor); 1006 pushBlock(interceptor); 1007 } 1008 1009 /** 1010 * Adds an interceptor around the whole of this nodes processing 1011 * 1012 * @param interceptor 1013 */ 1014 public void addInterceptor(InterceptorType interceptor) { 1015 interceptors.add(interceptor); 1016 } 1017 1018 /** 1019 * Adds an interceptor around the whole of this nodes processing 1020 * 1021 * @param interceptor 1022 */ 1023 public void addInterceptor(DelegateProcessor interceptor) { 1024 addInterceptor(new InterceptorRef(interceptor)); 1025 } 1026 1027 public void pushBlock(Block block) { 1028 blocks.add(block); 1029 } 1030 1031 public Block popBlock() { 1032 return blocks.isEmpty() ? null : blocks.removeLast(); 1033 } 1034 1035 public Type proceed() { 1036 ProceedType proceed = null; 1037 ProcessorType currentProcessor = this; 1038 1039 if (currentProcessor instanceof InterceptType) { 1040 proceed = ((InterceptType) currentProcessor).getProceed(); 1041 LOG.info("proceed() is the implied and hence not needed for an intercept()"); 1042 } 1043 if (proceed == null) { 1044 for (ProcessorType node = parent; node != null; node = node.getParent()) { 1045 if (node instanceof InterceptType) { 1046 InterceptType intercept = (InterceptType)node; 1047 proceed = intercept.getProceed(); 1048 break; 1049 } 1050 } 1051 1052 if (proceed == null) { 1053 throw new IllegalArgumentException("Cannot use proceed() without being within an intercept() block"); 1054 } 1055 1056 } 1057 1058 addOutput(proceed); 1059 return (Type) this; 1060 } 1061 1062 public Type stop() { 1063 ProcessorType currentProcessor = this; 1064 1065 if (currentProcessor instanceof InterceptType) { 1066 ((InterceptType) currentProcessor).stopIntercept(); 1067 } else { 1068 ProcessorType node; 1069 for (node = parent; node != null; node = node.getParent()) { 1070 if (node instanceof InterceptType) { 1071 ((InterceptType) node).stopIntercept(); 1072 break; 1073 } 1074 } 1075 if (node == null) { 1076 throw new IllegalArgumentException("Cannot use stop() without being within an intercept() block"); 1077 } 1078 } 1079 1080 return (Type) this; 1081 } 1082 1083 /** 1084 * Catches an exception type. 1085 * 1086 * @deprecated Please use {@link #onException(Class)} instead. Will be removed in Camel 2.0. 1087 */ 1088 public ExceptionType exception(Class exceptionType) { 1089 return onException(exceptionType); 1090 } 1091 1092 /** 1093 * Catches an exception type. 1094 */ 1095 public ExceptionType onException(Class exceptionType) { 1096 ExceptionType answer = new ExceptionType(exceptionType); 1097 addOutput(answer); 1098 return answer; 1099 } 1100 1101 /** 1102 * Apply an interceptor route if the predicate is true 1103 */ 1104 public ChoiceType intercept(Predicate predicate) { 1105 InterceptType answer = new InterceptType(); 1106 addOutput(answer); 1107 return answer.when(predicate); 1108 } 1109 1110 public Type interceptors(String... refs) { 1111 for (String ref : refs) { 1112 interceptor(ref); 1113 } 1114 return (Type) this; 1115 } 1116 1117 /** 1118 * Trace logs the exchange before it goes to the next processing step using 1119 * the {@link #DEFAULT_TRACE_CATEGORY} logging category. 1120 * 1121 * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a> 1122 * instead. Will be removed in Camel 2.0. 1123 */ 1124 public Type trace() { 1125 return trace(DEFAULT_TRACE_CATEGORY); 1126 } 1127 1128 /** 1129 * Trace logs the exchange before it goes to the next processing step using 1130 * the specified logging category. 1131 * 1132 * @param category the logging category trace messages will sent to. 1133 * 1134 * @deprecated Please use <a href="http://activemq.apache.org/camel/tracer.html>Tracer Support</a> 1135 * instead. Will be removed in Camel 2.0. 1136 */ 1137 public Type trace(String category) { 1138 final Log log = LogFactory.getLog(category); 1139 return intercept(new DelegateProcessor() { 1140 @Override 1141 public void process(Exchange exchange) throws Exception { 1142 log.trace(exchange); 1143 processNext(exchange); 1144 } 1145 }); 1146 } 1147 1148 public PolicyRef policies() { 1149 PolicyRef answer = new PolicyRef(); 1150 addOutput(answer); 1151 return answer; 1152 } 1153 1154 public PolicyRef policy(Policy policy) { 1155 PolicyRef answer = new PolicyRef(policy); 1156 addOutput(answer); 1157 return answer; 1158 } 1159 1160 /** 1161 * Forces handling of faults as exceptions 1162 * 1163 * @return the current builder with the fault handler configured 1164 */ 1165 public Type handleFault() { 1166 intercept(new HandleFaultType()); 1167 return (Type) this; 1168 } 1169 1170 /** 1171 * Installs the given error handler builder 1172 * 1173 * @param errorHandlerBuilder the error handler to be used by default for 1174 * all child routes 1175 * @return the current builder with the error handler configured 1176 */ 1177 public Type errorHandler(ErrorHandlerBuilder errorHandlerBuilder) { 1178 setErrorHandlerBuilder(errorHandlerBuilder); 1179 return (Type) this; 1180 } 1181 1182 /** 1183 * Configures whether or not the error handler is inherited by every 1184 * processing node (or just the top most one) 1185 * 1186 * @param condition the flag as to whether error handlers should be 1187 * inherited or not 1188 * @return the current builder 1189 */ 1190 public Type inheritErrorHandler(boolean condition) { 1191 setInheritErrorHandlerFlag(condition); 1192 return (Type) this; 1193 } 1194 1195 // Transformers 1196 // ------------------------------------------------------------------------- 1197 1198 /** 1199 * Adds the custom processor to this destination which could be a final 1200 * destination, or could be a transformation in a pipeline 1201 */ 1202 public Type process(Processor processor) { 1203 ProcessorRef answer = new ProcessorRef(processor); 1204 addOutput(answer); 1205 return (Type) this; 1206 } 1207 1208 /** 1209 * Adds the custom processor reference to this destination which could be a final 1210 * destination, or could be a transformation in a pipeline 1211 */ 1212 public Type processRef(String ref) { 1213 ProcessorRef answer = new ProcessorRef(); 1214 answer.setRef(ref); 1215 addOutput(answer); 1216 return (Type) this; 1217 } 1218 1219 /** 1220 * Adds a bean which is invoked which could be a final destination, or could 1221 * be a transformation in a pipeline 1222 */ 1223 public Type bean(Object bean) { 1224 BeanRef answer = new BeanRef(); 1225 answer.setBean(bean); 1226 addOutput(answer); 1227 return (Type) this; 1228 } 1229 1230 /** 1231 * Adds a bean and method which is invoked which could be a final 1232 * destination, or could be a transformation in a pipeline 1233 */ 1234 public Type bean(Object bean, String method) { 1235 BeanRef answer = new BeanRef(); 1236 answer.setBean(bean); 1237 answer.setMethod(method); 1238 addOutput(answer); 1239 return (Type) this; 1240 } 1241 1242 /** 1243 * Adds a bean by type which is invoked which could be a final destination, or could 1244 * be a transformation in a pipeline 1245 */ 1246 public Type bean(Class beanType) { 1247 BeanRef answer = new BeanRef(); 1248 answer.setBeanType(beanType); 1249 addOutput(answer); 1250 return (Type) this; 1251 } 1252 1253 /** 1254 * Adds a bean type and method which is invoked which could be a final 1255 * destination, or could be a transformation in a pipeline 1256 */ 1257 public Type bean(Class beanType, String method) { 1258 BeanRef answer = new BeanRef(); 1259 answer.setBeanType(beanType); 1260 answer.setMethod(method); 1261 addOutput(answer); 1262 return (Type) this; 1263 } 1264 1265 /** 1266 * Adds a bean which is invoked which could be a final destination, or could 1267 * be a transformation in a pipeline 1268 */ 1269 public Type beanRef(String ref) { 1270 BeanRef answer = new BeanRef(ref); 1271 addOutput(answer); 1272 return (Type) this; 1273 } 1274 1275 /** 1276 * Adds a bean and method which is invoked which could be a final 1277 * destination, or could be a transformation in a pipeline 1278 */ 1279 public Type beanRef(String ref, String method) { 1280 BeanRef answer = new BeanRef(ref, method); 1281 addOutput(answer); 1282 return (Type) this; 1283 } 1284 1285 /** 1286 * Adds a processor which sets the body on the IN message 1287 */ 1288 public ExpressionClause<ProcessorType<Type>> setBody() { 1289 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 1290 SetBodyType answer = new SetBodyType(clause); 1291 addOutput(answer); 1292 return clause; 1293 } 1294 1295 /** 1296 * Adds a processor which sets the body on the IN message 1297 */ 1298 public Type setBody(Expression expression) { 1299 SetBodyType answer = new SetBodyType(expression); 1300 addOutput(answer); 1301 return (Type) this; 1302 } 1303 1304 /** 1305 * Adds a processor which sets the body on the OUT message 1306 * 1307 * @deprecated Please use {@link #transform(Expression)} instead. Will be removed in Camel 2.0. 1308 */ 1309 @Deprecated 1310 public Type setOutBody(Expression expression) { 1311 return transform(expression); 1312 } 1313 1314 /** 1315 * Adds a processor which sets the body on the OUT message 1316 * 1317 * @deprecated Please use {@link #transform()} instead. Will be removed in Camel 2.0. 1318 */ 1319 @Deprecated 1320 public ExpressionClause<ProcessorType<Type>> setOutBody() { 1321 return transform(); 1322 } 1323 1324 /** 1325 * Adds a processor which sets the body on the OUT message 1326 */ 1327 public Type transform(Expression expression) { 1328 TransformType answer = new TransformType(expression); 1329 addOutput(answer); 1330 return (Type) this; 1331 } 1332 1333 /** 1334 * Adds a processor which sets the body on the OUT message 1335 */ 1336 public ExpressionClause<ProcessorType<Type>> transform() { 1337 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 1338 TransformType answer = new TransformType(clause); 1339 addOutput(answer); 1340 return clause; 1341 } 1342 1343 /** 1344 * Adds a processor which sets the body on the FAULT message 1345 */ 1346 public Type setFaultBody(Expression expression) { 1347 return process(ProcessorBuilder.setFaultBody(expression)); 1348 } 1349 1350 /** 1351 * Adds a processor which sets the header on the IN message 1352 */ 1353 public ExpressionClause<ProcessorType<Type>> setHeader(String name) { 1354 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 1355 SetHeaderType answer = new SetHeaderType(name, clause); 1356 addOutput(answer); 1357 return clause; 1358 } 1359 1360 /** 1361 * Adds a processor which sets the header on the IN message 1362 */ 1363 public Type setHeader(String name, Expression expression) { 1364 SetHeaderType answer = new SetHeaderType(name, expression); 1365 addOutput(answer); 1366 return (Type) this; 1367 } 1368 1369 /** 1370 * Adds a processor which sets the header on the IN message to the given value 1371 * @deprecated Please use {@link #setHeader(String, Expression)} instead. Will be removed in Camel 2.0. 1372 */ 1373 public Type setHeader(String name, String value) { 1374 SetHeaderType answer = new SetHeaderType(name, value); 1375 addOutput(answer); 1376 return (Type) this; 1377 } 1378 1379 /** 1380 * Adds a processor which sets the header on the OUT message 1381 */ 1382 public ExpressionClause<ProcessorType<Type>> setOutHeader(String name) { 1383 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 1384 SetOutHeaderType answer = new SetOutHeaderType(name, clause); 1385 addOutput(answer); 1386 return clause; 1387 } 1388 1389 /** 1390 * Adds a processor which sets the header on the OUT message 1391 */ 1392 public Type setOutHeader(String name, Expression expression) { 1393 SetOutHeaderType answer = new SetOutHeaderType(name, expression); 1394 addOutput(answer); 1395 return (Type) this; 1396 } 1397 1398 /** 1399 * Adds a processor which sets the header on the FAULT message 1400 */ 1401 public Type setFaultHeader(String name, Expression expression) { 1402 return process(ProcessorBuilder.setFaultHeader(name, expression)); 1403 } 1404 1405 /** 1406 * Adds a processor which sets the exchange property 1407 */ 1408 public Type setProperty(String name, Expression expression) { 1409 SetPropertyType answer = new SetPropertyType(name, expression); 1410 addOutput(answer); 1411 return (Type) this; 1412 } 1413 1414 1415 /** 1416 * Adds a processor which sets the exchange property 1417 */ 1418 public ExpressionClause<ProcessorType<Type>> setProperty(String name) { 1419 ExpressionClause<ProcessorType<Type>> clause = new ExpressionClause<ProcessorType<Type>>((Type) this); 1420 SetPropertyType answer = new SetPropertyType(name, clause); 1421 addOutput(answer); 1422 return clause; 1423 } 1424 1425 /** 1426 * Adds a processor which removes the header on the IN message 1427 */ 1428 public Type removeHeader(String name) { 1429 RemoveHeaderType answer = new RemoveHeaderType(name); 1430 addOutput(answer); 1431 return (Type) this; 1432 } 1433 1434 /** 1435 * Adds a processor which removes the header on the FAULT message 1436 */ 1437 public Type removeFaultHeader(String name) { 1438 return process(ProcessorBuilder.removeFaultHeader(name)); 1439 } 1440 1441 /** 1442 * Adds a processor which removes the exchange property 1443 */ 1444 public Type removeProperty(String name) { 1445 RemovePropertyType answer = new RemovePropertyType(name); 1446 addOutput(answer); 1447 return (Type) this; 1448 } 1449 1450 /** 1451 * Converts the IN message body to the specified type 1452 */ 1453 public Type convertBodyTo(Class type) { 1454 addOutput(new ConvertBodyType(type)); 1455 return (Type) this; 1456 } 1457 1458 /** 1459 * Converts the IN message body to the specified class type 1460 */ 1461 public Type convertBodyTo(String typeString) { 1462 addOutput(new ConvertBodyType(typeString)); 1463 return (Type) this; 1464 } 1465 1466 /** 1467 * Converts the OUT message body to the specified type 1468 * 1469 * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0. 1470 */ 1471 @Deprecated 1472 public Type convertOutBodyTo(Class type) { 1473 return process(new ConvertBodyProcessor(type)); 1474 } 1475 1476 /** 1477 * Converts the FAULT message body to the specified type 1478 * 1479 * @deprecated Please use {@link #convertBodyTo(Class)} instead. Will be removed in Camel 2.0. 1480 */ 1481 @Deprecated 1482 public Type convertFaultBodyTo(Class type) { 1483 return process(new ConvertBodyProcessor(type)); 1484 } 1485 1486 // DataFormat support 1487 // ------------------------------------------------------------------------- 1488 1489 /** 1490 * Unmarshals the in body using a {@link DataFormat} expression to define 1491 * the format of the input message and the output will be set on the out message body. 1492 * 1493 * @return the expression to create the {@link DataFormat} 1494 */ 1495 public DataFormatClause<ProcessorType<Type>> unmarshal() { 1496 return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Unmarshal); 1497 } 1498 1499 /** 1500 * Unmarshals the in body using the specified {@link DataFormat} 1501 * and sets the output on the out message body. 1502 * 1503 * @return this object 1504 */ 1505 public Type unmarshal(DataFormatType dataFormatType) { 1506 addOutput(new UnmarshalType(dataFormatType)); 1507 return (Type) this; 1508 } 1509 1510 /** 1511 * Unmarshals the in body using the specified {@link DataFormat} 1512 * and sets the output on the out message body. 1513 * 1514 * @return this object 1515 */ 1516 public Type unmarshal(DataFormat dataFormat) { 1517 return unmarshal(new DataFormatType(dataFormat)); 1518 } 1519 1520 /** 1521 * Unmarshals the in body using the specified {@link DataFormat} 1522 * reference in the {@link org.apache.camel.spi.Registry} and sets 1523 * the output on the out message body. 1524 * 1525 * @return this object 1526 */ 1527 public Type unmarshal(String dataTypeRef) { 1528 addOutput(new UnmarshalType(dataTypeRef)); 1529 return (Type) this; 1530 } 1531 1532 /** 1533 * Marshals the in body using a {@link DataFormat} expression to define 1534 * the format of the output which will be added to the out body. 1535 * 1536 * @return the expression to create the {@link DataFormat} 1537 */ 1538 public DataFormatClause<ProcessorType<Type>> marshal() { 1539 return new DataFormatClause<ProcessorType<Type>>(this, DataFormatClause.Operation.Marshal); 1540 } 1541 1542 /** 1543 * Marshals the in body using the specified {@link DataFormat} 1544 * and sets the output on the out message body. 1545 * 1546 * @return this object 1547 */ 1548 public Type marshal(DataFormatType dataFormatType) { 1549 addOutput(new MarshalType(dataFormatType)); 1550 return (Type) this; 1551 } 1552 1553 /** 1554 * Marshals the in body using the specified {@link DataFormat} 1555 * and sets the output on the out message body. 1556 * 1557 * @return this object 1558 */ 1559 public Type marshal(DataFormat dataFormat) { 1560 return marshal(new DataFormatType(dataFormat)); 1561 } 1562 1563 /** 1564 * Marshals the in body the specified {@link DataFormat} 1565 * reference in the {@link org.apache.camel.spi.Registry} and sets 1566 * the output on the out message body. 1567 * 1568 * @return this object 1569 */ 1570 public Type marshal(String dataTypeRef) { 1571 addOutput(new MarshalType(dataTypeRef)); 1572 return (Type) this; 1573 } 1574 1575 // Properties 1576 // ------------------------------------------------------------------------- 1577 @XmlTransient 1578 public ProcessorType<? extends ProcessorType> getParent() { 1579 return parent; 1580 } 1581 1582 public void setParent(ProcessorType<? extends ProcessorType> parent) { 1583 this.parent = parent; 1584 } 1585 1586 @XmlTransient 1587 public ErrorHandlerBuilder getErrorHandlerBuilder() { 1588 if (errorHandlerBuilder == null) { 1589 errorHandlerBuilder = createErrorHandlerBuilder(); 1590 } 1591 return errorHandlerBuilder; 1592 } 1593 1594 /** 1595 * Sets the error handler to use with processors created by this builder 1596 */ 1597 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) { 1598 this.errorHandlerBuilder = errorHandlerBuilder; 1599 } 1600 1601 /** 1602 * Sets the error handler if one is not already set 1603 */ 1604 protected void setErrorHandlerBuilderIfNull(ErrorHandlerBuilder errorHandlerBuilder) { 1605 if (this.errorHandlerBuilder == null) { 1606 setErrorHandlerBuilder(errorHandlerBuilder); 1607 } 1608 } 1609 1610 public String getErrorHandlerRef() { 1611 return errorHandlerRef; 1612 } 1613 1614 /** 1615 * Sets the bean ref name of the error handler builder to use on this route 1616 */ 1617 @XmlAttribute(required = false) 1618 public void setErrorHandlerRef(String errorHandlerRef) { 1619 this.errorHandlerRef = errorHandlerRef; 1620 setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef)); 1621 } 1622 1623 @XmlTransient 1624 public boolean isInheritErrorHandler() { 1625 return isInheritErrorHandler(getInheritErrorHandlerFlag()); 1626 } 1627 1628 /** 1629 * Lets default the inherit value to be true if there is none specified 1630 */ 1631 public static boolean isInheritErrorHandler(Boolean value) { 1632 return value == null || value.booleanValue(); 1633 } 1634 1635 @XmlAttribute(name = "inheritErrorHandler", required = false) 1636 public Boolean getInheritErrorHandlerFlag() { 1637 return inheritErrorHandlerFlag; 1638 } 1639 1640 public void setInheritErrorHandlerFlag(Boolean inheritErrorHandlerFlag) { 1641 this.inheritErrorHandlerFlag = inheritErrorHandlerFlag; 1642 } 1643 1644 @XmlTransient 1645 public NodeFactory getNodeFactory() { 1646 if (nodeFactory == null) { 1647 nodeFactory = new NodeFactory(); 1648 } 1649 return nodeFactory; 1650 } 1651 1652 public void setNodeFactory(NodeFactory nodeFactory) { 1653 this.nodeFactory = nodeFactory; 1654 } 1655 1656 /** 1657 * Returns a label to describe this node such as the expression if some kind of expression node 1658 */ 1659 public String getLabel() { 1660 return ""; 1661 } 1662 1663 // Implementation methods 1664 // ------------------------------------------------------------------------- 1665 1666 /** 1667 * Creates the processor and wraps it in any necessary interceptors and 1668 * error handlers 1669 */ 1670 protected Processor makeProcessor(RouteContext routeContext) throws Exception { 1671 Processor processor = createProcessor(routeContext); 1672 return wrapProcessor(routeContext, processor); 1673 } 1674 1675 /** 1676 * A strategy method which allows derived classes to wrap the child 1677 * processor in some kind of interceptor 1678 * 1679 * @param routeContext 1680 * @param target the processor which can be wrapped 1681 * @return the original processor or a new wrapped interceptor 1682 */ 1683 protected Processor wrapProcessorInInterceptors(RouteContext routeContext, Processor target) throws Exception { 1684 // The target is required. 1685 if (target == null) { 1686 throw new IllegalArgumentException("target not provided on node: " + this); 1687 } 1688 1689 List<InterceptStrategy> strategies = new ArrayList<InterceptStrategy>(); 1690 CamelContext camelContext = routeContext.getCamelContext(); 1691 if (camelContext instanceof DefaultCamelContext) { 1692 DefaultCamelContext defaultCamelContext = (DefaultCamelContext) camelContext; 1693 strategies.addAll(defaultCamelContext.getInterceptStrategies()); 1694 } 1695 strategies.addAll(routeContext.getInterceptStrategies()); 1696 for (InterceptStrategy strategy : strategies) { 1697 if (strategy != null) { 1698 target = strategy.wrapProcessorInInterceptors(this, target); 1699 } 1700 } 1701 1702 List<InterceptorType> list = routeContext.getRoute().getInterceptors(); 1703 if (interceptors != null) { 1704 list.addAll(interceptors); 1705 } 1706 // lets reverse the list so we apply the inner interceptors first 1707 Collections.reverse(list); 1708 Set<Processor> interceptors = new HashSet<Processor>(); 1709 interceptors.add(target); 1710 for (InterceptorType interceptorType : list) { 1711 DelegateProcessor interceptor = interceptorType.createInterceptor(routeContext); 1712 if (!interceptors.contains(interceptor)) { 1713 interceptors.add(interceptor); 1714 if (interceptor.getProcessor() != null) { 1715 LOG.warn("Interceptor " + interceptor + " currently wraps target " 1716 + interceptor.getProcessor() 1717 + " is attempting to change target " + target 1718 + " new wrapping has been denied."); 1719 } else { 1720 interceptor.setProcessor(target); 1721 target = interceptor; 1722 } 1723 } 1724 } 1725 return target; 1726 } 1727 1728 /** 1729 * A strategy method to allow newly created processors to be wrapped in an 1730 * error handler. 1731 */ 1732 protected Processor wrapInErrorHandler(RouteContext routeContext, Processor target) throws Exception { 1733 // The target is required. 1734 if (target == null) { 1735 throw new IllegalArgumentException("target not provided on node: " + this); 1736 } 1737 1738 ErrorHandlerWrappingStrategy strategy = routeContext.getErrorHandlerWrappingStrategy(); 1739 1740 if (strategy != null) { 1741 return strategy.wrapProcessorInErrorHandler(routeContext, this, target); 1742 } 1743 1744 return getErrorHandlerBuilder().createErrorHandler(routeContext, target); 1745 } 1746 1747 protected ErrorHandlerBuilder createErrorHandlerBuilder() { 1748 if (errorHandlerRef != null) { 1749 return new ErrorHandlerBuilderRef(errorHandlerRef); 1750 } 1751 if (isInheritErrorHandler()) { 1752 return new DeadLetterChannelBuilder(); 1753 } else { 1754 return new NoErrorHandlerBuilder(); 1755 } 1756 } 1757 1758 protected void configureChild(ProcessorType output) { 1759 output.setNodeFactory(getNodeFactory()); 1760 } 1761 1762 public void addOutput(ProcessorType processorType) { 1763 processorType.setParent(this); 1764 configureChild(processorType); 1765 if (blocks.isEmpty()) { 1766 getOutputs().add(processorType); 1767 } else { 1768 Block block = blocks.getLast(); 1769 block.addOutput(processorType); 1770 } 1771 } 1772 1773 /** 1774 * Creates a new instance of some kind of composite processor which defaults 1775 * to using a {@link Pipeline} but derived classes could change the 1776 * behaviour 1777 */ 1778 protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) { 1779 // return new MulticastProcessor(list); 1780 return new Pipeline(list); 1781 } 1782 1783 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorType<?>> outputs) 1784 throws Exception { 1785 List<Processor> list = new ArrayList<Processor>(); 1786 for (ProcessorType output : outputs) { 1787 Processor processor = output.createProcessor(routeContext); 1788 // if the ProceedType create processor is null we keep on going 1789 if (output instanceof ProceedType && processor == null) { 1790 continue; 1791 } 1792 processor = output.wrapProcessorInInterceptors(routeContext, processor); 1793 1794 ProcessorType currentProcessor = this; 1795 if (!(currentProcessor instanceof ExceptionType || currentProcessor instanceof TryType)) { 1796 processor = output.wrapInErrorHandler(routeContext, processor); 1797 } 1798 1799 list.add(processor); 1800 } 1801 Processor processor = null; 1802 if (!list.isEmpty()) { 1803 if (list.size() == 1) { 1804 processor = list.get(0); 1805 } else { 1806 processor = createCompositeProcessor(routeContext, list); 1807 } 1808 } 1809 return processor; 1810 } 1811 1812 public void clearOutput() { 1813 getOutputs().clear(); 1814 blocks.clear(); 1815 } 1816 }