1
2
3
4
5
6
7
8
9
10
11 package org.mule.util.queue;
12
13 import org.mule.util.queue.QueuePersistenceStrategy.Holder;
14 import org.mule.util.xa.AbstractTransactionContext;
15 import org.mule.util.xa.AbstractXAResourceManager;
16 import org.mule.util.xa.ResourceManagerException;
17 import org.mule.util.xa.ResourceManagerSystemException;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.transaction.xa.XAResource;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32
33
34
35
36
37
38
39
40
41
42 public class TransactionalQueueManager extends AbstractXAResourceManager implements QueueManager
43 {
44
45 private static Log logger = LogFactory.getLog(TransactionalQueueManager.class);
46
47 private Map queues = new HashMap();
48
49 private QueuePersistenceStrategy memoryPersistenceStrategy = new MemoryPersistenceStrategy();
50 private QueuePersistenceStrategy persistenceStrategy;
51
52 private QueueConfiguration defaultQueueConfiguration = new QueueConfiguration(false);
53
54 public synchronized QueueSession getQueueSession()
55 {
56 return new TransactionalQueueSession(this, this);
57 }
58
59 public synchronized void setDefaultQueueConfiguration(QueueConfiguration config)
60 {
61 this.defaultQueueConfiguration = config;
62 }
63
64 public synchronized void setQueueConfiguration(String queueName, QueueConfiguration config)
65 {
66 getQueue(queueName).config = config;
67 }
68
69 protected synchronized QueueInfo getQueue(String name)
70 {
71 QueueInfo q = (QueueInfo) queues.get(name);
72 if (q == null)
73 {
74 q = new QueueInfo();
75 q.name = name;
76 q.list = new LinkedList();
77 q.config = defaultQueueConfiguration;
78 queues.put(name, q);
79 }
80 return q;
81 }
82
83
84
85
86
87
88 protected Log getLogger()
89 {
90 return logger;
91 }
92
93 public void close()
94 {
95 try
96 {
97 stop(SHUTDOWN_MODE_NORMAL);
98 }
99 catch (ResourceManagerException e)
100 {
101
102 logger.error("Error disposing manager", e);
103 }
104 }
105
106 protected void doStart() throws ResourceManagerSystemException
107 {
108 if (persistenceStrategy != null)
109 {
110 try
111 {
112 persistenceStrategy.open();
113 }
114 catch (IOException e)
115 {
116 throw new ResourceManagerSystemException(e);
117 }
118 }
119 }
120
121 protected boolean shutdown(int mode, long timeoutMSecs)
122 {
123 try
124 {
125 if (persistenceStrategy != null)
126 {
127 persistenceStrategy.close();
128 }
129 }
130 catch (IOException e)
131 {
132
133 logger.error("Error closing persistent store", e);
134 }
135 return super.shutdown(mode, timeoutMSecs);
136 }
137
138 protected void recover() throws ResourceManagerSystemException
139 {
140 if (persistenceStrategy != null)
141 {
142 try
143 {
144 List msgs = persistenceStrategy.restore();
145 for (Iterator it = msgs.iterator(); it.hasNext();)
146 {
147 Holder h = (Holder) it.next();
148 getQueue(h.getQueue()).putNow(h.getId());
149 }
150 }
151 catch (Exception e)
152 {
153 throw new ResourceManagerSystemException(e);
154 }
155 }
156 }
157
158
159
160
161
162
163 protected AbstractTransactionContext createTransactionContext(Object session)
164 {
165 return new QueueTransactionContext();
166 }
167
168
169
170
171
172
173 protected void doBegin(AbstractTransactionContext context)
174 {
175
176 }
177
178
179
180
181
182
183 protected int doPrepare(AbstractTransactionContext context)
184 {
185 return XAResource.XA_OK;
186 }
187
188
189
190
191
192
193 protected void doCommit(AbstractTransactionContext context) throws ResourceManagerException
194 {
195 QueueTransactionContext ctx = (QueueTransactionContext) context;
196 try
197 {
198 if (ctx.added != null)
199 {
200 for (Iterator it = ctx.added.entrySet().iterator(); it.hasNext();)
201 {
202 Map.Entry entry = (Map.Entry) it.next();
203 QueueInfo queue = (QueueInfo) entry.getKey();
204 List queueAdded = (List) entry.getValue();
205 if (queueAdded != null && queueAdded.size() > 0)
206 {
207 for (Iterator itAdded = queueAdded.iterator(); itAdded.hasNext();)
208 {
209 Object object = itAdded.next();
210 Object id = doStore(queue, object);
211 queue.putNow(id);
212 }
213 }
214 }
215 }
216 if (ctx.removed != null)
217 {
218 for (Iterator it = ctx.removed.entrySet().iterator(); it.hasNext();)
219 {
220 Map.Entry entry = (Map.Entry) it.next();
221 QueueInfo queue = (QueueInfo) entry.getKey();
222 List queueRemoved = (List) entry.getValue();
223 if (queueRemoved != null && queueRemoved.size() > 0)
224 {
225 for (Iterator itRemoved = queueRemoved.iterator(); itRemoved.hasNext();)
226 {
227 Object id = itRemoved.next();
228 doRemove(queue, id);
229 }
230 }
231 }
232 }
233 }
234 catch (Exception e)
235 {
236
237
238
239 throw new ResourceManagerException(e);
240 }
241 finally
242 {
243 ctx.added = null;
244 ctx.removed = null;
245 }
246 }
247
248 protected Object doStore(QueueInfo queue, Object object) throws IOException
249 {
250 QueuePersistenceStrategy ps = (queue.config.persistent)
251 ? persistenceStrategy : memoryPersistenceStrategy;
252 Object id = ps.store(queue.name, object);
253 return id;
254 }
255
256 protected void doRemove(QueueInfo queue, Object id) throws IOException
257 {
258 QueuePersistenceStrategy ps = (queue.config.persistent)
259 ? persistenceStrategy : memoryPersistenceStrategy;
260 ps.remove(queue.name, id);
261 }
262
263 protected Object doLoad(QueueInfo queue, Object id) throws IOException
264 {
265 QueuePersistenceStrategy ps = (queue.config.persistent)
266 ? persistenceStrategy : memoryPersistenceStrategy;
267 Object obj = ps.load(queue.name, id);
268 return obj;
269 }
270
271
272
273
274
275
276 protected void doRollback(AbstractTransactionContext context) throws ResourceManagerException
277 {
278 QueueTransactionContext ctx = (QueueTransactionContext) context;
279 if (ctx.removed != null)
280 {
281 for (Iterator it = ctx.removed.entrySet().iterator(); it.hasNext();)
282 {
283 Map.Entry entry = (Map.Entry) it.next();
284 QueueInfo queue = (QueueInfo) entry.getKey();
285 List queueRemoved = (List) entry.getValue();
286 if (queueRemoved != null && queueRemoved.size() > 0)
287 {
288 for (Iterator itRemoved = queueRemoved.iterator(); itRemoved.hasNext();)
289 {
290 Object id = itRemoved.next();
291 queue.putNow(id);
292 }
293 }
294 }
295 }
296 ctx.added = null;
297 ctx.removed = null;
298 }
299
300 protected class QueueTransactionContext extends AbstractTransactionContext
301 {
302 protected Map added;
303 protected Map removed;
304
305 public boolean offer(QueueInfo queue, Object item, long timeout) throws InterruptedException
306 {
307 readOnly = false;
308 if (added == null)
309 {
310 added = new HashMap();
311 }
312 List queueAdded = (List) added.get(queue);
313 if (queueAdded == null)
314 {
315 queueAdded = new ArrayList();
316 added.put(queue, queueAdded);
317 }
318
319 if (queue.offer(null, queueAdded.size(), Long.MAX_VALUE))
320 {
321 queueAdded.add(item);
322 return true;
323 }
324 else
325 {
326 return false;
327 }
328 }
329
330 public Object poll(QueueInfo queue, long timeout) throws IOException, InterruptedException
331 {
332 readOnly = false;
333 if (added != null)
334 {
335 List queueAdded = (List)added.get(queue);
336 if (queueAdded != null)
337 {
338 return queueAdded.remove(queueAdded.size() - 1);
339 }
340 }
341 Object o = queue.poll(Long.MAX_VALUE);
342 if (o != null)
343 {
344 if (removed == null)
345 {
346 removed = new HashMap();
347 }
348 List queueRemoved = (List) removed.get(queue);
349 if (queueRemoved == null)
350 {
351 queueRemoved = new ArrayList();
352 removed.put(queue, queueRemoved);
353 }
354 queueRemoved.add(o);
355 o = doLoad(queue, o);
356 }
357 return o;
358 }
359
360 public Object peek(QueueInfo queue) throws IOException, InterruptedException
361 {
362 readOnly = false;
363 if (added != null)
364 {
365 List queueAdded = (List) added.get(queue);
366 if (queueAdded != null)
367 {
368 return queueAdded.get(queueAdded.size() - 1);
369 }
370 }
371 Object o = queue.peek();
372 if (o != null)
373 {
374 o = doLoad(queue, o);
375 }
376 return o;
377 }
378
379 public int size(QueueInfo queue)
380 {
381 int sz = queue.list.size();
382 if (added != null)
383 {
384 List queueAdded = (List) added.get(queue);
385 if (queueAdded != null)
386 {
387 sz += queueAdded.size();
388 }
389 }
390 return sz;
391 }
392
393 }
394
395
396
397
398 public QueuePersistenceStrategy getPersistenceStrategy()
399 {
400 return persistenceStrategy;
401 }
402
403
404
405
406 public void setPersistenceStrategy(QueuePersistenceStrategy persistenceStrategy)
407 {
408 if (operationMode != OPERATION_MODE_STOPPED)
409 {
410 throw new IllegalStateException();
411 }
412 this.persistenceStrategy = persistenceStrategy;
413 }
414
415 public QueuePersistenceStrategy getMemoryPersistenceStrategy()
416 {
417 return memoryPersistenceStrategy;
418 }
419
420 public void setMemoryPersistenceStrategy(QueuePersistenceStrategy memoryPersistenceStrategy)
421 {
422 if (operationMode != OPERATION_MODE_STOPPED)
423 {
424 throw new IllegalStateException();
425 }
426 this.memoryPersistenceStrategy = memoryPersistenceStrategy;
427 }
428 }