001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.scheduling.quartz;
018
019import java.util.concurrent.Callable;
020import java.util.concurrent.Future;
021import java.util.concurrent.FutureTask;
022
023import org.quartz.SchedulerConfigException;
024import org.quartz.simpl.SimpleThreadPool;
025
026import org.springframework.beans.factory.DisposableBean;
027import org.springframework.beans.factory.InitializingBean;
028import org.springframework.core.task.AsyncListenableTaskExecutor;
029import org.springframework.scheduling.SchedulingException;
030import org.springframework.scheduling.SchedulingTaskExecutor;
031import org.springframework.util.Assert;
032import org.springframework.util.concurrent.ListenableFuture;
033import org.springframework.util.concurrent.ListenableFutureTask;
034
035/**
036 * Subclass of Quartz's SimpleThreadPool that implements Spring's
037 * {@link org.springframework.core.task.TaskExecutor} interface
038 * and listens to Spring lifecycle callbacks.
039 *
040 * <p>Can be shared between a Quartz Scheduler (specified as "taskExecutor")
041 * and other TaskExecutor users, or even used completely independent of
042 * a Quartz Scheduler (as plain TaskExecutor backend).
043 *
044 * @author Juergen Hoeller
045 * @since 2.0
046 * @see org.quartz.simpl.SimpleThreadPool
047 * @see org.springframework.core.task.TaskExecutor
048 * @see SchedulerFactoryBean#setTaskExecutor
049 */
050public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool
051                implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, InitializingBean, DisposableBean {
052
053        private boolean waitForJobsToCompleteOnShutdown = false;
054
055
056        /**
057         * Set whether to wait for running jobs to complete on shutdown.
058         * Default is "false".
059         * @see org.quartz.simpl.SimpleThreadPool#shutdown(boolean)
060         */
061        public void setWaitForJobsToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
062                this.waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
063        }
064
065        @Override
066        public void afterPropertiesSet() throws SchedulerConfigException {
067                initialize();
068        }
069
070
071        @Override
072        public void execute(Runnable task) {
073                Assert.notNull(task, "Runnable must not be null");
074                if (!runInThread(task)) {
075                        throw new SchedulingException("Quartz SimpleThreadPool already shut down");
076                }
077        }
078
079        @Override
080        public void execute(Runnable task, long startTimeout) {
081                execute(task);
082        }
083
084        @Override
085        public Future<?> submit(Runnable task) {
086                FutureTask<Object> future = new FutureTask<>(task, null);
087                execute(future);
088                return future;
089        }
090
091        @Override
092        public <T> Future<T> submit(Callable<T> task) {
093                FutureTask<T> future = new FutureTask<>(task);
094                execute(future);
095                return future;
096        }
097
098        @Override
099        public ListenableFuture<?> submitListenable(Runnable task) {
100                ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
101                execute(future);
102                return future;
103        }
104
105        @Override
106        public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
107                ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
108                execute(future);
109                return future;
110        }
111
112
113        @Override
114        public void destroy() {
115                shutdown(this.waitForJobsToCompleteOnShutdown);
116        }
117
118}