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