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.concurrent.ExecutorService;
020
021import org.apache.camel.Predicate;
022import org.apache.camel.Processor;
023import org.apache.camel.model.OnCompletionDefinition;
024import org.apache.camel.model.OnCompletionMode;
025import org.apache.camel.model.ProcessorDefinition;
026import org.apache.camel.model.ProcessorDefinitionHelper;
027import org.apache.camel.processor.CamelInternalProcessor;
028import org.apache.camel.processor.OnCompletionProcessor;
029import org.apache.camel.spi.RouteContext;
030
031public class OnCompletionReifier extends ProcessorReifier<OnCompletionDefinition> {
032
033    public OnCompletionReifier(ProcessorDefinition<?> definition) {
034        super((OnCompletionDefinition)definition);
035    }
036
037    @Override
038    public Processor createProcessor(RouteContext routeContext) throws Exception {
039        // assign whether this was a route scoped onCompletion or not
040        // we need to know this later when setting the parent, as only route
041        // scoped should have parent
042        // Note: this logic can possible be removed when the Camel routing
043        // engine decides at runtime
044        // to apply onCompletion in a more dynamic fashion than current code
045        // base
046        // and therefore is in a better position to decide among context/route
047        // scoped OnCompletion at runtime
048        Boolean routeScoped = definition.getRouteScoped();
049        if (routeScoped == null) {
050            routeScoped = definition.getParent() != null;
051        }
052
053        boolean isOnCompleteOnly = definition.getOnCompleteOnly() != null && definition.getOnCompleteOnly();
054        boolean isOnFailureOnly = definition.getOnFailureOnly() != null && definition.getOnFailureOnly();
055        boolean isParallelProcessing = definition.getParallelProcessing() != null && definition.getParallelProcessing();
056        boolean original = definition.getUseOriginalMessagePolicy() != null && definition.getUseOriginalMessagePolicy();
057
058        if (isOnCompleteOnly && isOnFailureOnly) {
059            throw new IllegalArgumentException("Both onCompleteOnly and onFailureOnly cannot be true. Only one of them can be true. On node: " + this);
060        }
061        if (original) {
062            // ensure allow original is turned on
063            routeContext.setAllowUseOriginalMessage(true);
064        }
065
066        Processor childProcessor = this.createChildProcessor(routeContext, true);
067
068        // wrap the on completion route in a unit of work processor
069        CamelInternalProcessor internal = new CamelInternalProcessor(childProcessor);
070        internal.addAdvice(new CamelInternalProcessor.UnitOfWorkProcessorAdvice(routeContext));
071
072        routeContext.setOnCompletion(getId(definition, routeContext), internal);
073
074        Predicate when = null;
075        if (definition.getOnWhen() != null) {
076            when = definition.getOnWhen().getExpression().createPredicate(routeContext);
077        }
078
079        boolean shutdownThreadPool = ProcessorDefinitionHelper.willCreateNewThreadPool(routeContext, definition, isParallelProcessing);
080        ExecutorService threadPool = ProcessorDefinitionHelper.getConfiguredExecutorService(routeContext, "OnCompletion", definition, isParallelProcessing);
081
082        // should be after consumer by default
083        boolean afterConsumer = definition.getMode() == null || definition.getMode() == OnCompletionMode.AfterConsumer;
084
085        OnCompletionProcessor answer = new OnCompletionProcessor(routeContext.getCamelContext(), internal, threadPool, shutdownThreadPool, isOnCompleteOnly, isOnFailureOnly, when,
086                                                                 original, afterConsumer);
087        return answer;
088    }
089
090}