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