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;
020import java.util.concurrent.TimeUnit;
021
022import org.apache.camel.Processor;
023import org.apache.camel.Route;
024import org.apache.camel.builder.ThreadPoolProfileBuilder;
025import org.apache.camel.model.ProcessorDefinition;
026import org.apache.camel.model.ThreadsDefinition;
027import org.apache.camel.processor.ThreadsProcessor;
028import org.apache.camel.spi.ExecutorServiceManager;
029import org.apache.camel.spi.ThreadPoolProfile;
030import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
031
032public class ThreadsReifier extends ProcessorReifier<ThreadsDefinition> {
033
034    public ThreadsReifier(Route route, ProcessorDefinition<?> definition) {
035        super(route, (ThreadsDefinition) definition);
036    }
037
038    @Override
039    public Processor createProcessor() throws Exception {
040        // the threads name
041        String name = definition.getThreadName() != null ? parseString(definition.getThreadName()) : "Threads";
042        // prefer any explicit configured executor service
043        boolean shutdownThreadPool = willCreateNewThreadPool(definition, true);
044        ExecutorService threadPool = getConfiguredExecutorService(name, definition, false);
045
046        // resolve what rejected policy to use
047        ThreadPoolRejectedPolicy policy = resolveRejectedPolicy();
048        if (policy == null) {
049            if (parseBoolean(definition.getCallerRunsWhenRejected(), true)) {
050                // should use caller runs by default if not configured
051                policy = ThreadPoolRejectedPolicy.CallerRuns;
052            } else {
053                policy = ThreadPoolRejectedPolicy.Abort;
054            }
055        }
056        log.debug("Using ThreadPoolRejectedPolicy: {}", policy);
057
058        // if no explicit then create from the options
059        if (threadPool == null) {
060            ExecutorServiceManager manager = camelContext.getExecutorServiceManager();
061            // create the thread pool using a builder
062            ThreadPoolProfile profile = new ThreadPoolProfileBuilder(name)
063                .poolSize(definition.getPoolSize() != null ? parseInt(definition.getPoolSize()) : null)
064                .maxPoolSize(definition.getMaxPoolSize() != null ? parseInt(definition.getMaxPoolSize()) : null)
065                .keepAliveTime(definition.getKeepAliveTime() != null ? parseDuration(definition.getKeepAliveTime()) : null,
066                               definition.getTimeUnit() != null ? parse(TimeUnit.class, definition.getTimeUnit()) : null)
067                .maxQueueSize(definition.getMaxQueueSize() != null ? parseInt(definition.getMaxQueueSize()) : null)
068                .rejectedPolicy(policy)
069                .allowCoreThreadTimeOut(definition.getAllowCoreThreadTimeOut() != null ? parseBoolean(definition.getAllowCoreThreadTimeOut(), false) : null)
070                .build();
071            threadPool = manager.newThreadPool(definition, name, profile);
072            shutdownThreadPool = true;
073        } else {
074            if (definition.getThreadName() != null && !definition.getThreadName().equals("Threads")) {
075                throw new IllegalArgumentException("ThreadName and executorServiceRef options cannot be used together.");
076            }
077            if (definition.getPoolSize() != null) {
078                throw new IllegalArgumentException("PoolSize and executorServiceRef options cannot be used together.");
079            }
080            if (definition.getMaxPoolSize() != null) {
081                throw new IllegalArgumentException("MaxPoolSize and executorServiceRef options cannot be used together.");
082            }
083            if (definition.getKeepAliveTime() != null) {
084                throw new IllegalArgumentException("KeepAliveTime and executorServiceRef options cannot be used together.");
085            }
086            if (definition.getTimeUnit() != null) {
087                throw new IllegalArgumentException("TimeUnit and executorServiceRef options cannot be used together.");
088            }
089            if (definition.getMaxQueueSize() != null) {
090                throw new IllegalArgumentException("MaxQueueSize and executorServiceRef options cannot be used together.");
091            }
092            if (definition.getRejectedPolicy() != null) {
093                throw new IllegalArgumentException("RejectedPolicy and executorServiceRef options cannot be used together.");
094            }
095            if (definition.getAllowCoreThreadTimeOut() != null) {
096                throw new IllegalArgumentException("AllowCoreThreadTimeOut and executorServiceRef options cannot be used together.");
097            }
098        }
099
100        return new ThreadsProcessor(camelContext, threadPool, shutdownThreadPool, policy);
101    }
102
103    protected ThreadPoolRejectedPolicy resolveRejectedPolicy() {
104        if (definition.getExecutorServiceRef() != null && definition.getRejectedPolicy() == null) {
105            ThreadPoolProfile threadPoolProfile = camelContext.getExecutorServiceManager().getThreadPoolProfile(parseString(definition.getExecutorServiceRef()));
106            if (threadPoolProfile != null) {
107                return threadPoolProfile.getRejectedPolicy();
108            }
109        }
110        return parse(ThreadPoolRejectedPolicy.class, definition.getRejectedPolicy());
111    }
112
113}