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.impl.DefaultCamelContext;
028    import org.apache.camel.model.ChoiceType;
029    import org.apache.camel.model.ExceptionType;
030    import org.apache.camel.model.InterceptType;
031    import org.apache.camel.model.InterceptorRef;
032    import org.apache.camel.model.InterceptorType;
033    import org.apache.camel.model.ProcessorType;
034    import org.apache.camel.model.RouteType;
035    import org.apache.camel.model.RoutesType;
036    import org.apache.camel.processor.DelegateProcessor;
037    import org.apache.camel.processor.interceptor.StreamCachingInterceptor;
038    
039    /**
040     * A <a href="http://activemq.apache.org/camel/dsl.html">Java DSL</a> which is
041     * used to build {@link Route} instances in a {@link CamelContext} for smart routing.
042     *
043     * @version $Revision: 642753 $
044     */
045    public abstract class RouteBuilder extends BuilderSupport {
046        private AtomicBoolean initalized = new AtomicBoolean(false);
047        private RoutesType routeCollection = new RoutesType();
048        private List<Route> routes = new ArrayList<Route>();
049    
050        public RouteBuilder() {
051            this(null);
052        }
053    
054        public RouteBuilder(CamelContext context) {
055            super(context);
056        }
057    
058        @Override
059        public String toString() {
060            return routeCollection.toString();
061        }
062    
063        /**
064         * Called on initialization to to build the required destinationBuilders
065         */
066        public abstract void configure() throws Exception;
067    
068        /**
069         * Creates a new route from the given URI input
070         */
071        public RouteType from(String uri) {
072            RouteType answer = routeCollection.from(uri);
073            configureRoute(answer);
074            return answer;
075        }
076    
077        /**
078         * Creates a new route from the given endpoint
079         */
080        public RouteType from(Endpoint endpoint) {
081            RouteType answer = routeCollection.from(endpoint);
082            configureRoute(answer);
083            return answer;
084        }
085    
086        /**
087         * Installs the given error handler builder
088         *
089         * @param errorHandlerBuilder the error handler to be used by default for
090         *                all child routes
091         * @return the current builder with the error handler configured
092         */
093        public RouteBuilder errorHandler(ErrorHandlerBuilder errorHandlerBuilder) {
094            setErrorHandlerBuilder(errorHandlerBuilder);
095            return this;
096        }
097    
098        /**
099         * Configures whether or not the error handler is inherited by every
100         * processing node (or just the top most one)
101         *
102         * @param value the flag as to whether error handlers should be inherited or
103         *                not
104         * @return the current builder
105         */
106        public RouteBuilder inheritErrorHandler(boolean value) {
107            routeCollection.setInheritErrorHandlerFlag(value);
108            return this;
109        }
110    
111        /**
112         * Adds the given interceptor to this route
113         */
114        public RouteBuilder intercept(DelegateProcessor interceptor) {
115            routeCollection.intercept(interceptor);
116            return this;
117        }
118    
119        /**
120         * Adds a route for an interceptor; use the {@link ProcessorType#proceed()} method
121         * to continue processing the underying route being intercepted.
122         */
123        public InterceptType intercept() {
124            return routeCollection.intercept();
125        }
126    
127        /**
128         * Applies a route for an interceptor if the given predicate is true
129         * otherwise the interceptor route is not applied
130         */
131        public ChoiceType intercept(Predicate predicate) {
132            return routeCollection.intercept(predicate);
133        }
134    
135        /**
136         * Adds an exception handler route for the given exception type
137         */
138        public ExceptionType exception(Class exceptionType) {
139            return routeCollection.exception(exceptionType);
140        }
141    
142        // Properties
143        // -----------------------------------------------------------------------
144        public CamelContext getContext() {
145            CamelContext context = super.getContext();
146            if (context == null) {
147                context = createContainer();
148                setContext(context);
149            }
150            return context;
151        }
152    
153        /**
154         * Returns the routing map from inbound endpoints to processors
155         */
156        public List<Route> getRouteList() throws Exception {
157            checkInitialized();
158            return routes;
159        }
160    
161        @Override
162        public void setInheritErrorHandler(boolean inheritErrorHandler) {
163            super.setInheritErrorHandler(inheritErrorHandler);
164            routeCollection.setInheritErrorHandlerFlag(inheritErrorHandler);
165    
166        }
167    
168        @Override
169        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
170            super.setErrorHandlerBuilder(errorHandlerBuilder);
171            routeCollection.setErrorHandlerBuilder(getErrorHandlerBuilder());
172        }
173    
174        // Implementation methods
175        // -----------------------------------------------------------------------
176        protected void checkInitialized() throws Exception {
177            if (initalized.compareAndSet(false, true)) {
178                configure();
179                populateRoutes(routes);
180            }
181        }
182    
183        protected void populateRoutes(List<Route> routes) throws Exception {
184            CamelContext camelContext = getContext();
185            if (camelContext == null) {
186                throw new IllegalArgumentException("No CamelContext has been injected!");
187            }
188            routeCollection.setCamelContext(camelContext);
189            camelContext.addRouteDefinitions(routeCollection.getRoutes());
190        }
191    
192        public void setRouteCollection(RoutesType routeCollection) {
193            this.routeCollection = routeCollection;
194        }
195    
196        public RoutesType getRouteCollection() {
197            return this.routeCollection;
198        }
199        
200        /**
201         * Completely disable stream caching for all routes being defined in the same RouteBuilder after this. 
202         */
203        public void noStreamCaching() {
204            StreamCachingInterceptor.noStreamCaching(routeCollection.getInterceptors());
205        }
206        
207        /**
208         * Enable stream caching for all routes being defined in the same RouteBuilder after this call.
209         */
210        public void streamCaching() {
211            routeCollection.intercept(new StreamCachingInterceptor());
212        }
213        
214        /**
215         * Factory method
216         */
217        protected CamelContext createContainer() {
218            return new DefaultCamelContext();
219        }
220    
221        protected void configureRoute(RouteType route) {
222            route.setGroup(getClass().getName());
223        }
224    }