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(); } } }