/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.builder; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.RoutesBuilder; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.model.InterceptDefinition; import org.apache.camel.model.InterceptFromDefinition; import org.apache.camel.model.InterceptSendToEndpointDefinition; import org.apache.camel.model.ModelCamelContext; import org.apache.camel.model.OnCompletionDefinition; import org.apache.camel.model.OnExceptionDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.model.RoutesDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Java DSL which is * used to build {@link org.apache.camel.impl.DefaultRoute} instances in a {@link CamelContext} for smart routing. * * @version */ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuilder { protected Logger log = LoggerFactory.getLogger(getClass()); private AtomicBoolean initialized = new AtomicBoolean(false); private RoutesDefinition routeCollection = new RoutesDefinition(); public RouteBuilder() { this(null); } public RouteBuilder(CamelContext context) { super(context); } @Override public String toString() { return getRouteCollection().toString(); } /** * Called on initialization to build the routes using the fluent builder syntax. *

* This is a central method for RouteBuilder implementations to implement * the routes using the Java fluent builder syntax. * * @throws Exception can be thrown during configuration */ public abstract void configure() throws Exception; /** * Creates a new route from the given URI input * * @param uri the from uri * @return the builder */ public RouteDefinition from(String uri) { getRouteCollection().setCamelContext(getContext()); RouteDefinition answer = getRouteCollection().from(uri); configureRoute(answer); return answer; } /** * Creates a new route from the given URI input * * @param uri the String formatted from uri * @param args arguments for the string formatting of the uri * @return the builder */ public RouteDefinition fromF(String uri, Object... args) { getRouteCollection().setCamelContext(getContext()); RouteDefinition answer = getRouteCollection().from(String.format(uri, args)); configureRoute(answer); return answer; } /** * Creates a new route from the given endpoint * * @param endpoint the from endpoint * @return the builder */ public RouteDefinition from(Endpoint endpoint) { getRouteCollection().setCamelContext(getContext()); RouteDefinition answer = getRouteCollection().from(endpoint); configureRoute(answer); return answer; } /** * Creates a new route from the given URIs input * * @param uris the from uris * @return the builder */ public RouteDefinition from(String... uris) { getRouteCollection().setCamelContext(getContext()); RouteDefinition answer = getRouteCollection().from(uris); configureRoute(answer); return answer; } /** * Creates a new route from the given endpoint * * @param endpoints the from endpoints * @return the builder */ public RouteDefinition from(Endpoint... endpoints) { getRouteCollection().setCamelContext(getContext()); RouteDefinition answer = getRouteCollection().from(endpoints); configureRoute(answer); return answer; } /** * Installs the given error handler builder * * @param errorHandlerBuilder the error handler to be used by default for all child routes */ public void errorHandler(ErrorHandlerBuilder errorHandlerBuilder) { if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("errorHandler must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); setErrorHandlerBuilder(errorHandlerBuilder); } /** * Adds a route for an interceptor that intercepts every processing step. * * @return the builder */ public InterceptDefinition intercept() { if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("intercept must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().intercept(); } /** * Adds a route for an interceptor that intercepts incoming messages on any inputs in this route * * @return the builder */ public InterceptFromDefinition interceptFrom() { if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("interceptFrom must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().interceptFrom(); } /** * Adds a route for an interceptor that intercepts incoming messages on the given endpoint. * * @param uri endpoint uri * @return the builder */ public InterceptFromDefinition interceptFrom(String uri) { if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("interceptFrom must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().interceptFrom(uri); } /** * Applies a route for an interceptor if an exchange is send to the given endpoint * * @param uri endpoint uri * @return the builder */ public InterceptSendToEndpointDefinition interceptSendToEndpoint(String uri) { if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("interceptSendToEndpoint must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().interceptSendToEndpoint(uri); } /** * Exception clause * for catching certain exceptions and handling them. * * @param exception exception to catch * @return the builder */ public OnExceptionDefinition onException(Class exception) { // is only allowed at the top currently if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("onException must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().onException(exception); } /** * Exception clause * for catching certain exceptions and handling them. * * @param exceptions list of exceptions to catch * @return the builder */ public OnExceptionDefinition onException(Class... exceptions) { OnExceptionDefinition last = null; for (Class ex : exceptions) { last = last == null ? onException(ex) : last.onException(ex); } return last != null ? last : onException(Exception.class); } /** * On completion * callback for doing custom routing when the {@link org.apache.camel.Exchange} is complete. * * @return the builder */ public OnCompletionDefinition onCompletion() { // is only allowed at the top currently if (!getRouteCollection().getRoutes().isEmpty()) { throw new IllegalArgumentException("onCompletion must be defined before any routes in the RouteBuilder"); } getRouteCollection().setCamelContext(getContext()); return getRouteCollection().onCompletion(); } // Properties // ----------------------------------------------------------------------- public ModelCamelContext getContext() { ModelCamelContext context = super.getContext(); if (context == null) { context = createContainer(); setContext(context); } return context; } public void addRoutesToCamelContext(CamelContext context) throws Exception { configureRoutes((ModelCamelContext)context); // add routes to Camel by populating them populateRoutes(); } /** * Configures the routes * * @param context the Camel context * @return the routes configured * @throws Exception can be thrown during configuration */ public RoutesDefinition configureRoutes(ModelCamelContext context) throws Exception { setContext(context); checkInitialized(); routeCollection.setCamelContext(context); return routeCollection; } /** * Includes the routes from the build to this builder. *

* This allows you to use other builds as route templates. * @param routes other builder with routes to include * * @throws Exception can be thrown during configuration */ public void includeRoutes(RoutesBuilder routes) throws Exception { // TODO: We should support including multiple routes so I think invoking configure() // needs to be deferred to later if (routes instanceof RouteBuilder) { // if its a RouteBuilder then let it use my route collection and error handler // then we are integrated seamless RouteBuilder builder = (RouteBuilder) routes; builder.setContext(this.getContext()); builder.setRouteCollection(this.getRouteCollection()); builder.setErrorHandlerBuilder(this.getErrorHandlerBuilder()); // must invoke configure on the original builder so it adds its configuration to me builder.configure(); } else { getContext().addRoutes(routes); } } @Override public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) { super.setErrorHandlerBuilder(errorHandlerBuilder); getRouteCollection().setErrorHandlerBuilder(getErrorHandlerBuilder()); } // Implementation methods // ----------------------------------------------------------------------- @SuppressWarnings("deprecation") protected void checkInitialized() throws Exception { if (initialized.compareAndSet(false, true)) { // Set the CamelContext ErrorHandler here ModelCamelContext camelContext = getContext(); if (camelContext.getErrorHandlerBuilder() != null) { setErrorHandlerBuilder(camelContext.getErrorHandlerBuilder()); } configure(); // mark all route definitions as custom prepared because // a route builder prepares the route definitions correctly already for (RouteDefinition route : getRouteCollection().getRoutes()) { route.markPrepared(); } } } protected void populateRoutes() throws Exception { ModelCamelContext camelContext = getContext(); if (camelContext == null) { throw new IllegalArgumentException("CamelContext has not been injected!"); } getRouteCollection().setCamelContext(camelContext); camelContext.addRouteDefinitions(getRouteCollection().getRoutes()); } public void setRouteCollection(RoutesDefinition routeCollection) { this.routeCollection = routeCollection; } public RoutesDefinition getRouteCollection() { return this.routeCollection; } /** * Factory method * * @return the CamelContext */ protected ModelCamelContext createContainer() { return new DefaultCamelContext(); } protected void configureRoute(RouteDefinition route) { route.setGroup(getClass().getName()); } /** * Adds a collection of routes to this context * * @param routes the routes * @throws Exception if the routes could not be created for whatever reason * @deprecated will be removed in Camel 3.0. Instead use {@link #includeRoutes(org.apache.camel.RoutesBuilder) includeRoutes} instead. */ @Deprecated protected void addRoutes(RoutesBuilder routes) throws Exception { includeRoutes(routes); } }