1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.mule.work;
29
30 import org.mule.api.MuleException;
31 import org.mule.api.config.ThreadingProfile;
32 import org.mule.api.context.WorkManager;
33 import org.mule.api.work.WorkExecutor;
34
35 import java.text.MessageFormat;
36 import java.util.List;
37
38 import javax.resource.spi.XATerminator;
39 import javax.resource.spi.work.ExecutionContext;
40 import javax.resource.spi.work.Work;
41 import javax.resource.spi.work.WorkCompletedException;
42 import javax.resource.spi.work.WorkException;
43 import javax.resource.spi.work.WorkListener;
44
45 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
46 import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
47 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
48
49 import org.apache.commons.logging.Log;
50 import org.apache.commons.logging.LogFactory;
51
52
53
54
55
56
57 public class MuleWorkManager implements WorkManager
58 {
59
60
61
62 protected static final Log logger = LogFactory.getLog(MuleWorkManager.class);
63
64
65
66
67 private static final long SHUTDOWN_TIMEOUT = 5000L;
68
69
70
71
72 private final ThreadingProfile threadingProfile;
73
74
75
76
77
78 private volatile ExecutorService workExecutorService;
79 private final String name;
80
81
82
83
84 private final WorkExecutor scheduleWorkExecutor = new ScheduleWorkExecutor();
85 private final WorkExecutor startWorkExecutor = new StartWorkExecutor();
86 private final WorkExecutor syncWorkExecutor = new SyncWorkExecutor();
87
88 public MuleWorkManager(ThreadingProfile profile, String name)
89 {
90 super();
91
92 if (name == null)
93 {
94 name = "WorkManager#" + hashCode();
95 }
96
97 this.threadingProfile = profile;
98 this.name = name;
99 }
100
101 public synchronized void start() throws MuleException
102 {
103 if (workExecutorService == null)
104 {
105 workExecutorService = threadingProfile.createPool(name);
106 }
107 }
108
109 public synchronized void dispose()
110 {
111 if (workExecutorService != null)
112 {
113 try
114 {
115
116 List outstanding = workExecutorService.shutdownNow();
117
118
119 if (!workExecutorService.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
120 {
121 if (logger.isWarnEnabled())
122 {
123 logger.warn(MessageFormat.format(
124 "Pool {0} did not terminate in time; {1} work items were cancelled.",
125 new Object[] {name, outstanding.isEmpty() ? "No" : Integer.toString(outstanding.size())}));
126 }
127 }
128 }
129 catch (InterruptedException ie)
130 {
131
132 workExecutorService.shutdownNow();
133
134 Thread.currentThread().interrupt();
135 }
136 finally
137 {
138 workExecutorService = null;
139 }
140 }
141 }
142
143
144
145 public XATerminator getXATerminator()
146 {
147 return null;
148 }
149
150
151
152
153
154
155 public void doWork(Work work) throws WorkException
156 {
157 executeWork(new WorkerContext(work), syncWorkExecutor);
158 }
159
160
161
162
163
164
165
166
167 public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)
168 throws WorkException
169 {
170 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
171 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
172 executeWork(workWrapper, syncWorkExecutor);
173 }
174
175
176
177
178
179
180 public long startWork(Work work) throws WorkException
181 {
182 WorkerContext workWrapper = new WorkerContext(work);
183 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
184 executeWork(workWrapper, startWorkExecutor);
185 return System.currentTimeMillis() - workWrapper.getAcceptedTime();
186 }
187
188
189
190
191
192
193
194
195 public long startWork(Work work,
196 long startTimeout,
197 ExecutionContext execContext,
198 WorkListener workListener) throws WorkException
199 {
200 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
201 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
202 executeWork(workWrapper, startWorkExecutor);
203 return System.currentTimeMillis() - workWrapper.getAcceptedTime();
204 }
205
206
207
208
209
210
211 public void scheduleWork(Work work) throws WorkException
212 {
213 WorkerContext workWrapper = new WorkerContext(work);
214 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
215 executeWork(workWrapper, scheduleWorkExecutor);
216 }
217
218
219
220
221
222
223
224
225 public void scheduleWork(Work work,
226 long startTimeout,
227 ExecutionContext execContext,
228 WorkListener workListener) throws WorkException
229 {
230 WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
231 workWrapper.setThreadPriority(Thread.currentThread().getPriority());
232 executeWork(workWrapper, scheduleWorkExecutor);
233 }
234
235
236
237
238 public void execute(Runnable work)
239 {
240 if (workExecutorService == null)
241 {
242 throw new IllegalStateException("This MuleWorkManager '" + name + "' was never started");
243 }
244 else if (workExecutorService.isShutdown())
245 {
246 throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
247 }
248
249 workExecutorService.execute(work);
250 }
251
252
253
254
255
256
257
258
259 private void executeWork(WorkerContext work, WorkExecutor workExecutor) throws WorkException
260 {
261 if (workExecutorService == null || workExecutorService.isShutdown())
262 {
263 throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
264 }
265
266 try
267 {
268 work.workAccepted(this);
269 workExecutor.doExecute(work, workExecutorService);
270 WorkException exception = work.getWorkException();
271 if (null != exception)
272 {
273 throw exception;
274 }
275 }
276 catch (InterruptedException e)
277 {
278 WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted for WorkManager: " + name, e);
279 wcj.setErrorCode(WorkException.INTERNAL);
280 throw wcj;
281 }
282 }
283
284 }