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: 52414 $
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 onException(Class exceptionType) {
137            return routeCollection.exception(exceptionType);
138        }
139    
140        /**
141         * Adds an exception handler route for the given exception type
142         *
143         * @deprecated Please use {@link #onException(Class)} instead. Will be removed in Camel 2.0.
144         */
145        public ExceptionType exception(Class exceptionType) {
146            return onException(exceptionType);
147        }    
148        
149        // Properties
150        // -----------------------------------------------------------------------
151        public CamelContext getContext() {
152            CamelContext context = super.getContext();
153            if (context == null) {
154                context = createContainer();
155                setContext(context);
156            }
157            return context;
158        }
159    
160        /**
161         * Uses {@link org.apache.camel.CamelContext#getRoutes()} to return the routes in the context.
162         */
163        public List<Route> getRouteList() throws Exception {
164            checkInitialized();
165            return routes;
166        }
167    
168        @Override
169        public void setInheritErrorHandler(boolean inheritErrorHandler) {
170            super.setInheritErrorHandler(inheritErrorHandler);
171            routeCollection.setInheritErrorHandlerFlag(inheritErrorHandler);
172    
173        }
174    
175        @Override
176        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
177            super.setErrorHandlerBuilder(errorHandlerBuilder);
178            routeCollection.setErrorHandlerBuilder(getErrorHandlerBuilder());
179        }
180    
181        // Implementation methods
182        // -----------------------------------------------------------------------
183        protected void checkInitialized() throws Exception {
184            if (initialized.compareAndSet(false, true)) {
185                // Set the CamelContext ErrorHandler here
186                CamelContext camelContext = getContext();
187                if (camelContext.getErrorHandlerBuilder() != null) {
188                    setErrorHandlerBuilder(camelContext.getErrorHandlerBuilder());
189                }
190                configure();
191                populateRoutes(routes);
192            }
193        }
194    
195        protected void populateRoutes(List<Route> routes) throws Exception {
196            CamelContext camelContext = getContext();
197            if (camelContext == null) {
198                throw new IllegalArgumentException("No CamelContext has been injected!");
199            }
200            routeCollection.setCamelContext(camelContext);
201            camelContext.addRouteDefinitions(routeCollection.getRoutes());
202        }
203    
204        public void setRouteCollection(RoutesType routeCollection) {
205            this.routeCollection = routeCollection;
206        }
207    
208        public RoutesType getRouteCollection() {
209            return this.routeCollection;
210        }
211    
212        /**
213         * Completely disable stream caching for all routes being defined in the same RouteBuilder after this.
214         */
215        public void noStreamCaching() {
216            StreamCachingInterceptor.noStreamCaching(routeCollection.getInterceptors());
217        }
218    
219        /**
220         * Enable stream caching for all routes being defined in the same RouteBuilder after this call.
221         */
222        public void streamCaching() {
223            routeCollection.intercept(new StreamCachingInterceptor());
224        }
225    
226        /**
227         * Factory method
228         */
229        protected CamelContext createContainer() {
230            return new DefaultCamelContext();
231        }
232    
233        protected void configureRoute(RouteType route) {
234            route.setGroup(getClass().getName());
235        }
236    
237        protected void addRoutes(Routes routes) throws Exception {
238            getContext().addRoutes(routes);
239        }
240    }