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