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 */ 017package org.apache.camel.impl; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.concurrent.atomic.AtomicInteger; 025 026import org.apache.camel.CamelContext; 027import org.apache.camel.Endpoint; 028import org.apache.camel.NoSuchEndpointException; 029import org.apache.camel.Processor; 030import org.apache.camel.Route; 031import org.apache.camel.RuntimeCamelException; 032import org.apache.camel.ShutdownRoute; 033import org.apache.camel.ShutdownRunningTask; 034import org.apache.camel.model.FromDefinition; 035import org.apache.camel.model.ProcessorDefinition; 036import org.apache.camel.model.RouteDefinition; 037import org.apache.camel.processor.CamelInternalProcessor; 038import org.apache.camel.processor.Pipeline; 039import org.apache.camel.spi.InterceptStrategy; 040import org.apache.camel.spi.RouteContext; 041import org.apache.camel.spi.RoutePolicy; 042import org.apache.camel.util.CamelContextHelper; 043import org.apache.camel.util.ObjectHelper; 044 045/** 046 * The context used to activate new routing rules 047 * 048 * @version 049 */ 050public 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 messageHistory; 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 try { 128 // need add the endpoint into service 129 getCamelContext().addService(endpoint); 130 } catch (Exception ex) { 131 throw new RuntimeCamelException(ex); 132 } 133 } 134 if (endpoint == null) { 135 throw new IllegalArgumentException("Either 'uri' or 'ref' must be specified on: " + this); 136 } else { 137 return endpoint; 138 } 139 } 140 141 public <T> T lookup(String name, Class<T> type) { 142 return getCamelContext().getRegistry().lookupByNameAndType(name, type); 143 } 144 145 public <T> Map<String, T> lookupByType(Class<T> type) { 146 return getCamelContext().getRegistry().findByTypeWithName(type); 147 } 148 149 @Override 150 public <T> T mandatoryLookup(String name, Class<T> type) { 151 return CamelContextHelper.mandatoryLookup(getCamelContext(), name, type); 152 } 153 154 public void commit() { 155 // now lets turn all of the event driven consumer processors into a single route 156 if (!eventDrivenProcessors.isEmpty()) { 157 Processor target = Pipeline.newInstance(getCamelContext(), eventDrivenProcessors); 158 159 String routeId = route.idOrCreate(getCamelContext().getNodeIdFactory()); 160 161 // 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 162 CamelInternalProcessor internal = new CamelInternalProcessor(target); 163 internal.addAdvice(new CamelInternalProcessor.UnitOfWorkProcessorAdvice(routeId)); 164 165 // and then in route context so we can keep track which route this is at runtime 166 internal.addAdvice(new CamelInternalProcessor.RouteContextAdvice(this)); 167 168 // and then optionally add route policy processor if a custom policy is set 169 List<RoutePolicy> routePolicyList = getRoutePolicyList(); 170 if (routePolicyList != null && !routePolicyList.isEmpty()) { 171 for (RoutePolicy policy : routePolicyList) { 172 // add policy as service if we have not already done that (eg possible if two routes have the same service) 173 // this ensures Camel can control the lifecycle of the policy 174 if (!camelContext.hasService(policy)) { 175 try { 176 camelContext.addService(policy); 177 } catch (Exception e) { 178 throw ObjectHelper.wrapRuntimeCamelException(e); 179 } 180 } 181 } 182 183 internal.addAdvice(new CamelInternalProcessor.RoutePolicyAdvice(routePolicyList)); 184 } 185 186 // wrap in route inflight processor to track number of inflight exchanges for the route 187 internal.addAdvice(new CamelInternalProcessor.RouteInflightRepositoryAdvice(camelContext.getInflightRepository(), routeId)); 188 189 // wrap in JMX instrumentation processor that is used for performance stats 190 internal.addAdvice(new CamelInternalProcessor.InstrumentationAdvice("route")); 191 192 // wrap in route lifecycle 193 internal.addAdvice(new CamelInternalProcessor.RouteLifecycleAdvice()); 194 195 // and create the route that wraps the UoW 196 Route edcr = new EventDrivenConsumerRoute(this, getEndpoint(), internal); 197 edcr.getProperties().put(Route.ID_PROPERTY, routeId); 198 edcr.getProperties().put(Route.PARENT_PROPERTY, Integer.toHexString(route.hashCode())); 199 edcr.getProperties().put(Route.DESCRIPTION_PROPERTY, route.getDescriptionText()); 200 if (route.getGroup() != null) { 201 edcr.getProperties().put(Route.GROUP_PROPERTY, route.getGroup()); 202 } 203 String rest = "false"; 204 if (route.isRest() != null && route.isRest()) { 205 rest = "true"; 206 } 207 edcr.getProperties().put(Route.REST_PROPERTY, rest); 208 209 // after the route is created then set the route on the policy processor so we get hold of it 210 CamelInternalProcessor.RoutePolicyAdvice task = internal.getAdvice(CamelInternalProcessor.RoutePolicyAdvice.class); 211 if (task != null) { 212 task.setRoute(edcr); 213 } 214 CamelInternalProcessor.RouteLifecycleAdvice task2 = internal.getAdvice(CamelInternalProcessor.RouteLifecycleAdvice.class); 215 if (task2 != null) { 216 task2.setRoute(edcr); 217 } 218 219 // invoke init on route policy 220 if (routePolicyList != null && !routePolicyList.isEmpty()) { 221 for (RoutePolicy policy : routePolicyList) { 222 policy.onInit(edcr); 223 } 224 } 225 226 routes.add(edcr); 227 } 228 } 229 230 public void addEventDrivenProcessor(Processor processor) { 231 eventDrivenProcessors.add(processor); 232 } 233 234 public List<InterceptStrategy> getInterceptStrategies() { 235 return interceptStrategies; 236 } 237 238 public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) { 239 this.interceptStrategies = interceptStrategies; 240 } 241 242 public void addInterceptStrategy(InterceptStrategy interceptStrategy) { 243 getInterceptStrategies().add(interceptStrategy); 244 } 245 246 public void setManagedInterceptStrategy(InterceptStrategy interceptStrategy) { 247 this.managedInterceptStrategy = interceptStrategy; 248 } 249 250 public InterceptStrategy getManagedInterceptStrategy() { 251 return managedInterceptStrategy; 252 } 253 254 public boolean isRouteAdded() { 255 return routeAdded; 256 } 257 258 public void setIsRouteAdded(boolean routeAdded) { 259 this.routeAdded = routeAdded; 260 } 261 262 public void setTracing(Boolean tracing) { 263 this.trace = tracing; 264 } 265 266 public Boolean isTracing() { 267 if (trace != null) { 268 return trace; 269 } else { 270 // fallback to the option from camel context 271 return getCamelContext().isTracing(); 272 } 273 } 274 275 public void setMessageHistory(Boolean messageHistory) { 276 this.messageHistory = messageHistory; 277 } 278 279 public Boolean isMessageHistory() { 280 if (messageHistory != null) { 281 return messageHistory; 282 } else { 283 // fallback to the option from camel context 284 return getCamelContext().isMessageHistory(); 285 } 286 } 287 288 public void setStreamCaching(Boolean cache) { 289 this.streamCache = cache; 290 } 291 292 public Boolean isStreamCaching() { 293 if (streamCache != null) { 294 return streamCache; 295 } else { 296 // fallback to the option from camel context 297 return getCamelContext().isStreamCaching(); 298 } 299 } 300 301 public void setHandleFault(Boolean handleFault) { 302 this.handleFault = handleFault; 303 } 304 305 public Boolean isHandleFault() { 306 if (handleFault != null) { 307 return handleFault; 308 } else { 309 // fallback to the option from camel context 310 return getCamelContext().isHandleFault(); 311 } 312 } 313 314 public void setDelayer(Long delay) { 315 this.delay = delay; 316 } 317 318 public Long getDelayer() { 319 if (delay != null) { 320 return delay; 321 } else { 322 // fallback to the option from camel context 323 return getCamelContext().getDelayer(); 324 } 325 } 326 327 public void setAutoStartup(Boolean autoStartup) { 328 this.autoStartup = autoStartup; 329 } 330 331 public Boolean isAutoStartup() { 332 if (autoStartup != null) { 333 return autoStartup; 334 } 335 // default to true 336 return true; 337 } 338 339 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 340 this.shutdownRoute = shutdownRoute; 341 } 342 343 public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) { 344 throw new IllegalArgumentException("This option can only be configured on CamelContext"); 345 } 346 347 public Boolean isAllowUseOriginalMessage() { 348 return getCamelContext().isAllowUseOriginalMessage(); 349 } 350 351 public ShutdownRoute getShutdownRoute() { 352 if (shutdownRoute != null) { 353 return shutdownRoute; 354 } else { 355 // fallback to the option from camel context 356 return getCamelContext().getShutdownRoute(); 357 } 358 } 359 360 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 361 this.shutdownRunningTask = shutdownRunningTask; 362 } 363 364 public ShutdownRunningTask getShutdownRunningTask() { 365 if (shutdownRunningTask != null) { 366 return shutdownRunningTask; 367 } else { 368 // fallback to the option from camel context 369 return getCamelContext().getShutdownRunningTask(); 370 } 371 } 372 373 public int getAndIncrement(ProcessorDefinition<?> node) { 374 AtomicInteger count = nodeIndex.get(node); 375 if (count == null) { 376 count = new AtomicInteger(); 377 nodeIndex.put(node, count); 378 } 379 return count.getAndIncrement(); 380 } 381 382 public void setRoutePolicyList(List<RoutePolicy> routePolicyList) { 383 this.routePolicyList = routePolicyList; 384 } 385 386 public List<RoutePolicy> getRoutePolicyList() { 387 return routePolicyList; 388 } 389}