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