blob: 91722c553c07f241997e4b0a80818c6cf16295f1 [file] [log] [blame]
/**
* 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.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 <a href="http://camel.apache.org/dsl.html">Java DSL</a> 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();
}
/**
* <b>Called on initialization to build the routes using the fluent builder syntax.</b>
* <p/>
* 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 <a href="http://camel.apache.org/error-handler.html">error handler</a> builder
*
* @param errorHandlerBuilder the error handler to be used by default for all child routes
* @return the current builder with the error handler configured
*/
public RouteBuilder 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);
return this;
}
/**
* 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);
}
/**
* <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
* 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);
}
/**
* <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
* 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);
}
/**
* <a href="http://camel.apache.org/oncompletion.html">On completion</a>
* 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 CamelContext getContext() {
CamelContext context = super.getContext();
if (context == null) {
context = createContainer();
setContext(context);
}
return context;
}
public void addRoutesToCamelContext(CamelContext context) throws Exception {
configureRoutes(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(CamelContext context) throws Exception {
setContext(context);
checkInitialized();
routeCollection.setCamelContext(context);
return routeCollection;
}
/**
* Includes the routes from the build to this builder.
* <p/>
* 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
// -----------------------------------------------------------------------
protected void checkInitialized() throws Exception {
if (initialized.compareAndSet(false, true)) {
// Set the CamelContext ErrorHandler here
CamelContext 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 {
CamelContext 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 CamelContext 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);
}
}