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 }