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.impl;
018
019import java.util.Locale;
020import java.util.concurrent.ScheduledExecutorService;
021import java.util.concurrent.ScheduledFuture;
022import java.util.concurrent.TimeUnit;
023
024import org.apache.camel.CamelContext;
025import org.apache.camel.Consumer;
026import org.apache.camel.spi.ScheduledPollConsumerScheduler;
027import org.apache.camel.util.ObjectHelper;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * Default {@link org.apache.camel.impl.ScheduledBatchPollingConsumer}.
033 */
034public class DefaultScheduledPollConsumerScheduler extends org.apache.camel.support.ServiceSupport implements ScheduledPollConsumerScheduler {
035
036    private static final Logger LOG = LoggerFactory.getLogger(DefaultScheduledPollConsumerScheduler.class);
037    private CamelContext camelContext;
038    private Consumer consumer;
039    private ScheduledExecutorService scheduledExecutorService;
040    private boolean shutdownExecutor;
041    private volatile ScheduledFuture<?> future;
042    private Runnable task;
043
044    private long initialDelay = 1000;
045    private long delay = 500;
046    private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
047    private boolean useFixedDelay = true;
048
049    public CamelContext getCamelContext() {
050        return camelContext;
051    }
052
053    public void setCamelContext(CamelContext camelContext) {
054        this.camelContext = camelContext;
055    }
056
057    public long getInitialDelay() {
058        return initialDelay;
059    }
060
061    public void setInitialDelay(long initialDelay) {
062        this.initialDelay = initialDelay;
063    }
064
065    public long getDelay() {
066        return delay;
067    }
068
069    public void setDelay(long delay) {
070        this.delay = delay;
071    }
072
073    public TimeUnit getTimeUnit() {
074        return timeUnit;
075    }
076
077    public void setTimeUnit(TimeUnit timeUnit) {
078        this.timeUnit = timeUnit;
079    }
080
081    public boolean isUseFixedDelay() {
082        return useFixedDelay;
083    }
084
085    public void setUseFixedDelay(boolean useFixedDelay) {
086        this.useFixedDelay = useFixedDelay;
087    }
088
089    public ScheduledExecutorService getScheduledExecutorService() {
090        return scheduledExecutorService;
091    }
092
093    public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) {
094        this.scheduledExecutorService = scheduledExecutorService;
095    }
096
097    @Override
098    public void onInit(Consumer consumer) {
099        this.consumer = consumer;
100    }
101
102    @Override
103    public void scheduleTask(Runnable task) {
104        this.task = task;
105    }
106
107    @Override
108    public void unscheduleTask() {
109        if (future != null) {
110            future.cancel(false);
111        }
112    }
113
114    @Override
115    public void startScheduler() {
116        // only schedule task if we have not already done that
117        if (future == null) {
118            if (isUseFixedDelay()) {
119                if (LOG.isDebugEnabled()) {
120                    LOG.debug("Scheduling poll (fixed delay) with initialDelay: {}, delay: {} ({}) for: {}",
121                            new Object[]{getInitialDelay(), getDelay(), getTimeUnit().name().toLowerCase(Locale.ENGLISH), consumer.getEndpoint()});
122                }
123                future = scheduledExecutorService.scheduleWithFixedDelay(task, getInitialDelay(), getDelay(), getTimeUnit());
124            } else {
125                if (LOG.isDebugEnabled()) {
126                    LOG.debug("Scheduling poll (fixed rate) with initialDelay: {}, delay: {} ({}) for: {}",
127                            new Object[]{getInitialDelay(), getDelay(), getTimeUnit().name().toLowerCase(Locale.ENGLISH), consumer.getEndpoint()});
128                }
129                future = scheduledExecutorService.scheduleAtFixedRate(task, getInitialDelay(), getDelay(), getTimeUnit());
130            }
131        }
132    }
133
134    @Override
135    public boolean isSchedulerStarted() {
136        return future != null;
137    }
138
139    @Override
140    protected void doStart() throws Exception {
141        ObjectHelper.notNull(consumer, "Consumer", this);
142        ObjectHelper.notNull(camelContext, "CamelContext", this);
143        ObjectHelper.notNull(task, "Task", this);
144
145        // if no existing executor provided, then create a new thread pool ourselves
146        if (scheduledExecutorService == null) {
147            // we only need one thread in the pool to schedule this task
148            this.scheduledExecutorService = getCamelContext().getExecutorServiceManager()
149                    .newSingleThreadScheduledExecutor(consumer, consumer.getEndpoint().getEndpointUri());
150            // and we should shutdown the thread pool when no longer needed
151            this.shutdownExecutor = true;
152        }
153    }
154
155    @Override
156    protected void doStop() throws Exception {
157        if (future != null) {
158            LOG.debug("This consumer is stopping, so cancelling scheduled task: " + future);
159            future.cancel(true);
160            future = null;
161        }
162
163        if (shutdownExecutor && scheduledExecutorService != null) {
164            getCamelContext().getExecutorServiceManager().shutdownNow(scheduledExecutorService);
165            scheduledExecutorService = null;
166            future = null;
167        }
168    }
169
170}