001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.List; 022import java.util.StringTokenizer; 023import java.util.concurrent.atomic.AtomicBoolean; 024import javax.xml.bind.annotation.XmlAccessType; 025import javax.xml.bind.annotation.XmlAccessorType; 026import javax.xml.bind.annotation.XmlAttribute; 027import javax.xml.bind.annotation.XmlElementRef; 028import javax.xml.bind.annotation.XmlRootElement; 029import javax.xml.bind.annotation.XmlTransient; 030import javax.xml.bind.annotation.XmlType; 031 032import org.apache.camel.CamelContext; 033import org.apache.camel.Endpoint; 034import org.apache.camel.ErrorHandlerFactory; 035import org.apache.camel.FailedToCreateRouteException; 036import org.apache.camel.NoSuchEndpointException; 037import org.apache.camel.Route; 038import org.apache.camel.ServiceStatus; 039import org.apache.camel.ShutdownRoute; 040import org.apache.camel.ShutdownRunningTask; 041import org.apache.camel.StatefulService; 042import org.apache.camel.builder.AdviceWithRouteBuilder; 043import org.apache.camel.builder.AdviceWithTask; 044import org.apache.camel.builder.ErrorHandlerBuilderRef; 045import org.apache.camel.builder.RouteBuilder; 046import org.apache.camel.impl.DefaultRouteContext; 047import org.apache.camel.model.rest.RestDefinition; 048import org.apache.camel.processor.interceptor.HandleFault; 049import org.apache.camel.spi.LifecycleStrategy; 050import org.apache.camel.spi.Metadata; 051import org.apache.camel.spi.RouteContext; 052import org.apache.camel.spi.RoutePolicy; 053import org.apache.camel.spi.RoutePolicyFactory; 054import org.apache.camel.util.CamelContextHelper; 055import org.apache.camel.util.ObjectHelper; 056 057/** 058 * A Camel route 059 * 060 * @version 061 */ 062@Metadata(label = "configuration") 063@XmlRootElement(name = "route") 064@XmlType(propOrder = {"inputs", "outputs"}) 065@XmlAccessorType(XmlAccessType.PROPERTY) 066// must use XmlAccessType.PROPERTY as there is some custom logic needed to be executed in the setter methods 067public class RouteDefinition extends ProcessorDefinition<RouteDefinition> { 068 private final AtomicBoolean prepared = new AtomicBoolean(false); 069 private List<FromDefinition> inputs = new ArrayList<FromDefinition>(); 070 private List<ProcessorDefinition<?>> outputs = new ArrayList<ProcessorDefinition<?>>(); 071 private String group; 072 private String streamCache; 073 private String trace; 074 private String messageHistory; 075 private String handleFault; 076 private String delayer; 077 private String autoStartup; 078 private Integer startupOrder; 079 private List<RoutePolicy> routePolicies; 080 private String routePolicyRef; 081 private ShutdownRoute shutdownRoute; 082 private ShutdownRunningTask shutdownRunningTask; 083 private String errorHandlerRef; 084 private ErrorHandlerFactory errorHandlerBuilder; 085 // keep state whether the error handler is context scoped or not 086 // (will by default be context scoped of no explicit error handler configured) 087 private boolean contextScopedErrorHandler = true; 088 private Boolean rest; 089 private RestDefinition restDefinition; 090 091 public RouteDefinition() { 092 } 093 094 public RouteDefinition(String uri) { 095 from(uri); 096 } 097 098 public RouteDefinition(Endpoint endpoint) { 099 from(endpoint); 100 } 101 102 /** 103 * This route is created from the REST DSL. 104 */ 105 public void fromRest(String uri) { 106 from(uri); 107 rest = true; 108 } 109 110 /** 111 * Prepares the route definition to be ready to be added to {@link CamelContext} 112 * 113 * @param context the camel context 114 */ 115 public void prepare(ModelCamelContext context) { 116 if (prepared.compareAndSet(false, true)) { 117 RouteDefinitionHelper.prepareRoute(context, this); 118 } 119 } 120 121 /** 122 * Marks the route definition as prepared. 123 * <p/> 124 * This is needed if routes have been created by components such as 125 * <tt>camel-spring</tt> or <tt>camel-blueprint</tt>. 126 * Usually they share logic in the <tt>camel-core-xml</tt> module which prepares the routes. 127 */ 128 public void markPrepared() { 129 prepared.set(true); 130 } 131 132 @Override 133 public String toString() { 134 if (getId() != null) { 135 return "Route(" + getId() + ")[" + inputs + " -> " + outputs + "]"; 136 } else { 137 return "Route[" + inputs + " -> " + outputs + "]"; 138 } 139 } 140 141 /** 142 * Returns the status of the route if it has been registered with a {@link CamelContext} 143 */ 144 public ServiceStatus getStatus(CamelContext camelContext) { 145 if (camelContext != null) { 146 ServiceStatus answer = camelContext.getRouteStatus(this.getId()); 147 if (answer == null) { 148 answer = ServiceStatus.Stopped; 149 } 150 return answer; 151 } 152 return null; 153 } 154 155 public boolean isStartable(CamelContext camelContext) { 156 ServiceStatus status = getStatus(camelContext); 157 if (status == null) { 158 return true; 159 } else { 160 return status.isStartable(); 161 } 162 } 163 164 public boolean isStoppable(CamelContext camelContext) { 165 ServiceStatus status = getStatus(camelContext); 166 if (status == null) { 167 return false; 168 } else { 169 return status.isStoppable(); 170 } 171 } 172 173 public List<RouteContext> addRoutes(ModelCamelContext camelContext, Collection<Route> routes) throws Exception { 174 List<RouteContext> answer = new ArrayList<RouteContext>(); 175 176 @SuppressWarnings("deprecation") 177 ErrorHandlerFactory handler = camelContext.getErrorHandlerBuilder(); 178 if (handler != null) { 179 setErrorHandlerBuilderIfNull(handler); 180 } 181 182 for (FromDefinition fromType : inputs) { 183 RouteContext routeContext; 184 try { 185 routeContext = addRoutes(camelContext, routes, fromType); 186 } catch (FailedToCreateRouteException e) { 187 throw e; 188 } catch (Exception e) { 189 // wrap in exception which provide more details about which route was failing 190 throw new FailedToCreateRouteException(getId(), toString(), e); 191 } 192 answer.add(routeContext); 193 } 194 return answer; 195 } 196 197 198 public Endpoint resolveEndpoint(CamelContext camelContext, String uri) throws NoSuchEndpointException { 199 ObjectHelper.notNull(camelContext, "CamelContext"); 200 return CamelContextHelper.getMandatoryEndpoint(camelContext, uri); 201 } 202 203 @Deprecated 204 public RouteDefinition adviceWith(CamelContext camelContext, RouteBuilder builder) throws Exception { 205 return adviceWith((ModelCamelContext)camelContext, builder); 206 } 207 208 /** 209 * Advices this route with the route builder. 210 * <p/> 211 * <b>Important:</b> It is recommended to only advice a given route once (you can of course advice multiple routes). 212 * If you do it multiple times, then it may not work as expected, especially when any kind of error handling is involved. 213 * The Camel team plan for Camel 3.0 to support this as internal refactorings in the routing engine is needed to support this properly. 214 * <p/> 215 * You can use a regular {@link RouteBuilder} but the specialized {@link org.apache.camel.builder.AdviceWithRouteBuilder} 216 * has additional features when using the <a href="http://camel.apache.org/advicewith.html">advice with</a> feature. 217 * We therefore suggest you to use the {@link org.apache.camel.builder.AdviceWithRouteBuilder}. 218 * <p/> 219 * The advice process will add the interceptors, on exceptions, on completions etc. configured 220 * from the route builder to this route. 221 * <p/> 222 * This is mostly used for testing purpose to add interceptors and the likes to an existing route. 223 * <p/> 224 * Will stop and remove the old route from camel context and add and start this new advised route. 225 * 226 * @param camelContext the camel context 227 * @param builder the route builder 228 * @return a new route which is this route merged with the route builder 229 * @throws Exception can be thrown from the route builder 230 * @see AdviceWithRouteBuilder 231 */ 232 @SuppressWarnings("deprecation") 233 public RouteDefinition adviceWith(ModelCamelContext camelContext, RouteBuilder builder) throws Exception { 234 ObjectHelper.notNull(camelContext, "CamelContext"); 235 ObjectHelper.notNull(builder, "RouteBuilder"); 236 237 log.debug("AdviceWith route before: {}", this); 238 239 // inject this route into the advice route builder so it can access this route 240 // and offer features to manipulate the route directly 241 if (builder instanceof AdviceWithRouteBuilder) { 242 ((AdviceWithRouteBuilder) builder).setOriginalRoute(this); 243 } 244 245 // configure and prepare the routes from the builder 246 RoutesDefinition routes = builder.configureRoutes(camelContext); 247 248 log.debug("AdviceWith routes: {}", routes); 249 250 // we can only advice with a route builder without any routes 251 if (!builder.getRouteCollection().getRoutes().isEmpty()) { 252 throw new IllegalArgumentException("You can only advice from a RouteBuilder which has no existing routes." 253 + " Remove all routes from the route builder."); 254 } 255 // we can not advice with error handlers (if you added a new error handler in the route builder) 256 // we must check the error handler on builder is not the same as on camel context, as that would be the default 257 // context scoped error handler, in case no error handlers was configured 258 if (builder.getRouteCollection().getErrorHandlerBuilder() != null 259 && camelContext.getErrorHandlerBuilder() != builder.getRouteCollection().getErrorHandlerBuilder()) { 260 throw new IllegalArgumentException("You can not advice with error handlers. Remove the error handlers from the route builder."); 261 } 262 263 // stop and remove this existing route 264 camelContext.removeRouteDefinition(this); 265 266 // any advice with tasks we should execute first? 267 if (builder instanceof AdviceWithRouteBuilder) { 268 List<AdviceWithTask> tasks = ((AdviceWithRouteBuilder) builder).getAdviceWithTasks(); 269 for (AdviceWithTask task : tasks) { 270 task.task(); 271 } 272 } 273 274 // now merge which also ensures that interceptors and the likes get mixed in correctly as well 275 RouteDefinition merged = routes.route(this); 276 277 // add the new merged route 278 camelContext.getRouteDefinitions().add(0, merged); 279 280 // log the merged route at info level to make it easier to end users to spot any mistakes they may have made 281 log.info("AdviceWith route after: " + merged); 282 283 // If the camel context is started then we start the route 284 if (camelContext instanceof StatefulService) { 285 StatefulService service = (StatefulService) camelContext; 286 if (service.isStarted()) { 287 camelContext.startRoute(merged); 288 } 289 } 290 return merged; 291 } 292 293 // Fluent API 294 // ----------------------------------------------------------------------- 295 296 /** 297 * Creates an input to the route 298 * 299 * @param uri the from uri 300 * @return the builder 301 */ 302 public RouteDefinition from(String uri) { 303 getInputs().add(new FromDefinition(uri)); 304 return this; 305 } 306 307 /** 308 * Creates an input to the route 309 * 310 * @param endpoint the from endpoint 311 * @return the builder 312 */ 313 public RouteDefinition from(Endpoint endpoint) { 314 getInputs().add(new FromDefinition(endpoint)); 315 return this; 316 } 317 318 /** 319 * Creates inputs to the route 320 * 321 * @param uris the from uris 322 * @return the builder 323 */ 324 public RouteDefinition from(String... uris) { 325 for (String uri : uris) { 326 getInputs().add(new FromDefinition(uri)); 327 } 328 return this; 329 } 330 331 /** 332 * Creates inputs to the route 333 * 334 * @param endpoints the from endpoints 335 * @return the builder 336 */ 337 public RouteDefinition from(Endpoint... endpoints) { 338 for (Endpoint endpoint : endpoints) { 339 getInputs().add(new FromDefinition(endpoint)); 340 } 341 return this; 342 } 343 344 /** 345 * Set the group name for this route 346 * 347 * @param name the group name 348 * @return the builder 349 */ 350 public RouteDefinition group(String name) { 351 setGroup(name); 352 return this; 353 } 354 355 /** 356 * Set the route id for this route 357 * 358 * @param id the route id 359 * @return the builder 360 */ 361 public RouteDefinition routeId(String id) { 362 setId(id); 363 return this; 364 } 365 366 /** 367 * Set the route description for this route 368 * 369 * @param description the route description 370 * @return the builder 371 */ 372 public RouteDefinition routeDescription(String description) { 373 DescriptionDefinition desc = new DescriptionDefinition(); 374 desc.setText(description); 375 setDescription(desc); 376 return this; 377 } 378 379 /** 380 * Disable stream caching for this route. 381 * 382 * @return the builder 383 */ 384 public RouteDefinition noStreamCaching() { 385 setStreamCache("false"); 386 return this; 387 } 388 389 /** 390 * Enable stream caching for this route. 391 * 392 * @return the builder 393 */ 394 public RouteDefinition streamCaching() { 395 setStreamCache("true"); 396 return this; 397 } 398 399 /** 400 * Disable tracing for this route. 401 * 402 * @return the builder 403 */ 404 public RouteDefinition noTracing() { 405 setTrace("false"); 406 return this; 407 } 408 409 /** 410 * Enable tracing for this route. 411 * 412 * @return the builder 413 */ 414 public RouteDefinition tracing() { 415 setTrace("true"); 416 return this; 417 } 418 419 /** 420 * Enable message history for this route. 421 * 422 * @return the builder 423 */ 424 public RouteDefinition messageHistory() { 425 setMessageHistory("true"); 426 return this; 427 } 428 429 /** 430 * Disable message history for this route. 431 * 432 * @return the builder 433 */ 434 public RouteDefinition noMessageHistory() { 435 setMessageHistory("false"); 436 return this; 437 } 438 439 /** 440 * Disable handle fault for this route. 441 * 442 * @return the builder 443 */ 444 public RouteDefinition noHandleFault() { 445 setHandleFault("false"); 446 return this; 447 } 448 449 /** 450 * Enable handle fault for this route. 451 * 452 * @return the builder 453 */ 454 public RouteDefinition handleFault() { 455 setHandleFault("true"); 456 return this; 457 } 458 459 /** 460 * Disable delayer for this route. 461 * 462 * @return the builder 463 */ 464 public RouteDefinition noDelayer() { 465 setDelayer("0"); 466 return this; 467 } 468 469 /** 470 * Enable delayer for this route. 471 * 472 * @param delay delay in millis 473 * @return the builder 474 */ 475 public RouteDefinition delayer(long delay) { 476 setDelayer("" + delay); 477 return this; 478 } 479 480 /** 481 * Installs the given <a href="http://camel.apache.org/error-handler.html">error handler</a> builder. 482 * 483 * @param errorHandlerBuilder the error handler to be used by default for all child routes 484 * @return the current builder with the error handler configured 485 */ 486 public RouteDefinition errorHandler(ErrorHandlerFactory errorHandlerBuilder) { 487 setErrorHandlerBuilder(errorHandlerBuilder); 488 // we are now using a route scoped error handler 489 contextScopedErrorHandler = false; 490 return this; 491 } 492 493 /** 494 * Disables this route from being auto started when Camel starts. 495 * 496 * @return the builder 497 */ 498 public RouteDefinition noAutoStartup() { 499 setAutoStartup("false"); 500 return this; 501 } 502 503 /** 504 * Sets the auto startup property on this route. 505 * 506 * @param autoStartup - String indicator ("true" or "false") 507 * @return the builder 508 */ 509 public RouteDefinition autoStartup(String autoStartup) { 510 setAutoStartup(autoStartup); 511 return this; 512 } 513 514 /** 515 * Sets the auto startup property on this route. 516 * 517 * @param autoStartup - boolean indicator 518 * @return the builder 519 */ 520 public RouteDefinition autoStartup(boolean autoStartup) { 521 setAutoStartup(Boolean.toString(autoStartup)); 522 return this; 523 } 524 525 /** 526 * Configures the startup order for this route 527 * <p/> 528 * Camel will reorder routes and star them ordered by 0..N where 0 is the lowest number and N the highest number. 529 * Camel will stop routes in reverse order when its stopping. 530 * 531 * @param order the order represented as a number 532 * @return the builder 533 */ 534 public RouteDefinition startupOrder(int order) { 535 setStartupOrder(order); 536 return this; 537 } 538 539 /** 540 * Configures route policies for this route 541 * 542 * @param policies the route policies 543 * @return the builder 544 */ 545 public RouteDefinition routePolicy(RoutePolicy... policies) { 546 if (routePolicies == null) { 547 routePolicies = new ArrayList<RoutePolicy>(); 548 } 549 for (RoutePolicy policy : policies) { 550 routePolicies.add(policy); 551 } 552 return this; 553 } 554 555 /** 556 * Configures a route policy for this route 557 * 558 * @param routePolicyRef reference to a {@link RoutePolicy} to lookup and use. 559 * You can specify multiple references by separating using comma. 560 * @return the builder 561 */ 562 public RouteDefinition routePolicyRef(String routePolicyRef) { 563 setRoutePolicyRef(routePolicyRef); 564 return this; 565 } 566 567 /** 568 * Configures a shutdown route option. 569 * 570 * @param shutdownRoute the option to use when shutting down this route 571 * @return the builder 572 */ 573 public RouteDefinition shutdownRoute(ShutdownRoute shutdownRoute) { 574 setShutdownRoute(shutdownRoute); 575 return this; 576 } 577 578 /** 579 * Configures a shutdown running task option. 580 * 581 * @param shutdownRunningTask the option to use when shutting down and how to act upon running tasks. 582 * @return the builder 583 */ 584 public RouteDefinition shutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 585 setShutdownRunningTask(shutdownRunningTask); 586 return this; 587 } 588 589 // Properties 590 // ----------------------------------------------------------------------- 591 592 public List<FromDefinition> getInputs() { 593 return inputs; 594 } 595 596 /** 597 * Input to the route. 598 */ 599 @XmlElementRef 600 public void setInputs(List<FromDefinition> inputs) { 601 this.inputs = inputs; 602 } 603 604 public List<ProcessorDefinition<?>> getOutputs() { 605 return outputs; 606 } 607 608 /** 609 * Outputs are processors that determines how messages are processed by this route. 610 */ 611 @XmlElementRef 612 public void setOutputs(List<ProcessorDefinition<?>> outputs) { 613 this.outputs = outputs; 614 615 if (outputs != null) { 616 for (ProcessorDefinition<?> output : outputs) { 617 configureChild(output); 618 } 619 } 620 } 621 622 public boolean isOutputSupported() { 623 return true; 624 } 625 626 /** 627 * The group that this route belongs to; could be the name of the RouteBuilder class 628 * or be explicitly configured in the XML. 629 * <p/> 630 * May be null. 631 */ 632 public String getGroup() { 633 return group; 634 } 635 636 /** 637 * The group that this route belongs to; could be the name of the RouteBuilder class 638 * or be explicitly configured in the XML. 639 * <p/> 640 * May be null. 641 */ 642 @XmlAttribute 643 public void setGroup(String group) { 644 this.group = group; 645 } 646 647 /** 648 * Whether stream caching is enabled on this route. 649 */ 650 public String getStreamCache() { 651 return streamCache; 652 } 653 654 /** 655 * Whether stream caching is enabled on this route. 656 */ 657 @XmlAttribute 658 public void setStreamCache(String streamCache) { 659 this.streamCache = streamCache; 660 } 661 662 /** 663 * Whether tracing is enabled on this route. 664 */ 665 public String getTrace() { 666 return trace; 667 } 668 669 /** 670 * Whether tracing is enabled on this route. 671 */ 672 @XmlAttribute 673 public void setTrace(String trace) { 674 this.trace = trace; 675 } 676 677 /** 678 * Whether message history is enabled on this route. 679 */ 680 public String getMessageHistory() { 681 return messageHistory; 682 } 683 684 /** 685 * Whether message history is enabled on this route. 686 */ 687 @XmlAttribute @Metadata(defaultValue = "true") 688 public void setMessageHistory(String messageHistory) { 689 this.messageHistory = messageHistory; 690 } 691 692 /** 693 * Whether handle fault is enabled on this route. 694 */ 695 public String getHandleFault() { 696 return handleFault; 697 } 698 699 /** 700 * Whether handle fault is enabled on this route. 701 */ 702 @XmlAttribute 703 public void setHandleFault(String handleFault) { 704 this.handleFault = handleFault; 705 } 706 707 /** 708 * Whether to slow down processing messages by a given delay in msec. 709 */ 710 public String getDelayer() { 711 return delayer; 712 } 713 714 /** 715 * Whether to slow down processing messages by a given delay in msec. 716 */ 717 @XmlAttribute 718 public void setDelayer(String delayer) { 719 this.delayer = delayer; 720 } 721 722 /** 723 * Whether to auto start this route 724 */ 725 public String getAutoStartup() { 726 return autoStartup; 727 } 728 729 public boolean isAutoStartup(CamelContext camelContext) throws Exception { 730 if (getAutoStartup() == null) { 731 // should auto startup by default 732 return true; 733 } 734 Boolean isAutoStartup = CamelContextHelper.parseBoolean(camelContext, getAutoStartup()); 735 return isAutoStartup != null && isAutoStartup; 736 } 737 738 /** 739 * Whether to auto start this route 740 */ 741 @XmlAttribute @Metadata(defaultValue = "true") 742 public void setAutoStartup(String autoStartup) { 743 this.autoStartup = autoStartup; 744 } 745 746 /** 747 * To configure the ordering of the routes being started 748 */ 749 public Integer getStartupOrder() { 750 return startupOrder; 751 } 752 753 /** 754 * To configure the ordering of the routes being started 755 */ 756 @XmlAttribute 757 public void setStartupOrder(Integer startupOrder) { 758 this.startupOrder = startupOrder; 759 } 760 761 /** 762 * Sets the bean ref name of the error handler builder to use on this route 763 */ 764 @XmlAttribute 765 public void setErrorHandlerRef(String errorHandlerRef) { 766 this.errorHandlerRef = errorHandlerRef; 767 // we use an specific error handler ref (from Spring DSL) then wrap that 768 // with a error handler build ref so Camel knows its not just the default one 769 setErrorHandlerBuilder(new ErrorHandlerBuilderRef(errorHandlerRef)); 770 } 771 772 /** 773 * Sets the bean ref name of the error handler builder to use on this route 774 */ 775 public String getErrorHandlerRef() { 776 return errorHandlerRef; 777 } 778 779 /** 780 * Sets the error handler if one is not already set 781 */ 782 public void setErrorHandlerBuilderIfNull(ErrorHandlerFactory errorHandlerBuilder) { 783 if (this.errorHandlerBuilder == null) { 784 setErrorHandlerBuilder(errorHandlerBuilder); 785 } 786 } 787 788 /** 789 * Reference to custom {@link org.apache.camel.spi.RoutePolicy} to use by the route. 790 * Multiple policies can be configured by separating values using comma. 791 */ 792 @XmlAttribute 793 public void setRoutePolicyRef(String routePolicyRef) { 794 this.routePolicyRef = routePolicyRef; 795 } 796 797 /** 798 * Reference to custom {@link org.apache.camel.spi.RoutePolicy} to use by the route. 799 * Multiple policies can be configured by separating values using comma. 800 */ 801 public String getRoutePolicyRef() { 802 return routePolicyRef; 803 } 804 805 public List<RoutePolicy> getRoutePolicies() { 806 return routePolicies; 807 } 808 809 @XmlTransient 810 public void setRoutePolicies(List<RoutePolicy> routePolicies) { 811 this.routePolicies = routePolicies; 812 } 813 814 public ShutdownRoute getShutdownRoute() { 815 return shutdownRoute; 816 } 817 818 /** 819 * To control how to shutdown the route. 820 */ 821 @XmlAttribute @Metadata(defaultValue = "Default") 822 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 823 this.shutdownRoute = shutdownRoute; 824 } 825 826 /** 827 * To control how to shutdown the route. 828 */ 829 public ShutdownRunningTask getShutdownRunningTask() { 830 return shutdownRunningTask; 831 } 832 833 /** 834 * To control how to shutdown the route. 835 */ 836 @XmlAttribute @Metadata(defaultValue = "CompleteCurrentTaskOnly") 837 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 838 this.shutdownRunningTask = shutdownRunningTask; 839 } 840 841 private ErrorHandlerFactory createErrorHandlerBuilder() { 842 if (errorHandlerRef != null) { 843 return new ErrorHandlerBuilderRef(errorHandlerRef); 844 } 845 846 // return a reference to the default error handler 847 return new ErrorHandlerBuilderRef(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER); 848 } 849 850 @XmlTransient 851 public ErrorHandlerFactory getErrorHandlerBuilder() { 852 if (errorHandlerBuilder == null) { 853 errorHandlerBuilder = createErrorHandlerBuilder(); 854 } 855 return errorHandlerBuilder; 856 } 857 858 /** 859 * Sets the error handler to use with processors created by this builder 860 */ 861 public void setErrorHandlerBuilder(ErrorHandlerFactory errorHandlerBuilder) { 862 this.errorHandlerBuilder = errorHandlerBuilder; 863 } 864 865 @XmlAttribute 866 public Boolean isRest() { 867 return rest; 868 } 869 870 public RestDefinition getRestDefinition() { 871 return restDefinition; 872 } 873 874 @XmlTransient 875 public void setRestDefinition(RestDefinition restDefinition) { 876 this.restDefinition = restDefinition; 877 } 878 879 @SuppressWarnings("deprecation") 880 public boolean isContextScopedErrorHandler(CamelContext context) { 881 if (!contextScopedErrorHandler) { 882 return false; 883 } 884 // if error handler ref is configured it may refer to a context scoped, so we need to check this first 885 // the XML DSL will configure error handlers using refs, so we need this additional test 886 if (errorHandlerRef != null) { 887 ErrorHandlerFactory routeScoped = getErrorHandlerBuilder(); 888 ErrorHandlerFactory contextScoped = context.getErrorHandlerBuilder(); 889 return routeScoped != null && contextScoped != null && routeScoped == contextScoped; 890 } 891 892 return true; 893 } 894 895 // Implementation methods 896 // ------------------------------------------------------------------------- 897 protected RouteContext addRoutes(CamelContext camelContext, Collection<Route> routes, FromDefinition fromType) throws Exception { 898 RouteContext routeContext = new DefaultRouteContext(camelContext, this, fromType, routes); 899 900 // configure tracing 901 if (trace != null) { 902 Boolean isTrace = CamelContextHelper.parseBoolean(camelContext, getTrace()); 903 if (isTrace != null) { 904 routeContext.setTracing(isTrace); 905 if (isTrace) { 906 log.debug("Tracing is enabled on route: {}", getId()); 907 // tracing is added in the DefaultChannel so we can enable it on the fly 908 } 909 } 910 } 911 912 // configure message history 913 if (messageHistory != null) { 914 Boolean isMessageHistory = CamelContextHelper.parseBoolean(camelContext, getMessageHistory()); 915 if (isMessageHistory != null) { 916 routeContext.setMessageHistory(isMessageHistory); 917 if (isMessageHistory) { 918 log.debug("Message history is enabled on route: {}", getId()); 919 } 920 } 921 } 922 923 // configure stream caching 924 if (streamCache != null) { 925 Boolean isStreamCache = CamelContextHelper.parseBoolean(camelContext, getStreamCache()); 926 if (isStreamCache != null) { 927 routeContext.setStreamCaching(isStreamCache); 928 if (isStreamCache) { 929 log.debug("StreamCaching is enabled on route: {}", getId()); 930 } 931 } 932 } 933 934 // configure handle fault 935 if (handleFault != null) { 936 Boolean isHandleFault = CamelContextHelper.parseBoolean(camelContext, getHandleFault()); 937 if (isHandleFault != null) { 938 routeContext.setHandleFault(isHandleFault); 939 if (isHandleFault) { 940 log.debug("HandleFault is enabled on route: {}", getId()); 941 // only add a new handle fault if not already a global configured on camel context 942 if (HandleFault.getHandleFault(camelContext) == null) { 943 addInterceptStrategy(new HandleFault()); 944 } 945 } 946 } 947 } 948 949 // configure delayer 950 if (delayer != null) { 951 Long delayer = CamelContextHelper.parseLong(camelContext, getDelayer()); 952 if (delayer != null) { 953 routeContext.setDelayer(delayer); 954 if (delayer > 0) { 955 log.debug("Delayer is enabled with: {} ms. on route: {}", delayer, getId()); 956 } else { 957 log.debug("Delayer is disabled on route: {}", getId()); 958 } 959 } 960 } 961 962 // configure route policy 963 if (routePolicies != null && !routePolicies.isEmpty()) { 964 for (RoutePolicy policy : routePolicies) { 965 log.debug("RoutePolicy is enabled: {} on route: {}", policy, getId()); 966 routeContext.getRoutePolicyList().add(policy); 967 } 968 } 969 if (routePolicyRef != null) { 970 StringTokenizer policyTokens = new StringTokenizer(routePolicyRef, ","); 971 while (policyTokens.hasMoreTokens()) { 972 String ref = policyTokens.nextToken().trim(); 973 RoutePolicy policy = CamelContextHelper.mandatoryLookup(camelContext, ref, RoutePolicy.class); 974 log.debug("RoutePolicy is enabled: {} on route: {}", policy, getId()); 975 routeContext.getRoutePolicyList().add(policy); 976 } 977 } 978 if (camelContext.getRoutePolicyFactories() != null) { 979 for (RoutePolicyFactory factory : camelContext.getRoutePolicyFactories()) { 980 RoutePolicy policy = factory.createRoutePolicy(camelContext, getId(), this); 981 if (policy != null) { 982 log.debug("RoutePolicy is enabled: {} on route: {}", policy, getId()); 983 routeContext.getRoutePolicyList().add(policy); 984 } 985 } 986 } 987 988 // configure auto startup 989 Boolean isAutoStartup = CamelContextHelper.parseBoolean(camelContext, getAutoStartup()); 990 if (isAutoStartup != null) { 991 log.debug("Using AutoStartup {} on route: {}", isAutoStartup, getId()); 992 routeContext.setAutoStartup(isAutoStartup); 993 } 994 995 // configure shutdown 996 if (shutdownRoute != null) { 997 log.debug("Using ShutdownRoute {} on route: {}", getShutdownRoute(), getId()); 998 routeContext.setShutdownRoute(getShutdownRoute()); 999 } 1000 if (shutdownRunningTask != null) { 1001 log.debug("Using ShutdownRunningTask {} on route: {}", getShutdownRunningTask(), getId()); 1002 routeContext.setShutdownRunningTask(getShutdownRunningTask()); 1003 } 1004 1005 // should inherit the intercept strategies we have defined 1006 routeContext.setInterceptStrategies(this.getInterceptStrategies()); 1007 // force endpoint resolution 1008 routeContext.getEndpoint(); 1009 for (LifecycleStrategy strategy : camelContext.getLifecycleStrategies()) { 1010 strategy.onRouteContextCreate(routeContext); 1011 } 1012 1013 // validate route has output processors 1014 if (!ProcessorDefinitionHelper.hasOutputs(outputs, true)) { 1015 RouteDefinition route = routeContext.getRoute(); 1016 String at = fromType.toString(); 1017 Exception cause = new IllegalArgumentException("Route " + route.getId() + " has no output processors." 1018 + " You need to add outputs to the route such as to(\"log:foo\")."); 1019 throw new FailedToCreateRouteException(route.getId(), route.toString(), at, cause); 1020 } 1021 1022 List<ProcessorDefinition<?>> list = new ArrayList<ProcessorDefinition<?>>(outputs); 1023 for (ProcessorDefinition<?> output : list) { 1024 try { 1025 output.addRoutes(routeContext, routes); 1026 } catch (Exception e) { 1027 RouteDefinition route = routeContext.getRoute(); 1028 throw new FailedToCreateRouteException(route.getId(), route.toString(), output.toString(), e); 1029 } 1030 } 1031 1032 routeContext.commit(); 1033 return routeContext; 1034 } 1035}