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