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