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