KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > prevayler > PrevaylerFactory


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

5 package org.prevayler;
6
7 import java.io.IOException JavaDoc;
8 import java.io.Serializable JavaDoc;
9
10 import org.prevayler.implementation.PrevaylerImpl;
11 import org.prevayler.implementation.clock.MachineClock;
12 import org.prevayler.implementation.logging.PersistentLogger;
13 import org.prevayler.implementation.logging.TransactionLogger;
14 import org.prevayler.implementation.logging.TransientLogger;
15 import org.prevayler.implementation.publishing.CentralPublisher;
16 import org.prevayler.implementation.publishing.TransactionPublisher;
17 import org.prevayler.implementation.publishing.censorship.LiberalTransactionCensor;
18 import org.prevayler.implementation.publishing.censorship.StrictTransactionCensor;
19 import org.prevayler.implementation.publishing.censorship.TransactionCensor;
20 import org.prevayler.implementation.replication.ServerListener;
21 import org.prevayler.implementation.replication.ClientPublisher;
22 import org.prevayler.implementation.snapshot.NullSnapshotManager;
23 import org.prevayler.implementation.snapshot.SnapshotManager;
24
25 /** Provides easy access to all Prevayler configurations and implementations available in this distribution.
26  * Static methods are also provided as short-cuts for the most common configurations.
27  * <br>By default, the Prevayler instances created by this class will write their Transactions to .transactionLog files before executing them. The FileDescriptor.sync() method is called to make sure the Java file write-buffers have been written to the operating system. Many operating systems, including most recent versions of Linux and Windows, allow the hard-drive's write-cache to be disabled. This guarantees no executed Transaction will be lost in the event of a power shortage, for example.
28  * <br>Also by default, the Prevayler instances created by this class will filter out all Transactions that would throw a RuntimeException or Error if executed on the Prevalent System. This requires enough RAM to hold another copy of the prevalent system.
29  * @see Prevayler
30  */

31 public class PrevaylerFactory {
32
33     private Object JavaDoc _prevalentSystem;
34     private Clock _clock;
35
36     private boolean _transactionFiltering = true;
37
38     private boolean _transientMode;
39     private String JavaDoc _prevalenceBase;
40     private SnapshotManager _snapshotManager;
41
42     private long _transactionLogSizeThreshold;
43     private long _transactionLogAgeThreshold;
44     
45     private int _serverPort = -1;
46     private String JavaDoc _remoteServerIpAddress;
47     private int _remoteServerPort;
48     public static final int DEFAULT_REPLICATION_PORT = 8756;
49
50
51     /** Creates a Prevayler that will use a directory called "PrevalenceBase" under the current directory to read and write its .snapshot and .transactionLog files.
52      * @param newPrevalentSystem The newly started, "empty" prevalent system that will be used as a starting point for every system startup, until the first snapshot is taken.
53      */

54     public static Prevayler createPrevayler(Serializable JavaDoc newPrevalentSystem) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
55         return createPrevayler(newPrevalentSystem, "PrevalenceBase");
56     }
57
58
59     /** Creates a Prevayler that will use the given prevalenceBase directory to read and write its .snapshot and .transactionLog files.
60      * @param newPrevalentSystem The newly started, "empty" prevalent system that will be used as a starting point for every system startup, until the first snapshot is taken.
61      * @param prevalenceBase The directory where the .snapshot files and .transactionLog files will be read and written.
62      */

63     public static Prevayler createPrevayler(Serializable JavaDoc newPrevalentSystem, String JavaDoc prevalenceBase) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
64         PrevaylerFactory factory = new PrevaylerFactory();
65         factory.configurePrevalentSystem(newPrevalentSystem);
66         factory.configurePrevalenceBase(prevalenceBase);
67         return factory.create();
68     }
69
70
71     /** Creates a Prevayler that will execute Transactions WITHOUT writing them to disk. This is useful for running automated tests or demos MUCH faster than with a regular Prevayler.
72      *
73      * Attempts to take snapshots on this transient Prevayler will throw an IOException.
74      * @param newPrevalentSystem The newly started, "empty" prevalent system.
75      * @see #createCheckpointPrevayler(Serializable newPrevalentSystem, String snapshotDirectory)
76      */

77     public static Prevayler createTransientPrevayler(Serializable JavaDoc newPrevalentSystem) {
78         PrevaylerFactory factory = new PrevaylerFactory();
79         factory.configurePrevalentSystem(newPrevalentSystem);
80         factory.configureSnapshotManager(new NullSnapshotManager(newPrevalentSystem, "Transient Prevaylers are unable to take snapshots."));
81         factory.configureTransientMode(true);
82         try {
83             return factory.create();
84         } catch (Exception JavaDoc e) {
85             e.printStackTrace(); //Transient Prevayler creation should not fail.
86
return null;
87         }
88     }
89
90
91     /** @deprecated Use createCheckpointPrevayler() instead of this method. Deprecated since Prevayler2.00.001.
92      */

93     public static Prevayler createTransientPrevayler(Serializable JavaDoc newPrevalentSystem, String JavaDoc snapshotDirectory) {
94         return createCheckpointPrevayler(newPrevalentSystem, snapshotDirectory);
95     }
96
97     /** Creates a Prevayler that will execute Transactions WITHOUT writing them to disk. Snapshots will work as "checkpoints" for the system, therefore. This is useful for stand-alone applications that have a "Save" button, for example.
98      * @param newPrevalentSystem The newly started, "empty" prevalent system that will be used as a starting point for every system startup, until the first snapshot is taken.
99      * @param snapshotDirectory The directory where the .snapshot files will be read and written.
100      */

101     public static Prevayler createCheckpointPrevayler(Serializable JavaDoc newPrevalentSystem, String JavaDoc snapshotDirectory) {
102         PrevaylerFactory factory = new PrevaylerFactory();
103         factory.configurePrevalentSystem(newPrevalentSystem);
104         factory.configurePrevalenceBase(snapshotDirectory);
105         factory.configureTransientMode(true);
106         try {
107             return factory.create();
108         } catch (Exception JavaDoc e) {
109             e.printStackTrace(); //Transient Prevayler creation should not fail.
110
return null;
111         }
112     }
113
114
115     private Clock clock() {
116         return _clock != null ? _clock : new MachineClock();
117     }
118
119
120     /** Determines whether the Prevayler created by this factory should be transient (transientMode = true) or persistent (transientMode = false). A transient Prevayler will execute its Transactions WITHOUT writing them to disk. This is useful for stand-alone applications which have a "Save" button, for example, or for running automated tests MUCH faster than with a persistent Prevayler.
121      */

122     public void configureTransientMode(boolean transientMode) {
123         _transientMode = transientMode;
124     }
125
126
127     /** Configures the Clock that will be used by the created Prevayler. The Clock interface can be implemented by the application if it requires Prevayler to use a special time source other than the machine clock (default).
128      */

129     public void configureClock(Clock clock) {
130         _clock = clock;
131     }
132
133
134     /** Configures the directory where the created Prevayler will read and write its .transactionLog and .snapshot files. The default is a directory called "PrevalenceBase" under the current directory.
135      * @param prevalenceBase Will be ignored for the .snapshot files if a SnapshotManager is configured.
136      */

137     public void configurePrevalenceBase(String JavaDoc prevalenceBase) {
138         _prevalenceBase = prevalenceBase;
139     }
140
141
142     /** Configures the prevalent system that will be used by the Prevayler created by this factory.
143      * @param newPrevalentSystem Will be ignored if a SnapshotManager is configured too because a SnapshotManager already has a prevalent system. If the default SnapshotManager is used, this prevalentSystem must be Serializable. If another SnapshotManager is used, this prevalentSystem must be compatible with it.
144      * @see #configureSnapshotManager(SnapshotManager)
145      */

146     public void configurePrevalentSystem(Object JavaDoc newPrevalentSystem) {
147         _prevalentSystem = newPrevalentSystem;
148     }
149
150
151     /** Reserved for future implementation.
152      */

153     public void configureReplicationClient(String JavaDoc remoteServerIpAddress, int remoteServerPort) {
154         _remoteServerIpAddress = remoteServerIpAddress;
155         _remoteServerPort = remoteServerPort;
156     }
157
158
159     /** Reserved for future implementation.
160      */

161     public void configureReplicationServer(int port) {
162         _serverPort = port;
163     }
164
165
166     /** Configures the SnapshotManager to be used by the Prevayler created by this factory. The default is a SnapshotManager which uses plain Java serialization to create its .snapshot files. This SnapshotManager is also used to create deep copies of the transactions, so they must be serializable by this SnapshotManager.
167      */

168     public void configureSnapshotManager(SnapshotManager snapshotManager) {
169         _snapshotManager = snapshotManager;
170     }
171
172
173     /** Determines whether the Prevayler created by this factory should filter out all Transactions that would throw a RuntimeException or Error if executed on the Prevalent System (default is true). This requires enough RAM to hold another copy of the prevalent system.
174      */

175     public void configureTransactionFiltering(boolean transactionFiltering) {
176         _transactionFiltering = transactionFiltering;
177     }
178
179
180     /** Returns a Prevayler created according to what was defined by calls to the configuration methods above.
181      * @throws IOException If there is trouble creating the Prevalence Base directory or reading a .transactionLog or .snapshot file.
182      * @throws ClassNotFoundException If a class of a serialized Object is not found when reading a .transactionLog or .snapshot file.
183      */

184     public Prevayler create() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
185         SnapshotManager snapshotManager = snapshotManager();
186         TransactionPublisher publisher = publisher(snapshotManager);
187         if (_serverPort != -1) new ServerListener(publisher, _serverPort);
188         return new PrevaylerImpl(snapshotManager, publisher);
189     }
190
191
192     private String JavaDoc prevalenceBase() {
193         return _prevalenceBase != null ? _prevalenceBase : "PrevalenceBase";
194     }
195
196
197     private Object JavaDoc prevalentSystem() {
198         if (_prevalentSystem == null) throw new IllegalStateException JavaDoc("The prevalent system must be configured.");
199         return _prevalentSystem;
200     }
201
202
203     private TransactionPublisher publisher(SnapshotManager snapshotManager) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
204         if (_remoteServerIpAddress != null) return new ClientPublisher(_remoteServerIpAddress, _remoteServerPort);
205         return new CentralPublisher(clock(), censor(snapshotManager), logger());
206     }
207
208
209     private TransactionCensor censor(SnapshotManager snapshotManager) {
210         return _transactionFiltering
211             ? (TransactionCensor) new StrictTransactionCensor(snapshotManager)
212             : new LiberalTransactionCensor();
213     }
214
215
216     private TransactionLogger logger() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
217         return _transientMode
218             ? (TransactionLogger)new TransientLogger()
219             : new PersistentLogger(prevalenceBase(), _transactionLogSizeThreshold, _transactionLogAgeThreshold);
220     }
221
222
223     private SnapshotManager snapshotManager() throws ClassNotFoundException JavaDoc, IOException JavaDoc {
224         return _snapshotManager != null
225             ? _snapshotManager
226             : new SnapshotManager(prevalentSystem(), prevalenceBase());
227     }
228
229
230     public void configureTransactionLogFileSizeThreshold(long sizeInBytes) {
231         _transactionLogSizeThreshold = sizeInBytes;
232     }
233
234     
235     public void configureTransactionLogFileAgeThreshold(long ageInMilliseconds) {
236         _transactionLogAgeThreshold = ageInMilliseconds;
237     }
238
239 }
240
Popular Tags