package org.prevayler.implementation.snapshot; import org.prevayler.foundation.serialization.JavaSerializer; import org.prevayler.foundation.serialization.Serializer; import org.prevayler.implementation.PrevalentSystemGuard; import org.prevayler.implementation.PrevaylerDirectory; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collections; import java.util.Iterator; import java.util.Map; public class GenericSnapshotManager { private Map _strategies; private String _primarySuffix; private PrevaylerDirectory _directory; private PrevalentSystemGuard _recoveredPrevalentSystem; public GenericSnapshotManager(Map snapshotSerializers, String primarySnapshotSuffix, Object newPrevalentSystem, PrevaylerDirectory directory, Serializer journalSerializer) throws IOException, ClassNotFoundException { for (Iterator iterator = snapshotSerializers.keySet().iterator(); iterator.hasNext();) { String suffix = (String) iterator.next(); PrevaylerDirectory.checkValidSnapshotSuffix(suffix); } if (!snapshotSerializers.containsKey(primarySnapshotSuffix)) { throw new IllegalArgumentException("Primary suffix '" + primarySnapshotSuffix + "' does not appear in strategies map"); } _strategies = snapshotSerializers; _primarySuffix = primarySnapshotSuffix; _directory = directory; _directory.produceDirectory(); File latestSnapshot = _directory.latestSnapshot(); long recoveredVersion = latestSnapshot == null ? 0 : PrevaylerDirectory.snapshotVersion(latestSnapshot); Object recoveredPrevalentSystem = latestSnapshot == null ? newPrevalentSystem : readSnapshot(latestSnapshot); _recoveredPrevalentSystem = new PrevalentSystemGuard(recoveredPrevalentSystem, recoveredVersion, journalSerializer); } GenericSnapshotManager(Object newPrevalentSystem) { _strategies = Collections.singletonMap("snapshot", new JavaSerializer()); _primarySuffix = "snapshot"; _directory = null; _recoveredPrevalentSystem = new PrevalentSystemGuard(newPrevalentSystem, 0, new JavaSerializer()); } public Serializer primarySerializer() { return (Serializer) _strategies.get(_primarySuffix); } public PrevalentSystemGuard recoveredPrevalentSystem() { return _recoveredPrevalentSystem; } public void writeSnapshot(Object prevalentSystem, long version) throws IOException { File tempFile = _directory.createTempFile("snapshot" + version + "temp", "generatingSnapshot"); writeSnapshot(prevalentSystem, tempFile); File permanent = snapshotFile(version); permanent.delete(); if (!tempFile.renameTo(permanent)) throw new IOException( "Temporary snapshot file generated: " + tempFile + "\nUnable to rename it permanently to: " + permanent); } private void writeSnapshot(Object prevalentSystem, File snapshotFile) throws IOException { OutputStream out = new FileOutputStream(snapshotFile); try { primarySerializer().writeObject(out, prevalentSystem); } finally { out.close(); } } private File snapshotFile(long version) { return _directory.snapshotFile(version, _primarySuffix); } private Object readSnapshot(File snapshotFile) throws ClassNotFoundException, IOException { String suffix = snapshotFile.getName().substring(snapshotFile.getName().indexOf('.') + 1); if (!_strategies.containsKey(suffix)) throw new IOException( snapshotFile.toString() + " cannot be read; only " + _strategies.keySet().toString() + " supported"); Serializer serializer = (Serializer) _strategies.get(suffix); FileInputStream in = new FileInputStream(snapshotFile); try { return serializer.readObject(in); } finally { in.close(); } } }