/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.impl; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.apache.camel.CamelContext; import org.apache.camel.Consumer; import org.apache.camel.spi.ScheduledPollConsumerScheduler; import org.apache.camel.util.ObjectHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Default {@link org.apache.camel.impl.ScheduledBatchPollingConsumer}. */ public class DefaultScheduledPollConsumerScheduler extends org.apache.camel.support.ServiceSupport implements ScheduledPollConsumerScheduler { private static final Logger LOG = LoggerFactory.getLogger(DefaultScheduledPollConsumerScheduler.class); private CamelContext camelContext; private Consumer consumer; private ScheduledExecutorService scheduledExecutorService; private boolean shutdownExecutor; private volatile List<ScheduledFuture<?>> futures = new ArrayList<ScheduledFuture<?>>(); private Runnable task; private int concurrentTasks = 1; private long initialDelay = 1000; private long delay = 500; private TimeUnit timeUnit = TimeUnit.MILLISECONDS; private boolean useFixedDelay = true; public DefaultScheduledPollConsumerScheduler() { } public DefaultScheduledPollConsumerScheduler(ScheduledExecutorService scheduledExecutorService) { this.scheduledExecutorService = scheduledExecutorService; } public CamelContext getCamelContext() { return camelContext; } public void setCamelContext(CamelContext camelContext) { this.camelContext = camelContext; } public long getInitialDelay() { return initialDelay; } public void setInitialDelay(long initialDelay) { this.initialDelay = initialDelay; } public long getDelay() { return delay; } public void setDelay(long delay) { this.delay = delay; } public TimeUnit getTimeUnit() { return timeUnit; } public void setTimeUnit(TimeUnit timeUnit) { this.timeUnit = timeUnit; } public boolean isUseFixedDelay() { return useFixedDelay; } public void setUseFixedDelay(boolean useFixedDelay) { this.useFixedDelay = useFixedDelay; } public ScheduledExecutorService getScheduledExecutorService() { return scheduledExecutorService; } public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) { this.scheduledExecutorService = scheduledExecutorService; } public int getConcurrentTasks() { return concurrentTasks; } public void setConcurrentTasks(int concurrentTasks) { this.concurrentTasks = concurrentTasks; } @Override public void onInit(Consumer consumer) { this.consumer = consumer; } @Override public void scheduleTask(Runnable task) { this.task = task; } @Override public void unscheduleTask() { if (isSchedulerStarted()) { for (ScheduledFuture<?> future : futures) { future.cancel(true); } futures.clear(); } } @Override public void startScheduler() { // only schedule task if we have not already done that if (futures.size() == 0) { if (isUseFixedDelay()) { if (LOG.isDebugEnabled()) { LOG.debug("Scheduling poll (fixed delay) with initialDelay: {}, delay: {} ({}) for: {}", new Object[]{getInitialDelay(), getDelay(), getTimeUnit().name().toLowerCase(Locale.ENGLISH), consumer.getEndpoint()}); } for (int i = 0; i < concurrentTasks; i++) { futures.add(scheduledExecutorService.scheduleWithFixedDelay(task, getInitialDelay(), getDelay(), getTimeUnit())); } } else { if (LOG.isDebugEnabled()) { LOG.debug("Scheduling poll (fixed rate) with initialDelay: {}, delay: {} ({}) for: {}", new Object[]{getInitialDelay(), getDelay(), getTimeUnit().name().toLowerCase(Locale.ENGLISH), consumer.getEndpoint()}); } for (int i = 0; i < concurrentTasks; i++) { futures.add(scheduledExecutorService.scheduleAtFixedRate(task, getInitialDelay(), getDelay(), getTimeUnit())); } } } } @Override public boolean isSchedulerStarted() { return futures != null && futures.size() > 0; } @Override protected void doStart() throws Exception { ObjectHelper.notNull(consumer, "Consumer", this); ObjectHelper.notNull(camelContext, "CamelContext", this); ObjectHelper.notNull(task, "Task", this); // if no existing executor provided, then create a new thread pool ourselves if (scheduledExecutorService == null) { // we only need one thread in the pool to schedule this task this.scheduledExecutorService = getCamelContext().getExecutorServiceManager() .newScheduledThreadPool(consumer, consumer.getEndpoint().getEndpointUri(), concurrentTasks); // and we should shutdown the thread pool when no longer needed this.shutdownExecutor = true; } } @Override protected void doStop() throws Exception { if (isSchedulerStarted()) { LOG.debug("This consumer is stopping, so cancelling scheduled task: " + futures); for (ScheduledFuture<?> future : futures) { future.cancel(true); } futures.clear(); } if (shutdownExecutor && scheduledExecutorService != null) { getCamelContext().getExecutorServiceManager().shutdownNow(scheduledExecutorService); scheduledExecutorService = null; futures.clear(); } } }