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.List;
021import java.util.concurrent.ExecutorService;
022
023import org.apache.camel.AggregationStrategy;
024import org.apache.camel.CamelContextAware;
025import org.apache.camel.Processor;
026import org.apache.camel.model.MulticastDefinition;
027import org.apache.camel.model.ProcessorDefinition;
028import org.apache.camel.model.ProcessorDefinitionHelper;
029import org.apache.camel.processor.MulticastProcessor;
030import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
031import org.apache.camel.processor.aggregate.ShareUnitOfWorkAggregationStrategy;
032import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
033import org.apache.camel.spi.RouteContext;
034import org.apache.camel.support.CamelContextHelper;
035
036public class MulticastReifier extends ProcessorReifier<MulticastDefinition> {
037
038    public MulticastReifier(ProcessorDefinition<?> definition) {
039        super((MulticastDefinition)definition);
040    }
041
042    @Override
043    public Processor createProcessor(RouteContext routeContext) throws Exception {
044        Processor answer = this.createChildProcessor(routeContext, true);
045
046        // force the answer as a multicast processor even if there is only one
047        // child processor in the multicast
048        if (!(answer instanceof MulticastProcessor)) {
049            List<Processor> list = new ArrayList<>(1);
050            list.add(answer);
051            answer = createCompositeProcessor(routeContext, list);
052        }
053        return answer;
054    }
055
056    @Override
057    protected Processor createCompositeProcessor(RouteContext routeContext, List<Processor> list) throws Exception {
058        final AggregationStrategy strategy = createAggregationStrategy(routeContext);
059
060        boolean isParallelProcessing = definition.getParallelProcessing() != null && definition.getParallelProcessing();
061        boolean isShareUnitOfWork = definition.getShareUnitOfWork() != null && definition.getShareUnitOfWork();
062        boolean isStreaming = definition.getStreaming() != null && definition.getStreaming();
063        boolean isStopOnException = definition.getStopOnException() != null && definition.getStopOnException();
064        boolean isParallelAggregate = definition.getParallelAggregate() != null && definition.getParallelAggregate();
065        boolean isStopOnAggregateException = definition.getStopOnAggregateException() != null && definition.getStopOnAggregateException();
066
067        boolean shutdownThreadPool = ProcessorDefinitionHelper.willCreateNewThreadPool(routeContext, definition, isParallelProcessing);
068        ExecutorService threadPool = ProcessorDefinitionHelper.getConfiguredExecutorService(routeContext, "Multicast", definition, isParallelProcessing);
069
070        long timeout = definition.getTimeout() != null ? definition.getTimeout() : 0;
071        if (timeout > 0 && !isParallelProcessing) {
072            throw new IllegalArgumentException("Timeout is used but ParallelProcessing has not been enabled.");
073        }
074        if (definition.getOnPrepareRef() != null) {
075            definition.setOnPrepare(CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), definition.getOnPrepareRef(), Processor.class));
076        }
077
078        MulticastProcessor answer = new MulticastProcessor(routeContext.getCamelContext(), list, strategy, isParallelProcessing, threadPool, shutdownThreadPool, isStreaming,
079                                                           isStopOnException, timeout, definition.getOnPrepare(), isShareUnitOfWork, isParallelAggregate,
080                                                           isStopOnAggregateException);
081        return answer;
082    }
083
084    private AggregationStrategy createAggregationStrategy(RouteContext routeContext) {
085        AggregationStrategy strategy = definition.getAggregationStrategy();
086        if (strategy == null && definition.getStrategyRef() != null) {
087            Object aggStrategy = routeContext.lookup(definition.getStrategyRef(), Object.class);
088            if (aggStrategy instanceof AggregationStrategy) {
089                strategy = (AggregationStrategy)aggStrategy;
090            } else if (aggStrategy != null) {
091                AggregationStrategyBeanAdapter adapter = new AggregationStrategyBeanAdapter(aggStrategy, definition.getStrategyMethodName());
092                if (definition.getStrategyMethodAllowNull() != null) {
093                    adapter.setAllowNullNewExchange(definition.getStrategyMethodAllowNull());
094                    adapter.setAllowNullOldExchange(definition.getStrategyMethodAllowNull());
095                }
096                strategy = adapter;
097            } else {
098                throw new IllegalArgumentException("Cannot find AggregationStrategy in Registry with name: " + definition.getStrategyRef());
099            }
100        }
101
102        if (strategy == null) {
103            // default to use latest aggregation strategy
104            strategy = new UseLatestAggregationStrategy();
105        }
106
107        if (strategy instanceof CamelContextAware) {
108            ((CamelContextAware)strategy).setCamelContext(routeContext.getCamelContext());
109        }
110
111        if (definition.getShareUnitOfWork() != null && definition.getShareUnitOfWork()) {
112            // wrap strategy in share unit of work
113            strategy = new ShareUnitOfWorkAggregationStrategy(strategy);
114        }
115
116        return strategy;
117    }
118
119}