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