KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > prevayler > implementation > snapshot > SnapshotManager


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.implementation.snapshot;
6
7 import java.io.*;
8
9 import org.prevayler.foundation.*;
10
11
12 /** Writes and reads snapshots to/from files. You can extend this class to use a serialization mechanism other than Java's. E.g: XML.
13  */

14 public class SnapshotManager {
15
16     //only here to allow for subclases to call init method rather than super
17
//please don't use.
18
SnapshotManager() {}
19
20     SnapshotManager(Object JavaDoc newPrevalentSystem) {
21         nullInit(newPrevalentSystem);
22     }
23
24     // this is only here for NullSnapshotManager support
25
protected void nullInit(Object JavaDoc newPrevalentSystem) {
26         _recoveredPrevalentSystem = newPrevalentSystem;
27         _recoveredVersion = 0;
28         _directory = null;
29     }
30
31     private File _directory;
32     private Object JavaDoc _recoveredPrevalentSystem;
33     private long _recoveredVersion;
34
35
36     /**
37      * @param newPrevalentSystem The prevalentSystem to serialize/deserialize
38      * @param snapshotDirectoryName The path of the directory where the last snapshot file will be read and where the new snapshot files will be created.
39      */

40     public SnapshotManager(Object JavaDoc newPrevalentSystem, String JavaDoc snapshotDirectoryName) throws ClassNotFoundException JavaDoc, IOException {
41         init(newPrevalentSystem, snapshotDirectoryName);
42     }
43
44     /**
45      * @param newPrevalentSystem The prevalentSystem to serialize/deserialize
46      * @param snapshotDirectoryName The path of the directory where the last snapshot file will be read and where the new snapshot files will be created.
47      */

48     protected void init(Object JavaDoc newPrevalentSystem, String JavaDoc snapshotDirectoryName) throws ClassNotFoundException JavaDoc, IOException {
49         _directory = FileManager.produceDirectory(snapshotDirectoryName);
50         _recoveredVersion = latestVersion();
51         _recoveredPrevalentSystem = _recoveredVersion == 0
52             ? newPrevalentSystem
53             : readSnapshot(_recoveredVersion);
54     }
55
56     public Object JavaDoc recoveredPrevalentSystem() { return _recoveredPrevalentSystem; }
57
58
59     public long recoveredVersion() { return _recoveredVersion; }
60
61
62     public void writeSnapshot(Object JavaDoc prevalentSystem, long version) throws IOException {
63         File tempFile = File.createTempFile("snapshot" + version + "temp", "generatingSnapshot", _directory);
64
65         writeSnapshot(prevalentSystem, tempFile);
66
67         File permanent = snapshotFile(version);
68         permanent.delete();
69         if (!tempFile.renameTo(permanent)) throw new IOException("Temporary snapshot file generated: " + tempFile + "\nUnable to rename it permanently to: " + permanent);
70     }
71
72
73     private void writeSnapshot(Object JavaDoc prevalentSystem, File snapshotFile) throws IOException {
74         OutputStream out = new FileOutputStream(snapshotFile);
75         try {
76             writeSnapshot(prevalentSystem, out);
77         } finally {
78             out.close();
79         }
80     }
81
82
83     /** Serializes prevalentSystem and writes it to snapshotFile. You can overload this method to use a serialization mechanism other than Java's. E.g: XML.
84     */

85     public void writeSnapshot(Object JavaDoc prevalentSystem, OutputStream out) throws IOException {
86         ObjectOutputStream stream = new ObjectOutputStream(out);
87         stream.writeObject(prevalentSystem);
88     }
89
90
91     /** Returns "snapshot", the default suffix/extension for snapshot files. You can overload this method and return a different suffix if you want. E.g: "XmlSnapshot"
92     */

93     protected String JavaDoc suffix() {
94         return "snapshot";
95     }
96
97
98     /** Returns zero if no snapshot file was found.
99     */

100     private long latestVersion() throws IOException {
101         String JavaDoc[] fileNames = _directory.list();
102         if (fileNames == null) throw new IOException("Error reading file list from directory " + _directory);
103
104         long result = 0;
105         for (int i = 0; i < fileNames.length; i++) {
106             long candidate = version(fileNames[i]);
107             if (candidate > result) result = candidate;
108         }
109         return result;
110     }
111
112
113     private Object JavaDoc readSnapshot(long version) throws ClassNotFoundException JavaDoc, IOException {
114         File snapshotFile = snapshotFile(version);
115         return readSnapshot(snapshotFile);
116     }
117
118
119     private Object JavaDoc readSnapshot(File snapshotFile) throws ClassNotFoundException JavaDoc, IOException {
120         FileInputStream in = new FileInputStream(snapshotFile);
121         try {
122             return readSnapshot(in);
123         } finally { in.close(); }
124     }
125
126
127     /** Deserializes and returns the object contained in snapshotFile. You can overload this method to use a deserialization mechanism other than Java's. E.g: XML.
128     */

129     public Object JavaDoc readSnapshot(InputStream in) throws IOException, ClassNotFoundException JavaDoc {
130         ObjectInputStream ois = new ObjectInputStream(in);
131         return ois.readObject();
132     }
133
134
135     private File snapshotFile(long version) {
136         String JavaDoc fileName = "0000000000000000000" + version;
137         return new File(_directory, fileName.substring(fileName.length() - 19) + "." + suffix());
138     }
139
140
141     /** Returns -1 if fileName is not the name of a snapshot file.
142     */

143     private long version(String JavaDoc fileName) {
144         if (!fileName.endsWith("." + suffix())) return -1;
145         return Long.parseLong(fileName.substring(0, fileName.indexOf("." + suffix()))); // "00000.snapshot" becomes "00000".
146
}
147
148
149     public Object JavaDoc deepCopy(Object JavaDoc original, String JavaDoc errorMessage) {
150         try {
151             ByteArrayOutputStream out = new ByteArrayOutputStream();
152             writeSnapshot(original, out);
153             return readSnapshot(new ByteArrayInputStream(out.toByteArray()));
154         } catch (Exception JavaDoc ex) {
155             ex.printStackTrace();
156             throw new RuntimeException JavaDoc(errorMessage);
157         }
158     }
159
160 }
161
Popular Tags