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