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.impl;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.concurrent.atomic.AtomicInteger;
025    
026    import org.apache.camel.CamelContext;
027    import org.apache.camel.Endpoint;
028    import org.apache.camel.NoSuchEndpointException;
029    import org.apache.camel.Processor;
030    import org.apache.camel.Route;
031    import org.apache.camel.ShutdownRoute;
032    import org.apache.camel.ShutdownRunningTask;
033    import org.apache.camel.management.InstrumentationProcessor;
034    import org.apache.camel.model.FromDefinition;
035    import org.apache.camel.model.ProcessorDefinition;
036    import org.apache.camel.model.RouteDefinition;
037    import org.apache.camel.processor.Pipeline;
038    import org.apache.camel.processor.RouteInflightRepositoryProcessor;
039    import org.apache.camel.processor.RoutePolicyProcessor;
040    import org.apache.camel.processor.UnitOfWorkProcessor;
041    import org.apache.camel.spi.InterceptStrategy;
042    import org.apache.camel.spi.RouteContext;
043    import org.apache.camel.spi.RoutePolicy;
044    import org.apache.camel.util.ObjectHelper;
045    
046    /**
047     * The context used to activate new routing rules
048     *
049     * @version 
050     */
051    public class DefaultRouteContext implements RouteContext {
052        private final Map<ProcessorDefinition<?>, AtomicInteger> nodeIndex = new HashMap<ProcessorDefinition<?>, AtomicInteger>();
053        private final RouteDefinition route;
054        private FromDefinition from;
055        private final Collection<Route> routes;
056        private Endpoint endpoint;
057        private final List<Processor> eventDrivenProcessors = new ArrayList<Processor>();
058        private CamelContext camelContext;
059        private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
060        private InterceptStrategy managedInterceptStrategy;
061        private boolean routeAdded;
062        private Boolean trace;
063        private Boolean streamCache;
064        private Boolean handleFault;
065        private Long delay;
066        private Boolean autoStartup = Boolean.TRUE;
067        private List<RoutePolicy> routePolicyList = new ArrayList<RoutePolicy>();
068        private ShutdownRoute shutdownRoute;
069        private ShutdownRunningTask shutdownRunningTask;
070    
071        public DefaultRouteContext(CamelContext camelContext, RouteDefinition route, FromDefinition from, Collection<Route> routes) {
072            this.camelContext = camelContext;
073            this.route = route;
074            this.from = from;
075            this.routes = routes;
076        }
077    
078        /**
079         * Only used for lazy construction from inside ExpressionType
080         */
081        public DefaultRouteContext(CamelContext camelContext) {
082            this.camelContext = camelContext;
083            this.routes = new ArrayList<Route>();
084            this.route = new RouteDefinition("temporary");
085        }
086    
087        public Endpoint getEndpoint() {
088            if (endpoint == null) {
089                endpoint = from.resolveEndpoint(this);
090            }
091            return endpoint;
092        }
093    
094        public FromDefinition getFrom() {
095            return from;
096        }
097    
098        public RouteDefinition getRoute() {
099            return route;
100        }
101    
102        public CamelContext getCamelContext() {
103            return camelContext;
104        }
105    
106        public Endpoint resolveEndpoint(String uri) {
107            return route.resolveEndpoint(getCamelContext(), uri);
108        }
109    
110        public Endpoint resolveEndpoint(String uri, String ref) {
111            Endpoint endpoint = null;
112            if (uri != null) {
113                endpoint = resolveEndpoint(uri);
114                if (endpoint == null) {
115                    throw new NoSuchEndpointException(uri);
116                }
117            }
118            if (ref != null) {
119                endpoint = lookup(ref, Endpoint.class);
120                if (endpoint == null) {
121                    throw new NoSuchEndpointException("ref:" + ref, "check your camel registry with id " + ref);
122                }
123                // Check the endpoint has the right CamelContext 
124                if (!this.getCamelContext().equals(endpoint.getCamelContext())) {
125                    throw new NoSuchEndpointException("ref:" + ref, "make sure the endpoint has the same camel context as the route does.");
126                }
127            }
128            if (endpoint == null) {
129                throw new IllegalArgumentException("Either 'uri' or 'ref' must be specified on: " + this);
130            } else {
131                return endpoint;
132            }
133        }
134    
135        public <T> T lookup(String name, Class<T> type) {
136            return getCamelContext().getRegistry().lookup(name, type);
137        }
138    
139        public <T> Map<String, T> lookupByType(Class<T> type) {
140            return getCamelContext().getRegistry().lookupByType(type);
141        }
142        
143        public void commit() {
144            // now lets turn all of the event driven consumer processors into a single route
145            if (!eventDrivenProcessors.isEmpty()) {
146                Processor target = Pipeline.newInstance(getCamelContext(), eventDrivenProcessors);
147    
148                // and wrap it in a unit of work so the UoW is on the top, so the entire route will be in the same UoW
149                UnitOfWorkProcessor unitOfWorkProcessor = new UnitOfWorkProcessor(this, target);
150    
151                // and then optionally add route policy processor if a custom policy is set
152                RoutePolicyProcessor routePolicyProcessor = null;
153                List<RoutePolicy> routePolicyList = getRoutePolicyList();
154                if (routePolicyList != null && !routePolicyList.isEmpty()) {
155                    for (RoutePolicy policy : routePolicyList) {
156                        // add policy as service if we have not already done that (eg possible if two routes have the same service)
157                        // this ensures Camel can control the lifecycle of the policy
158                        if (!camelContext.hasService(policy)) {
159                            try {
160                                camelContext.addService(policy);
161                            } catch (Exception e) {
162                                throw ObjectHelper.wrapRuntimeCamelException(e);
163                            }
164                        }
165                    }
166                    routePolicyProcessor = new RoutePolicyProcessor(unitOfWorkProcessor, routePolicyList);
167                    target = routePolicyProcessor;
168                } else {
169                    target = unitOfWorkProcessor;
170                }
171    
172                // wrap in route inflight processor to track number of inflight exchanges for the route
173                RouteInflightRepositoryProcessor inflight = new RouteInflightRepositoryProcessor(camelContext.getInflightRepository(), target);
174    
175                // and wrap it by a instrumentation processor that is to be used for performance stats
176                // for this particular route
177                InstrumentationProcessor instrument = new InstrumentationProcessor();
178                instrument.setType("route");
179                instrument.setProcessor(inflight);
180    
181                // and create the route that wraps the UoW
182                Route edcr = new EventDrivenConsumerRoute(this, getEndpoint(), instrument);
183                // create the route id
184                String routeId = route.idOrCreate(getCamelContext().getNodeIdFactory());
185                edcr.getProperties().put(Route.ID_PROPERTY, routeId);
186                edcr.getProperties().put(Route.PARENT_PROPERTY, Integer.toHexString(route.hashCode()));
187                if (route.getGroup() != null) {
188                    edcr.getProperties().put(Route.GROUP_PROPERTY, route.getGroup());
189                }
190    
191                // after the route is created then set the route on the policy processor so we get hold of it
192                if (routePolicyProcessor != null) {
193                    routePolicyProcessor.setRoute(edcr);
194                }
195                // after the route is created then set the route on the inflight processor so we get hold of it
196                inflight.setRoute(edcr);
197    
198                // invoke init on route policy
199                if (routePolicyList != null && !routePolicyList.isEmpty()) {
200                    for (RoutePolicy policy : routePolicyList) {
201                        policy.onInit(edcr);
202                    }
203                }
204    
205                routes.add(edcr);
206            }
207        }
208    
209        public void addEventDrivenProcessor(Processor processor) {
210            eventDrivenProcessors.add(processor);
211        }
212    
213        public List<InterceptStrategy> getInterceptStrategies() {
214            return interceptStrategies;
215        }
216    
217        public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
218            this.interceptStrategies = interceptStrategies;
219        }
220    
221        public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
222            getInterceptStrategies().add(interceptStrategy);
223        }
224    
225        public void setManagedInterceptStrategy(InterceptStrategy interceptStrategy) {
226            this.managedInterceptStrategy = interceptStrategy;
227        }
228    
229        public InterceptStrategy getManagedInterceptStrategy() {
230            return managedInterceptStrategy;
231        }
232    
233        public boolean isRouteAdded() {
234            return routeAdded;
235        }
236    
237        public void setIsRouteAdded(boolean routeAdded) {
238            this.routeAdded = routeAdded;
239        }
240    
241        public void setTracing(Boolean tracing) {
242            this.trace = tracing;
243        }
244    
245        public Boolean isTracing() {
246            if (trace != null) {
247                return trace;
248            } else {
249                // fallback to the option from camel context
250                return getCamelContext().isTracing();
251            }
252        }
253    
254        public void setStreamCaching(Boolean cache) {
255            this.streamCache = cache;
256        }
257    
258        public Boolean isStreamCaching() {
259            if (streamCache != null) {
260                return streamCache;
261            } else {
262                // fallback to the option from camel context
263                return getCamelContext().isStreamCaching();
264            }
265        }
266    
267        public void setHandleFault(Boolean handleFault) {
268            this.handleFault = handleFault;
269        }
270    
271        public Boolean isHandleFault() {
272            if (handleFault != null) {
273                return handleFault;
274            } else {
275                // fallback to the option from camel context
276                return getCamelContext().isHandleFault();
277            }
278        }
279    
280        public void setDelayer(Long delay) {
281            this.delay = delay;
282        }
283    
284        public Long getDelayer() {
285            if (delay != null) {
286                return delay;
287            } else {
288                // fallback to the option from camel context
289                return getCamelContext().getDelayer();
290            }
291        }
292    
293        public void setAutoStartup(Boolean autoStartup) {
294            this.autoStartup = autoStartup;
295        }
296    
297        public Boolean isAutoStartup() {
298            if (autoStartup != null) {
299                return autoStartup;
300            }
301            // default to true
302            return true;
303        }
304    
305        public void setShutdownRoute(ShutdownRoute shutdownRoute) {
306            this.shutdownRoute = shutdownRoute;
307        }
308    
309        public ShutdownRoute getShutdownRoute() {
310            if (shutdownRoute != null) {
311                return shutdownRoute;
312            } else {
313                // fallback to the option from camel context
314                return getCamelContext().getShutdownRoute();
315            }
316        }
317    
318        public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
319            this.shutdownRunningTask = shutdownRunningTask;
320        }
321    
322        public ShutdownRunningTask getShutdownRunningTask() {
323            if (shutdownRunningTask != null) {
324                return shutdownRunningTask;
325            } else {
326                // fallback to the option from camel context
327                return getCamelContext().getShutdownRunningTask();
328            }
329        }
330        
331        public int getAndIncrement(ProcessorDefinition<?> node) {
332            AtomicInteger count = nodeIndex.get(node);
333            if (count == null) {
334                count = new AtomicInteger();
335                nodeIndex.put(node, count);
336            }
337            return count.getAndIncrement();
338        }
339    
340        public void setRoutePolicyList(List<RoutePolicy> routePolicyList) {
341            this.routePolicyList = routePolicyList;
342        }
343    
344        public List<RoutePolicy> getRoutePolicyList() {
345            return routePolicyList;
346        }
347    }