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.reifier; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.function.Function; 025 026import org.apache.camel.Channel; 027import org.apache.camel.ErrorHandlerFactory; 028import org.apache.camel.ExtendedCamelContext; 029import org.apache.camel.Processor; 030import org.apache.camel.model.AggregateDefinition; 031import org.apache.camel.model.BeanDefinition; 032import org.apache.camel.model.CatchDefinition; 033import org.apache.camel.model.ChoiceDefinition; 034import org.apache.camel.model.ClaimCheckDefinition; 035import org.apache.camel.model.ConvertBodyDefinition; 036import org.apache.camel.model.DelayDefinition; 037import org.apache.camel.model.DynamicRouterDefinition; 038import org.apache.camel.model.EnrichDefinition; 039import org.apache.camel.model.ExpressionNode; 040import org.apache.camel.model.FilterDefinition; 041import org.apache.camel.model.FinallyDefinition; 042import org.apache.camel.model.HystrixDefinition; 043import org.apache.camel.model.IdempotentConsumerDefinition; 044import org.apache.camel.model.InOnlyDefinition; 045import org.apache.camel.model.InOutDefinition; 046import org.apache.camel.model.InterceptDefinition; 047import org.apache.camel.model.InterceptFromDefinition; 048import org.apache.camel.model.InterceptSendToEndpointDefinition; 049import org.apache.camel.model.LoadBalanceDefinition; 050import org.apache.camel.model.LogDefinition; 051import org.apache.camel.model.LoopDefinition; 052import org.apache.camel.model.MarshalDefinition; 053import org.apache.camel.model.MulticastDefinition; 054import org.apache.camel.model.OnCompletionDefinition; 055import org.apache.camel.model.OnExceptionDefinition; 056import org.apache.camel.model.OnFallbackDefinition; 057import org.apache.camel.model.OptionalIdentifiedDefinition; 058import org.apache.camel.model.OtherwiseDefinition; 059import org.apache.camel.model.PipelineDefinition; 060import org.apache.camel.model.PolicyDefinition; 061import org.apache.camel.model.PollEnrichDefinition; 062import org.apache.camel.model.ProcessDefinition; 063import org.apache.camel.model.ProcessorDefinition; 064import org.apache.camel.model.ProcessorDefinitionHelper; 065import org.apache.camel.model.RecipientListDefinition; 066import org.apache.camel.model.RemoveHeaderDefinition; 067import org.apache.camel.model.RemoveHeadersDefinition; 068import org.apache.camel.model.RemovePropertiesDefinition; 069import org.apache.camel.model.RemovePropertyDefinition; 070import org.apache.camel.model.ResequenceDefinition; 071import org.apache.camel.model.RollbackDefinition; 072import org.apache.camel.model.RouteDefinition; 073import org.apache.camel.model.RouteDefinitionHelper; 074import org.apache.camel.model.RoutingSlipDefinition; 075import org.apache.camel.model.SagaDefinition; 076import org.apache.camel.model.SamplingDefinition; 077import org.apache.camel.model.ScriptDefinition; 078import org.apache.camel.model.SetBodyDefinition; 079import org.apache.camel.model.SetExchangePatternDefinition; 080import org.apache.camel.model.SetHeaderDefinition; 081import org.apache.camel.model.SetPropertyDefinition; 082import org.apache.camel.model.SortDefinition; 083import org.apache.camel.model.SplitDefinition; 084import org.apache.camel.model.StepDefinition; 085import org.apache.camel.model.StopDefinition; 086import org.apache.camel.model.ThreadsDefinition; 087import org.apache.camel.model.ThrottleDefinition; 088import org.apache.camel.model.ThrowExceptionDefinition; 089import org.apache.camel.model.ToDefinition; 090import org.apache.camel.model.ToDynamicDefinition; 091import org.apache.camel.model.TransactedDefinition; 092import org.apache.camel.model.TransformDefinition; 093import org.apache.camel.model.TryDefinition; 094import org.apache.camel.model.UnmarshalDefinition; 095import org.apache.camel.model.ValidateDefinition; 096import org.apache.camel.model.WhenDefinition; 097import org.apache.camel.model.WhenSkipSendToEndpointDefinition; 098import org.apache.camel.model.WireTapDefinition; 099import org.apache.camel.model.cloud.ServiceCallDefinition; 100import org.apache.camel.model.language.ExpressionDefinition; 101import org.apache.camel.processor.InterceptEndpointProcessor; 102import org.apache.camel.processor.Pipeline; 103import org.apache.camel.processor.channel.DefaultChannel; 104import org.apache.camel.reifier.errorhandler.ErrorHandlerReifier; 105import org.apache.camel.spi.IdAware; 106import org.apache.camel.spi.InterceptStrategy; 107import org.apache.camel.spi.LifecycleStrategy; 108import org.apache.camel.spi.RouteContext; 109import org.slf4j.Logger; 110import org.slf4j.LoggerFactory; 111 112public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> { 113 114 private static final Map<Class<?>, Function<ProcessorDefinition<?>, ProcessorReifier<? extends ProcessorDefinition<?>>>> PROCESSORS; 115 static { 116 // NOTE: if adding a new class then update the initial capacity of the 117 // HashMap 118 Map<Class<?>, Function<ProcessorDefinition<?>, ProcessorReifier<? extends ProcessorDefinition<?>>>> map = new HashMap<>(65); 119 map.put(AggregateDefinition.class, AggregateReifier::new); 120 map.put(BeanDefinition.class, BeanReifier::new); 121 map.put(CatchDefinition.class, CatchReifier::new); 122 map.put(ChoiceDefinition.class, ChoiceReifier::new); 123 map.put(ClaimCheckDefinition.class, ClaimCheckReifier::new); 124 map.put(ConvertBodyDefinition.class, ConvertBodyReifier::new); 125 map.put(DelayDefinition.class, DelayReifier::new); 126 map.put(DynamicRouterDefinition.class, DynamicRouterReifier::new); 127 map.put(EnrichDefinition.class, EnrichReifier::new); 128 map.put(FilterDefinition.class, FilterReifier::new); 129 map.put(FinallyDefinition.class, FinallyReifier::new); 130 map.put(HystrixDefinition.class, HystrixReifier::new); 131 map.put(IdempotentConsumerDefinition.class, IdempotentConsumerReifier::new); 132 map.put(InOnlyDefinition.class, SendReifier::new); 133 map.put(InOutDefinition.class, SendReifier::new); 134 map.put(InterceptDefinition.class, InterceptReifier::new); 135 map.put(InterceptFromDefinition.class, InterceptFromReifier::new); 136 map.put(InterceptSendToEndpointDefinition.class, InterceptSendToEndpointReifier::new); 137 map.put(LoadBalanceDefinition.class, LoadBalanceReifier::new); 138 map.put(LogDefinition.class, LogReifier::new); 139 map.put(LoopDefinition.class, LoopReifier::new); 140 map.put(MarshalDefinition.class, MarshalReifier::new); 141 map.put(MulticastDefinition.class, MulticastReifier::new); 142 map.put(OnCompletionDefinition.class, OnCompletionReifier::new); 143 map.put(OnExceptionDefinition.class, OnExceptionReifier::new); 144 map.put(OnFallbackDefinition.class, OnFallbackReifier::new); 145 map.put(OtherwiseDefinition.class, OtherwiseReifier::new); 146 map.put(PipelineDefinition.class, PipelineReifier::new); 147 map.put(PolicyDefinition.class, PolicyReifier::new); 148 map.put(PollEnrichDefinition.class, PollEnrichReifier::new); 149 map.put(ProcessDefinition.class, ProcessReifier::new); 150 map.put(RecipientListDefinition.class, RecipientListReifier::new); 151 map.put(RemoveHeaderDefinition.class, RemoveHeaderReifier::new); 152 map.put(RemoveHeadersDefinition.class, RemoveHeadersReifier::new); 153 map.put(RemovePropertiesDefinition.class, RemovePropertiesReifier::new); 154 map.put(RemovePropertyDefinition.class, RemovePropertyReifier::new); 155 map.put(ResequenceDefinition.class, ResequenceReifier::new); 156 map.put(RollbackDefinition.class, RollbackReifier::new); 157 map.put(RouteDefinition.class, RouteReifier::new); 158 map.put(RoutingSlipDefinition.class, RoutingSlipReifier::new); 159 map.put(SagaDefinition.class, SagaReifier::new); 160 map.put(SamplingDefinition.class, SamplingReifier::new); 161 map.put(ScriptDefinition.class, ScriptReifier::new); 162 map.put(ServiceCallDefinition.class, ServiceCallReifier::new); 163 map.put(SetBodyDefinition.class, SetBodyReifier::new); 164 map.put(SetExchangePatternDefinition.class, SetExchangePatternReifier::new); 165 map.put(SetHeaderDefinition.class, SetHeaderReifier::new); 166 map.put(SetPropertyDefinition.class, SetPropertyReifier::new); 167 map.put(SortDefinition.class, SortReifier::new); 168 map.put(SplitDefinition.class, SplitReifier::new); 169 map.put(StepDefinition.class, StepReifier::new); 170 map.put(StopDefinition.class, StopReifier::new); 171 map.put(ThreadsDefinition.class, ThreadsReifier::new); 172 map.put(ThrottleDefinition.class, ThrottleReifier::new); 173 map.put(ThrowExceptionDefinition.class, ThrowExceptionReifier::new); 174 map.put(ToDefinition.class, SendReifier::new); 175 map.put(ToDynamicDefinition.class, ToDynamicReifier::new); 176 map.put(TransactedDefinition.class, TransactedReifier::new); 177 map.put(TransformDefinition.class, TransformReifier::new); 178 map.put(TryDefinition.class, TryReifier::new); 179 map.put(UnmarshalDefinition.class, UnmarshalReifier::new); 180 map.put(ValidateDefinition.class, ValidateReifier::new); 181 map.put(WireTapDefinition.class, WireTapReifier::new); 182 map.put(WhenSkipSendToEndpointDefinition.class, WhenSkipSendToEndpointReifier::new); 183 map.put(WhenDefinition.class, WhenReifier::new); 184 PROCESSORS = map; 185 } 186 protected final Logger log = LoggerFactory.getLogger(getClass()); 187 188 protected final T definition; 189 190 public ProcessorReifier(T definition) { 191 this.definition = definition; 192 } 193 194 public static void registerReifier(Class<?> processorClass, Function<ProcessorDefinition<?>, ProcessorReifier<? extends ProcessorDefinition<?>>> creator) { 195 PROCESSORS.put(processorClass, creator); 196 } 197 198 public static ProcessorReifier<? extends ProcessorDefinition<?>> reifier(ProcessorDefinition<?> definition) { 199 Function<ProcessorDefinition<?>, ProcessorReifier<? extends ProcessorDefinition<?>>> reifier = PROCESSORS.get(definition.getClass()); 200 if (reifier != null) { 201 return reifier.apply(definition); 202 } 203 throw new IllegalStateException("Unsupported definition: " + definition); 204 } 205 206 /** 207 * Override this in definition class and implement logic to create the 208 * processor based on the definition model. 209 */ 210 public abstract Processor createProcessor(RouteContext routeContext) throws Exception; 211 212 /** 213 * Prefer to use {#link #createChildProcessor}. 214 */ 215 protected Processor createOutputsProcessor(RouteContext routeContext) throws Exception { 216 Collection<ProcessorDefinition<?>> outputs = definition.getOutputs(); 217 return createOutputsProcessor(routeContext, outputs); 218 } 219 220 /** 221 * Creates the child processor (outputs) from the current definition 222 * 223 * @param routeContext the route context 224 * @param mandatory whether or not children is mandatory (ie the definition 225 * should have outputs) 226 * @return the created children, or <tt>null</tt> if definition had no 227 * output 228 * @throws Exception is thrown if error creating the child or if it was 229 * mandatory and there was no output defined on definition 230 */ 231 protected Processor createChildProcessor(RouteContext routeContext, boolean mandatory) throws Exception { 232 Processor children = null; 233 // at first use custom factory 234 if (routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory() != null) { 235 children = routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory().createChildProcessor(routeContext, definition, mandatory); 236 } 237 // fallback to default implementation if factory did not create the 238 // child 239 if (children == null) { 240 children = createOutputsProcessor(routeContext); 241 } 242 243 if (children == null && mandatory) { 244 throw new IllegalArgumentException("Definition has no children on " + definition); 245 } 246 return children; 247 } 248 249 public void addRoutes(RouteContext routeContext) throws Exception { 250 Channel processor = makeProcessor(routeContext); 251 if (processor == null) { 252 // no processor to add 253 return; 254 } 255 256 if (!routeContext.isRouteAdded()) { 257 // are we routing to an endpoint interceptor, if so we should not 258 // add it as an event driven 259 // processor as we use the producer to trigger the interceptor 260 boolean endpointInterceptor = processor.getNextProcessor() instanceof InterceptEndpointProcessor; 261 262 // only add regular processors as event driven 263 if (endpointInterceptor) { 264 log.debug("Endpoint interceptor should not be added as an event driven consumer route: {}", processor); 265 } else { 266 log.trace("Adding event driven processor: {}", processor); 267 routeContext.addEventDrivenProcessor(processor); 268 } 269 } 270 } 271 272 /** 273 * Wraps the child processor in whatever necessary interceptors and error 274 * handlers 275 */ 276 public Channel wrapProcessor(RouteContext routeContext, Processor processor) throws Exception { 277 // don't double wrap 278 if (processor instanceof Channel) { 279 return (Channel)processor; 280 } 281 return wrapChannel(routeContext, processor, null); 282 } 283 284 protected Channel wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition<?> child) throws Exception { 285 return wrapChannel(routeContext, processor, child, definition.isInheritErrorHandler()); 286 } 287 288 protected Channel wrapChannel(RouteContext routeContext, Processor processor, ProcessorDefinition<?> child, Boolean inheritErrorHandler) throws Exception { 289 // put a channel in between this and each output to control the route 290 // flow logic 291 DefaultChannel channel = new DefaultChannel(); 292 293 // add interceptor strategies to the channel must be in this order: 294 // camel context, route context, local 295 List<InterceptStrategy> interceptors = new ArrayList<>(); 296 addInterceptStrategies(routeContext, interceptors, routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getInterceptStrategies()); 297 addInterceptStrategies(routeContext, interceptors, routeContext.getInterceptStrategies()); 298 addInterceptStrategies(routeContext, interceptors, definition.getInterceptStrategies()); 299 300 // force the creation of an id 301 RouteDefinitionHelper.forceAssignIds(routeContext.getCamelContext(), definition); 302 303 // fix parent/child relationship. This will be the case of the routes 304 // has been 305 // defined using XML DSL or end user may have manually assembled a route 306 // from the model. 307 // Background note: parent/child relationship is assembled on-the-fly 308 // when using Java DSL (fluent builders) 309 // where as when using XML DSL (JAXB) then it fixed after, but if people 310 // are using custom interceptors 311 // then we need to fix the parent/child relationship beforehand, and 312 // thus we can do it here 313 // ideally we need the design time route -> runtime route to be a 314 // 2-phase pass (scheduled work for Camel 3.0) 315 if (child != null && definition != child) { 316 child.setParent(definition); 317 } 318 319 // set the child before init the channel 320 RouteDefinition route = ProcessorDefinitionHelper.getRoute(definition); 321 boolean first = false; 322 if (route != null && !route.getOutputs().isEmpty()) { 323 first = route.getOutputs().get(0) == definition; 324 } 325 // set scoping 326 boolean routeScoped = true; 327 if (definition instanceof OnExceptionDefinition) { 328 routeScoped = ((OnExceptionDefinition)definition).isRouteScoped(); 329 } else if (this.definition instanceof OnCompletionDefinition) { 330 routeScoped = ((OnCompletionDefinition)definition).isRouteScoped(); 331 } 332 // initialize the channel 333 channel.initChannel(routeContext, definition, child, interceptors, processor, route, first, routeScoped); 334 335 boolean wrap = false; 336 // set the error handler, must be done after init as we can set the 337 // error handler as first in the chain 338 if (definition instanceof TryDefinition || definition instanceof CatchDefinition || definition instanceof FinallyDefinition) { 339 // do not use error handler for try .. catch .. finally blocks as it 340 // will handle errors itself 341 log.trace("{} is part of doTry .. doCatch .. doFinally so no error handler is applied", definition); 342 } else if (ProcessorDefinitionHelper.isParentOfType(TryDefinition.class, definition, true) 343 || ProcessorDefinitionHelper.isParentOfType(CatchDefinition.class, definition, true) 344 || ProcessorDefinitionHelper.isParentOfType(FinallyDefinition.class, definition, true)) { 345 // do not use error handler for try .. catch .. finally blocks as it 346 // will handle errors itself 347 // by checking that any of our parent(s) is not a try .. catch or 348 // finally type 349 log.trace("{} is part of doTry .. doCatch .. doFinally so no error handler is applied", definition); 350 } else if (definition instanceof OnExceptionDefinition || ProcessorDefinitionHelper.isParentOfType(OnExceptionDefinition.class, definition, true)) { 351 log.trace("{} is part of OnException so no error handler is applied", definition); 352 // do not use error handler for onExceptions blocks as it will 353 // handle errors itself 354 } else if (definition instanceof HystrixDefinition || ProcessorDefinitionHelper.isParentOfType(HystrixDefinition.class, definition, true)) { 355 // do not use error handler for hystrix as it offers circuit 356 // breaking with fallback for its outputs 357 // however if inherit error handler is enabled, we need to wrap an 358 // error handler on the hystrix parent 359 if (inheritErrorHandler != null && inheritErrorHandler && child == null) { 360 // only wrap the parent (not the children of the hystrix) 361 wrap = true; 362 } else { 363 log.trace("{} is part of HystrixCircuitBreaker so no error handler is applied", definition); 364 } 365 } else if (definition instanceof MulticastDefinition) { 366 // do not use error handler for multicast as it offers fine grained 367 // error handlers for its outputs 368 // however if share unit of work is enabled, we need to wrap an 369 // error handler on the multicast parent 370 MulticastDefinition def = (MulticastDefinition)definition; 371 boolean isShareUnitOfWork = def.getShareUnitOfWork() != null && def.getShareUnitOfWork(); 372 if (isShareUnitOfWork && child == null) { 373 // only wrap the parent (not the children of the multicast) 374 wrap = true; 375 } else { 376 log.trace("{} is part of multicast which have special error handling so no error handler is applied", definition); 377 } 378 } else { 379 // use error handler by default or if configured to do so 380 wrap = true; 381 } 382 if (wrap) { 383 wrapChannelInErrorHandler(channel, routeContext, inheritErrorHandler); 384 } 385 386 // do post init at the end 387 channel.postInitChannel(); 388 log.trace("{} wrapped in Channel: {}", definition, channel); 389 390 return channel; 391 } 392 393 /** 394 * Wraps the given channel in error handler (if error handler is inherited) 395 * 396 * @param channel the channel 397 * @param routeContext the route context 398 * @param inheritErrorHandler whether to inherit error handler 399 * @throws Exception can be thrown if failed to create error handler builder 400 */ 401 private void wrapChannelInErrorHandler(DefaultChannel channel, RouteContext routeContext, Boolean inheritErrorHandler) throws Exception { 402 if (inheritErrorHandler == null || inheritErrorHandler) { 403 log.trace("{} is configured to inheritErrorHandler", definition); 404 Processor output = channel.getOutput(); 405 Processor errorHandler = wrapInErrorHandler(routeContext, output); 406 // set error handler on channel 407 channel.setErrorHandler(errorHandler); 408 } else { 409 log.debug("{} is configured to not inheritErrorHandler.", definition); 410 } 411 } 412 413 /** 414 * Wraps the given output in an error handler 415 * 416 * @param routeContext the route context 417 * @param output the output 418 * @return the output wrapped with the error handler 419 * @throws Exception can be thrown if failed to create error handler builder 420 */ 421 protected Processor wrapInErrorHandler(RouteContext routeContext, Processor output) throws Exception { 422 ErrorHandlerFactory builder = routeContext.getErrorHandlerFactory(); 423 // create error handler 424 Processor errorHandler = ErrorHandlerReifier.reifier(builder).createErrorHandler(routeContext, output); 425 426 // invoke lifecycles so we can manage this error handler builder 427 for (LifecycleStrategy strategy : routeContext.getCamelContext().getLifecycleStrategies()) { 428 strategy.onErrorHandlerAdd(routeContext, errorHandler, builder); 429 } 430 431 return errorHandler; 432 } 433 434 /** 435 * Adds the given list of interceptors to the channel. 436 * 437 * @param routeContext the route context 438 * @param interceptors the list to add strategies 439 * @param strategies list of strategies to add. 440 */ 441 protected void addInterceptStrategies(RouteContext routeContext, List<InterceptStrategy> interceptors, List<InterceptStrategy> strategies) { 442 interceptors.addAll(strategies); 443 } 444 445 /** 446 * Creates a new instance of some kind of composite processor which defaults 447 * to using a {@link Pipeline} but derived classes could change the 448 * behaviour 449 */ 450 protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) throws Exception { 451 return Pipeline.newInstance(routeContext.getCamelContext(), list); 452 } 453 454 protected Processor createOutputsProcessor(RouteContext routeContext, Collection<ProcessorDefinition<?>> outputs) throws Exception { 455 // We will save list of actions to restore the outputs back to the 456 // original state. 457 Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter(); 458 try { 459 return createOutputsProcessorImpl(routeContext, outputs); 460 } finally { 461 propertyPlaceholdersChangeReverter.run(); 462 } 463 } 464 465 protected Processor createOutputsProcessorImpl(RouteContext routeContext, Collection<ProcessorDefinition<?>> outputs) throws Exception { 466 List<Processor> list = new ArrayList<>(); 467 for (ProcessorDefinition<?> output : outputs) { 468 469 // allow any custom logic before we create the processor 470 reifier(output).preCreateProcessor(); 471 472 // resolve properties before we create the processor 473 ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), output); 474 475 // also resolve properties and constant fields on embedded 476 // expressions 477 ProcessorDefinition<?> me = (ProcessorDefinition<?>)output; 478 if (me instanceof ExpressionNode) { 479 ExpressionNode exp = (ExpressionNode)me; 480 ExpressionDefinition expressionDefinition = exp.getExpression(); 481 if (expressionDefinition != null) { 482 // resolve properties before we create the processor 483 ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), expressionDefinition); 484 } 485 } 486 487 Processor processor = createProcessor(routeContext, output); 488 489 // inject id 490 if (processor instanceof IdAware) { 491 String id = getId(output, routeContext); 492 ((IdAware)processor).setId(id); 493 } 494 495 if (output instanceof Channel && processor == null) { 496 continue; 497 } 498 499 Processor channel = wrapChannel(routeContext, processor, output); 500 list.add(channel); 501 } 502 503 // if more than one output wrap than in a composite processor else just 504 // keep it as is 505 Processor processor = null; 506 if (!list.isEmpty()) { 507 if (list.size() == 1) { 508 processor = list.get(0); 509 } else { 510 processor = createCompositeProcessor(routeContext, list); 511 } 512 } 513 514 return processor; 515 } 516 517 protected Processor createProcessor(RouteContext routeContext, ProcessorDefinition<?> output) throws Exception { 518 Processor processor = null; 519 // at first use custom factory 520 if (routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory() != null) { 521 processor = routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory().createProcessor(routeContext, output); 522 } 523 // fallback to default implementation if factory did not create the 524 // processor 525 if (processor == null) { 526 processor = reifier(output).createProcessor(routeContext); 527 } 528 return processor; 529 } 530 531 /** 532 * Creates the processor and wraps it in any necessary interceptors and 533 * error handlers 534 */ 535 protected Channel makeProcessor(RouteContext routeContext) throws Exception { 536 // We will save list of actions to restore the definition back to the 537 // original state. 538 Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter(); 539 try { 540 return makeProcessorImpl(routeContext); 541 } finally { 542 // Lets restore 543 propertyPlaceholdersChangeReverter.run(); 544 } 545 } 546 547 private Channel makeProcessorImpl(RouteContext routeContext) throws Exception { 548 Processor processor = null; 549 550 // allow any custom logic before we create the processor 551 preCreateProcessor(); 552 553 // resolve properties before we create the processor 554 ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), definition); 555 556 // also resolve properties and constant fields on embedded expressions 557 ProcessorDefinition<?> me = definition; 558 if (me instanceof ExpressionNode) { 559 ExpressionNode exp = (ExpressionNode)me; 560 ExpressionDefinition expressionDefinition = exp.getExpression(); 561 if (expressionDefinition != null) { 562 // resolve properties before we create the processor 563 ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), expressionDefinition); 564 } 565 } 566 567 // at first use custom factory 568 if (routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory() != null) { 569 processor = routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getProcessorFactory().createProcessor(routeContext, definition); 570 } 571 // fallback to default implementation if factory did not create the 572 // processor 573 if (processor == null) { 574 processor = createProcessor(routeContext); 575 } 576 577 // inject id 578 if (processor instanceof IdAware) { 579 String id = getId(definition, routeContext); 580 ((IdAware)processor).setId(id); 581 } 582 583 if (processor == null) { 584 // no processor to make 585 return null; 586 } 587 return wrapProcessor(routeContext, processor); 588 } 589 590 /** 591 * Strategy to execute any custom logic before the {@link Processor} is 592 * created. 593 */ 594 protected void preCreateProcessor() { 595 definition.preCreateProcessor(); 596 } 597 598 /** 599 * Strategy for children to do any custom configuration 600 * 601 * @param output the child to be added as output to this 602 */ 603 public void configureChild(ProcessorDefinition<?> output) { 604 // noop 605 } 606 607 protected String getId(OptionalIdentifiedDefinition<?> def, RouteContext routeContext) { 608 return def.idOrCreate(routeContext.getCamelContext().adapt(ExtendedCamelContext.class).getNodeIdFactory()); 609 } 610}