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.builder; 018 019 import java.util.concurrent.atomic.AtomicBoolean; 020 021 import org.apache.camel.CamelContext; 022 import org.apache.camel.Endpoint; 023 import org.apache.camel.RoutesBuilder; 024 import org.apache.camel.impl.DefaultCamelContext; 025 import org.apache.camel.model.InterceptDefinition; 026 import org.apache.camel.model.InterceptFromDefinition; 027 import org.apache.camel.model.InterceptSendToEndpointDefinition; 028 import org.apache.camel.model.OnCompletionDefinition; 029 import org.apache.camel.model.OnExceptionDefinition; 030 import org.apache.camel.model.RouteDefinition; 031 import org.apache.camel.model.RoutesDefinition; 032 033 /** 034 * A <a href="http://camel.apache.org/dsl.html">Java DSL</a> which is 035 * used to build {@link org.apache.camel.impl.DefaultRoute} instances in a {@link CamelContext} for smart routing. 036 * 037 * @version $Revision: 982303 $ 038 */ 039 public abstract class RouteBuilder extends BuilderSupport implements RoutesBuilder { 040 private AtomicBoolean initialized = new AtomicBoolean(false); 041 private RoutesDefinition routeCollection = new RoutesDefinition(); 042 043 public RouteBuilder() { 044 this(null); 045 } 046 047 public RouteBuilder(CamelContext context) { 048 super(context); 049 } 050 051 @Override 052 public String toString() { 053 return routeCollection.toString(); 054 } 055 056 /** 057 * <b>Called on initialization to build the routes using the fluent builder syntax.</b> 058 * <p/> 059 * This is a central method for RouteBuilder implementations to implement 060 * the routes using the Java fluent builder syntax. 061 * 062 * @throws Exception can be thrown during configuration 063 */ 064 public abstract void configure() throws Exception; 065 066 /** 067 * Creates a new route from the given URI input 068 * 069 * @param uri the from uri 070 * @return the builder 071 */ 072 public RouteDefinition from(String uri) { 073 routeCollection.setCamelContext(getContext()); 074 RouteDefinition answer = routeCollection.from(uri); 075 configureRoute(answer); 076 return answer; 077 } 078 079 /** 080 * Creates a new route from the given URI input 081 * 082 * @param uri the String formatted from uri 083 * @param args arguments for the string formatting of the uri 084 * @return the builder 085 */ 086 public RouteDefinition fromF(String uri, Object... args) { 087 routeCollection.setCamelContext(getContext()); 088 RouteDefinition answer = routeCollection.from(String.format(uri, args)); 089 configureRoute(answer); 090 return answer; 091 } 092 093 /** 094 * Creates a new route from the given endpoint 095 * 096 * @param endpoint the from endpoint 097 * @return the builder 098 */ 099 public RouteDefinition from(Endpoint endpoint) { 100 routeCollection.setCamelContext(getContext()); 101 RouteDefinition answer = routeCollection.from(endpoint); 102 configureRoute(answer); 103 return answer; 104 } 105 106 /** 107 * Creates a new route from the given URIs input 108 * 109 * @param uris the from uris 110 * @return the builder 111 */ 112 public RouteDefinition from(String... uris) { 113 routeCollection.setCamelContext(getContext()); 114 RouteDefinition answer = routeCollection.from(uris); 115 configureRoute(answer); 116 return answer; 117 } 118 119 /** 120 * Creates a new route from the given endpoint 121 * 122 * @param endpoints the from endpoints 123 * @return the builder 124 */ 125 public RouteDefinition from(Endpoint... endpoints) { 126 routeCollection.setCamelContext(getContext()); 127 RouteDefinition answer = routeCollection.from(endpoints); 128 configureRoute(answer); 129 return answer; 130 } 131 132 /** 133 * Installs the given <a href="http://camel.apache.org/error-handler.html">error handler</a> builder 134 * 135 * @param errorHandlerBuilder the error handler to be used by default for all child routes 136 * @return the current builder with the error handler configured 137 */ 138 public RouteBuilder errorHandler(ErrorHandlerBuilder errorHandlerBuilder) { 139 routeCollection.setCamelContext(getContext()); 140 setErrorHandlerBuilder(errorHandlerBuilder); 141 return this; 142 } 143 144 /** 145 * Adds a route for an interceptor that intercepts every processing step. 146 * 147 * @return the builder 148 */ 149 public InterceptDefinition intercept() { 150 routeCollection.setCamelContext(getContext()); 151 return routeCollection.intercept(); 152 } 153 154 /** 155 * Adds a route for an interceptor that intercepts incoming messages on any inputs in this route 156 * 157 * @return the builder 158 */ 159 public InterceptFromDefinition interceptFrom() { 160 routeCollection.setCamelContext(getContext()); 161 return routeCollection.interceptFrom(); 162 } 163 164 /** 165 * Adds a route for an interceptor that intercepts incoming messages on the given endpoint. 166 * 167 * @param uri endpoint uri 168 * @return the builder 169 */ 170 public InterceptFromDefinition interceptFrom(String uri) { 171 routeCollection.setCamelContext(getContext()); 172 return routeCollection.interceptFrom(uri); 173 } 174 175 /** 176 * Applies a route for an interceptor if an exchange is send to the given endpoint 177 * 178 * @param uri endpoint uri 179 * @return the builder 180 */ 181 public InterceptSendToEndpointDefinition interceptSendToEndpoint(String uri) { 182 routeCollection.setCamelContext(getContext()); 183 return routeCollection.interceptSendToEndpoint(uri); 184 } 185 186 /** 187 * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a> 188 * for catching certain exceptions and handling them. 189 * 190 * @param exception exception to catch 191 * @return the builder 192 */ 193 public OnExceptionDefinition onException(Class exception) { 194 routeCollection.setCamelContext(getContext()); 195 return routeCollection.onException(exception); 196 } 197 198 /** 199 * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a> 200 * for catching certain exceptions and handling them. 201 * 202 * @param exceptions list of exceptions to catch 203 * @return the builder 204 */ 205 public OnExceptionDefinition onException(Class... exceptions) { 206 OnExceptionDefinition last = null; 207 for (Class ex : exceptions) { 208 last = last == null ? onException(ex) : last.onException(ex); 209 } 210 return last != null ? last : onException(Exception.class); 211 } 212 213 /** 214 * <a href="http://camel.apache.org/oncompletion.html">On completion</a> 215 * callback for doing custom routing when the {@link org.apache.camel.Exchange} is complete. 216 * 217 * @return the builder 218 */ 219 public OnCompletionDefinition onCompletion() { 220 routeCollection.setCamelContext(getContext()); 221 return routeCollection.onCompletion(); 222 } 223 224 // Properties 225 // ----------------------------------------------------------------------- 226 public CamelContext getContext() { 227 CamelContext context = super.getContext(); 228 if (context == null) { 229 context = createContainer(); 230 setContext(context); 231 } 232 return context; 233 } 234 235 public void addRoutesToCamelContext(CamelContext context) throws Exception { 236 configureRoutes(context); 237 // add routes to Camel by populating them 238 populateRoutes(); 239 } 240 241 /** 242 * Configures the routes 243 * 244 * @param context the Camel context 245 * @return the routes configured 246 * @throws Exception can be thrown during configuration 247 */ 248 public RoutesDefinition configureRoutes(CamelContext context) throws Exception { 249 setContext(context); 250 checkInitialized(); 251 routeCollection.setCamelContext(context); 252 return routeCollection; 253 } 254 255 /** 256 * Includes the routes from the build to this builder. 257 * <p/> 258 * This allows you to use other builds as route templates. 259 * @param routes other builder with routes to include 260 * 261 * @throws Exception can be thrown during configuration 262 */ 263 public void includeRoutes(RoutesBuilder routes) throws Exception { 264 // TODO: We should support including multiple routes so I think invoking configure() 265 // needs to be deferred to later 266 if (routes instanceof RouteBuilder) { 267 // if its a RouteBuilder then let it use my route collection and error handler 268 // then we are integrated seamless 269 RouteBuilder builder = (RouteBuilder) routes; 270 builder.setContext(this.getContext()); 271 builder.setRouteCollection(this.getRouteCollection()); 272 builder.setErrorHandlerBuilder(this.getErrorHandlerBuilder()); 273 // must invoke configure on the original builder so it adds its configuration to me 274 builder.configure(); 275 } else { 276 getContext().addRoutes(routes); 277 } 278 } 279 280 @Override 281 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) { 282 super.setErrorHandlerBuilder(errorHandlerBuilder); 283 routeCollection.setErrorHandlerBuilder(getErrorHandlerBuilder()); 284 } 285 286 // Implementation methods 287 // ----------------------------------------------------------------------- 288 protected void checkInitialized() throws Exception { 289 if (initialized.compareAndSet(false, true)) { 290 // Set the CamelContext ErrorHandler here 291 CamelContext camelContext = getContext(); 292 if (camelContext.getErrorHandlerBuilder() != null) { 293 setErrorHandlerBuilder(camelContext.getErrorHandlerBuilder()); 294 } 295 configure(); 296 // mark all route definitions as custom prepared because 297 // a route builder prepares the route definitions correctly already 298 for (RouteDefinition route : getRouteCollection().getRoutes()) { 299 route.customPrepared(); 300 } 301 } 302 } 303 304 protected void populateRoutes() throws Exception { 305 CamelContext camelContext = getContext(); 306 if (camelContext == null) { 307 throw new IllegalArgumentException("CamelContext has not been injected!"); 308 } 309 routeCollection.setCamelContext(camelContext); 310 camelContext.addRouteDefinitions(routeCollection.getRoutes()); 311 } 312 313 public void setRouteCollection(RoutesDefinition routeCollection) { 314 this.routeCollection = routeCollection; 315 } 316 317 public RoutesDefinition getRouteCollection() { 318 return this.routeCollection; 319 } 320 321 /** 322 * Factory method 323 */ 324 protected CamelContext createContainer() { 325 return new DefaultCamelContext(); 326 } 327 328 protected void configureRoute(RouteDefinition route) { 329 route.setGroup(getClass().getName()); 330 } 331 332 /** 333 * Adds a collection of routes to this context 334 * 335 * @throws Exception if the routes could not be created for whatever reason 336 * @deprecated use {@link #includeRoutes(org.apache.camel.RoutesBuilder) includeRoutes} instead. 337 */ 338 @Deprecated 339 protected void addRoutes(RoutesBuilder routes) throws Exception { 340 includeRoutes(routes); 341 } 342 343 }