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