KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > prevayler > implementation > publishing > censorship > StrictTransactionCensor


1 //Prevayler(TM) - The Free-Software Prevalence Layer.
2
//Copyright (C) 2001-2003 Klaus Wuestefeld
3
//This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4
//Contributions: Jon TirsÚn.
5

6 package org.prevayler.implementation.publishing.censorship;
7
8 import org.prevayler.Transaction;
9 import org.prevayler.implementation.snapshot.*;
10
11 import java.io.ByteArrayInputStream JavaDoc;
12 import java.io.ByteArrayOutputStream JavaDoc;
13 import java.util.Date JavaDoc;
14
15 public class StrictTransactionCensor implements TransactionCensor {
16
17     private final Object JavaDoc _king;
18     private Object JavaDoc _royalFoodTaster;
19     private final SnapshotManager _snapshotManager;
20
21     
22     public StrictTransactionCensor(SnapshotManager snapshotManager) {
23         _snapshotManager = snapshotManager;
24         _king = _snapshotManager.recoveredPrevalentSystem();
25         //The _royalFoodTaster cannot be initialized here, or else the pending transactions will not be applied to it.
26
}
27
28     public void approve(Transaction transaction, Date JavaDoc executionTime) throws RuntimeException JavaDoc, Error JavaDoc {
29         try {
30             Transaction transactionCopy = (Transaction)_snapshotManager.deepCopy(transaction, "Unable to produce a copy of the transaction for trying out before applying it to the real system.");
31             transactionCopy.executeOn(royalFoodTaster(), executionTime);
32         } catch (RuntimeException JavaDoc rx) {
33             letTheFoodTasterDie();
34             throw rx;
35         } catch (Error JavaDoc error) {
36             letTheFoodTasterDie();
37             throw error;
38         }
39     }
40
41     private void letTheFoodTasterDie() {
42         _royalFoodTaster = null; // Producing the new food taster now could avoid the next transaction having to wait for its lazy evaluation. Trying to serialize the whole system in RAM right after an OutOfMemoryError has been thrown, for example, isn't a very good idea, though. In that case, there probably will not even be a next transaction... ;)
43
}
44
45     private Object JavaDoc royalFoodTaster() {
46         if (_royalFoodTaster == null) produceNewFoodTaster();
47         return _royalFoodTaster;
48     }
49
50     private void produceNewFoodTaster() {
51         try {
52             ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
53             synchronized (_king) { _snapshotManager.writeSnapshot(_king, out); }
54             _royalFoodTaster = _snapshotManager.readSnapshot(new ByteArrayInputStream JavaDoc(out.toByteArray()));
55         } catch (Exception JavaDoc ex) {
56             ex.printStackTrace();
57             throw new RuntimeException JavaDoc("Unable to produce a copy of the prevalent system for trying out transactions before applying them to the real system.");
58         }
59     }
60
61 }
62
63
64
Popular Tags