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