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.ArrayList;
020 import java.util.List;
021 import java.util.concurrent.atomic.AtomicBoolean;
022
023 import org.apache.camel.CamelContext;
024 import org.apache.camel.Endpoint;
025 import org.apache.camel.Predicate;
026 import org.apache.camel.Route;
027 import org.apache.camel.Routes;
028 import org.apache.camel.impl.DefaultCamelContext;
029 import org.apache.camel.model.ChoiceDefinition;
030 import org.apache.camel.model.InterceptDefinition;
031 import org.apache.camel.model.OnExceptionDefinition;
032 import org.apache.camel.model.RouteDefinition;
033 import org.apache.camel.model.RoutesDefinition;
034 import org.apache.camel.processor.DelegateProcessor;
035 import org.apache.camel.processor.interceptor.StreamCachingInterceptor;
036
037 /**
038 * A <a href="http://camel.apache.org/dsl.html">Java DSL</a> which is
039 * used to build {@link Route} instances in a {@link CamelContext} for smart routing.
040 *
041 * @version $Revision: 751655 $
042 */
043 public abstract class RouteBuilder extends BuilderSupport implements Routes {
044 private AtomicBoolean initialized = new AtomicBoolean(false);
045 private RoutesDefinition routeCollection = new RoutesDefinition();
046 private List<Route> routes = new ArrayList<Route>();
047
048 public RouteBuilder() {
049 this(null);
050 }
051
052 public RouteBuilder(CamelContext context) {
053 super(context);
054 }
055
056 @Override
057 public String toString() {
058 return routeCollection.toString();
059 }
060
061 /**
062 * <b>Called on initialization to build the routes using the fluent builder syntax.</b>
063 * <p/>
064 * This is a central method for RouteBuilder implementations to implement
065 * the routes using the Java fluent builder syntax.
066 *
067 * @throws Exception can be thrown during configuration
068 */
069 public abstract void configure() throws Exception;
070
071 /**
072 * Creates a new route from the given URI input
073 *
074 * @param uri the from uri
075 * @return the builder
076 */
077 public RouteDefinition from(String uri) {
078 RouteDefinition answer = routeCollection.from(uri);
079 configureRoute(answer);
080 return answer;
081 }
082
083 /**
084 * Creates a new route from the given endpoint
085 *
086 * @param endpoint the from endpoint
087 * @return the builder
088 */
089 public RouteDefinition from(Endpoint endpoint) {
090 RouteDefinition answer = routeCollection.from(endpoint);
091 configureRoute(answer);
092 return answer;
093 }
094
095 /**
096 * Creates a new route from the given URIs input
097 *
098 * @param uris the from uris
099 * @return the builder
100 */
101 public RouteDefinition from(String... uris) {
102 RouteDefinition answer = routeCollection.from(uris);
103 configureRoute(answer);
104 return answer;
105 }
106
107 /**
108 * Creates a new route from the given endpoint
109 *
110 * @param endpoints the from endpoints
111 * @return the builder
112 */
113 public RouteDefinition from(Endpoint... endpoints) {
114 RouteDefinition answer = routeCollection.from(endpoints);
115 configureRoute(answer);
116 return answer;
117 }
118
119 /**
120 * Installs the given <a href="http://camel.apache.org/error-handler.html">error handler</a> builder
121 *
122 * @param errorHandlerBuilder the error handler to be used by default for all child routes
123 * @return the current builder with the error handler configured
124 */
125 public RouteBuilder errorHandler(ErrorHandlerBuilder errorHandlerBuilder) {
126 setErrorHandlerBuilder(errorHandlerBuilder);
127 return this;
128 }
129
130 /**
131 * Configures whether or not the <a href="http://camel.apache.org/error-handler.html">error handler</a>
132 * is inherited by every processing node (or just the top most one)
133 *
134 * @param inherit whether error handlers should be inherited or not
135 * @return the current builder
136 */
137 public RouteBuilder inheritErrorHandler(boolean inherit) {
138 routeCollection.setInheritErrorHandlerFlag(inherit);
139 return this;
140 }
141
142 /**
143 * Adds the given interceptor to this route
144 *
145 * @param interceptor the interceptor
146 * @return the builder
147 */
148 public RouteBuilder intercept(DelegateProcessor interceptor) {
149 routeCollection.intercept(interceptor);
150 return this;
151 }
152
153 /**
154 * Adds a route for an interceptor; use the {@link org.apache.camel.model.ProcessorDefinition#proceed()} method
155 * to continue processing the underlying route being intercepted.
156 * @return the builder
157 */
158 public InterceptDefinition intercept() {
159 return routeCollection.intercept();
160 }
161
162 /**
163 * Applies a route for an interceptor if the given predicate is true
164 * otherwise the interceptor route is not applied
165 *
166 * @param predicate the predicate
167 * @return the builder
168 */
169 public ChoiceDefinition intercept(Predicate predicate) {
170 return routeCollection.intercept(predicate);
171 }
172
173 /**
174 * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
175 * for catching certain exceptions and handling them.
176 *
177 * @param exception exception to catch
178 * @return the builder
179 */
180 public OnExceptionDefinition onException(Class exception) {
181 return routeCollection.onException(exception);
182 }
183
184 /**
185 * <a href="http://camel.apache.org/exception-clause.html">Exception clause</a>
186 * for catching certain exceptions and handling them.
187 *
188 * @param exceptions list of exceptions to catch
189 * @return the builder
190 */
191 public OnExceptionDefinition onException(Class... exceptions) {
192 OnExceptionDefinition last = null;
193 for (Class ex : exceptions) {
194 last = last == null ? onException(ex) : last.onException(ex);
195 }
196 return last != null ? last : onException(Exception.class);
197 }
198
199 // Properties
200 // -----------------------------------------------------------------------
201 public CamelContext getContext() {
202 CamelContext context = super.getContext();
203 if (context == null) {
204 context = createContainer();
205 setContext(context);
206 }
207 return context;
208 }
209
210 /**
211 * Uses {@link org.apache.camel.CamelContext#getRoutes()} to return the routes in the context.
212 */
213 public List<Route> getRouteList() throws Exception {
214 checkInitialized();
215 return routes;
216 }
217
218 @Override
219 public void setInheritErrorHandler(boolean inheritErrorHandler) {
220 super.setInheritErrorHandler(inheritErrorHandler);
221 routeCollection.setInheritErrorHandlerFlag(inheritErrorHandler);
222
223 }
224
225 @Override
226 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
227 super.setErrorHandlerBuilder(errorHandlerBuilder);
228 routeCollection.setErrorHandlerBuilder(getErrorHandlerBuilder());
229 }
230
231 // Implementation methods
232 // -----------------------------------------------------------------------
233 protected void checkInitialized() throws Exception {
234 if (initialized.compareAndSet(false, true)) {
235 // Set the CamelContext ErrorHandler here
236 CamelContext camelContext = getContext();
237 if (camelContext.getErrorHandlerBuilder() != null) {
238 setErrorHandlerBuilder(camelContext.getErrorHandlerBuilder());
239 }
240 configure();
241 populateRoutes(routes);
242 }
243 }
244
245 protected void populateRoutes(List<Route> routes) throws Exception {
246 CamelContext camelContext = getContext();
247 if (camelContext == null) {
248 throw new IllegalArgumentException("CamelContext has not been injected!");
249 }
250 routeCollection.setCamelContext(camelContext);
251 camelContext.addRouteDefinitions(routeCollection.getRoutes());
252 }
253
254 public void setRouteCollection(RoutesDefinition routeCollection) {
255 this.routeCollection = routeCollection;
256 }
257
258 public RoutesDefinition getRouteCollection() {
259 return this.routeCollection;
260 }
261
262 /**
263 * Completely disable stream caching for all routes being defined in the same RouteBuilder after this.
264 */
265 public void noStreamCaching() {
266 StreamCachingInterceptor.noStreamCaching(routeCollection.getInterceptors());
267 }
268
269 /**
270 * Enable stream caching for all routes being defined in the same RouteBuilder after this call.
271 */
272 public void streamCaching() {
273 routeCollection.intercept(new StreamCachingInterceptor());
274 }
275
276 /**
277 * Factory method
278 */
279 protected CamelContext createContainer() {
280 return new DefaultCamelContext();
281 }
282
283 protected void configureRoute(RouteDefinition route) {
284 route.setGroup(getClass().getName());
285 }
286
287 /**
288 * Adds a collection of routes to this context
289 *
290 * @throws Exception if the routes could not be created for whatever reason
291 */
292 protected void addRoutes(Routes routes) throws Exception {
293 getContext().addRoutes(routes);
294 }
295 }