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: 881279 $
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 }
297 }
298
299 protected void populateRoutes() throws Exception {
300 CamelContext camelContext = getContext();
301 if (camelContext == null) {
302 throw new IllegalArgumentException("CamelContext has not been injected!");
303 }
304 routeCollection.setCamelContext(camelContext);
305 camelContext.addRouteDefinitions(routeCollection.getRoutes());
306 }
307
308 public void setRouteCollection(RoutesDefinition routeCollection) {
309 this.routeCollection = routeCollection;
310 }
311
312 public RoutesDefinition getRouteCollection() {
313 return this.routeCollection;
314 }
315
316 /**
317 * Factory method
318 */
319 protected CamelContext createContainer() {
320 return new DefaultCamelContext();
321 }
322
323 protected void configureRoute(RouteDefinition route) {
324 route.setGroup(getClass().getName());
325 }
326
327 /**
328 * Adds a collection of routes to this context
329 *
330 * @throws Exception if the routes could not be created for whatever reason
331 * @deprecated use {@link #includeRoutes(org.apache.camel.RoutesBuilder) includeRoutes} instead.
332 */
333 @Deprecated
334 protected void addRoutes(RoutesBuilder routes) throws Exception {
335 includeRoutes(routes);
336 }
337
338 }