1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport;
12
13 import org.mule.api.MuleException;
14 import org.mule.api.construct.FlowConstruct;
15 import org.mule.api.endpoint.InboundEndpoint;
16 import org.mule.api.lifecycle.CreateException;
17 import org.mule.api.transport.Connector;
18 import org.mule.config.i18n.CoreMessages;
19 import org.mule.util.ObjectUtils;
20
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.concurrent.Future;
25 import java.util.concurrent.RejectedExecutionException;
26 import java.util.concurrent.ScheduledExecutorService;
27 import java.util.concurrent.ScheduledFuture;
28 import java.util.concurrent.TimeUnit;
29
30
31
32
33
34
35
36 public abstract class AbstractPollingMessageReceiver extends AbstractMessageReceiver
37 {
38 public static final long DEFAULT_POLL_FREQUENCY = 1000;
39 public static final TimeUnit DEFAULT_POLL_TIMEUNIT = TimeUnit.MILLISECONDS;
40
41 public static final long DEFAULT_STARTUP_DELAY = 1000;
42
43 private long frequency = DEFAULT_POLL_FREQUENCY;
44 private TimeUnit timeUnit = DEFAULT_POLL_TIMEUNIT;
45
46
47 protected final Map<ScheduledFuture, PollingReceiverWorker> schedules = new HashMap<ScheduledFuture, PollingReceiverWorker>();
48
49 public AbstractPollingMessageReceiver(Connector connector,
50 FlowConstruct flowConstruct,
51 final InboundEndpoint endpoint) throws CreateException
52 {
53 super(connector, flowConstruct, endpoint);
54 }
55
56 @Override
57 protected void doStart() throws MuleException
58 {
59 try
60 {
61 this.schedule();
62 }
63 catch (Exception ex)
64 {
65 this.stop();
66 throw new CreateException(CoreMessages.failedToScheduleWork(), ex, this);
67 }
68 }
69
70 @Override
71 protected void doStop() throws MuleException
72 {
73 this.unschedule();
74 }
75
76
77
78
79
80
81
82
83
84
85
86 protected void schedule()
87 throws RejectedExecutionException, NullPointerException, IllegalArgumentException
88 {
89 synchronized (schedules)
90 {
91
92
93
94
95 PollingReceiverWorker pollingReceiverWorker = this.createWork();
96 ScheduledFuture schedule = connector.getScheduler().scheduleWithFixedDelay(
97 new PollingReceiverWorkerSchedule(pollingReceiverWorker), DEFAULT_STARTUP_DELAY,
98 this.getFrequency(), this.getTimeUnit());
99 schedules.put(schedule, pollingReceiverWorker);
100
101 if (logger.isDebugEnabled())
102 {
103 logger.debug(ObjectUtils.identityToShortString(this) + " scheduled "
104 + ObjectUtils.identityToShortString(schedule) + " with " + frequency
105 + " " + getTimeUnit() + " polling frequency");
106 }
107 }
108 }
109
110
111
112
113
114
115 protected void unschedule()
116 {
117 synchronized (schedules)
118 {
119
120 for (Iterator<ScheduledFuture> i = schedules.keySet().iterator(); i.hasNext();)
121 {
122 ScheduledFuture schedule = i.next();
123 schedule.cancel(false);
124
125 int shutdownTimeout = connector.getMuleContext().getConfiguration().getShutdownTimeout();
126 PollingReceiverWorker worker = schedules.get(schedule);
127 for (int elapsed = 0; worker.isRunning() && elapsed < shutdownTimeout; elapsed += 50)
128 {
129 try
130 {
131 Thread.sleep(50);
132 }
133 catch (InterruptedException e)
134 {
135 logger.warn(
136 ObjectUtils.identityToShortString(this) + " interrupted while waiting for poll() to complete as part of message receiver stop.",
137 e);
138 break;
139 }
140 }
141 i.remove();
142
143 if (logger.isDebugEnabled())
144 {
145 logger.debug(ObjectUtils.identityToShortString(this) + " cancelled polling schedule: "
146 + ObjectUtils.identityToShortString(schedule));
147 }
148 }
149 }
150 }
151
152 public void disableNativeScheduling()
153 {
154 this.unschedule();
155 }
156
157 protected PollingReceiverWorker createWork()
158 {
159 return new PollingReceiverWorker(this);
160 }
161
162 public long getFrequency()
163 {
164 return frequency;
165 }
166
167
168
169 public void setFrequency(long value)
170 {
171 if (value <= 0)
172 {
173 frequency = DEFAULT_POLL_FREQUENCY;
174 }
175 else
176 {
177 frequency = value;
178 }
179 }
180
181 public TimeUnit getTimeUnit()
182 {
183 return timeUnit;
184 }
185
186 public void setTimeUnit(TimeUnit timeUnit)
187 {
188 this.timeUnit = timeUnit;
189 }
190
191
192
193
194
195
196
197
198
199
200
201 protected int getBatchSize(int available)
202 {
203 if (available <= 0)
204 {
205 return 0;
206 }
207
208 int maxThreads = connector.getReceiverThreadingProfile().getMaxThreadsActive();
209 return Math.max(1, Math.min(available, ((maxThreads / 2) - 1)));
210 }
211
212
213
214
215 public final void performPoll() throws Exception
216 {
217 if (!pollOnPrimaryInstanceOnly() || flowConstruct.getMuleContext().isPrimaryPollingInstance())
218 {
219 poll();
220 }
221 }
222
223
224
225
226 protected boolean pollOnPrimaryInstanceOnly()
227 {
228 return false;
229 }
230
231
232 protected abstract void poll() throws Exception;
233 }