package zendo.playground.various.transactional;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
/**
* Provides transactional support for code blocks.
*
* @author bogdan.mocanu
*/
public class Transactional {
private Map<String, Object> mappedObjects = new HashMap<String, Object>();
private Map<String, byte[]> serializedObjects = new HashMap<String, byte[]>();
private boolean rollback = false;
public void put( String name, Object object ) {
mappedObjects.put( name, object );
serializedObjects.put( name, serializeObject( object ) );
}
@SuppressWarnings( "unchecked" )
public <T extends Object> T get( String name ) {
return (T) mappedObjects.get( name );
}
public void rollback() {
rollback = true;
}
// --------------------------------------------------------------------------
public void execute( Execution exec ) {
try {
exec.transactionalParent = this;
exec.execute();
} catch ( Exception exception ) {
exception.printStackTrace();
rollback = true;
}
if ( rollback ) {
rollbackData();
}
}
private byte[] serializeObject( Object object ) {
ObjectOutputStream oos = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream( baos );
oos.writeObject( object );
return baos.toByteArray();
} catch ( Exception exception ) {
exception.printStackTrace();
return null;
} finally {
IOUtils.closeQuietly( oos );
}
}
private Object unserializeObject( byte[] content ) {
ObjectInputStream ois = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream( content );
ois = new ObjectInputStream( bais );
Object result = ois.readObject();
return result;
} catch ( Exception exception ) {
exception.printStackTrace();
return null;
} finally {
IOUtils.closeQuietly( ois );
}
}
private void rollbackData() {
Map<String, Object> originalMappedObjects = new HashMap<String, Object>();
for ( Entry<String, Object> mappedEntry : mappedObjects.entrySet() ) {
String key = mappedEntry.getKey();
Object originalObject = unserializeObject( serializedObjects.get( key ) );
originalMappedObjects.put( key, originalObject );
}
mappedObjects = originalMappedObjects;
}
// --------------------------------------------------------------------------
protected static abstract class Execution {
private Transactional transactionalParent;
protected abstract void execute() throws Exception;
protected <T> T get( String name ) {
return (T)transactionalParent.get( name );
}
protected void rollback() {
transactionalParent.rollback();
}
}
}