package diskCacheV111.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* This class contains various utility methods for serialising and
* deserialising objects. It is intended to facilitate unit-testing of
* objects that implement the Serializable interface: if we want to check
* that we can deserialise objects and catch if we break serialisable
* compatibility.
*/
public class SerializableUtils {
private static final int STRING_LINE_LENGTH = 61;
public static void assertSerialisationExpected( String message,
String encodedExpected,
Object object)
throws IOException {
String encodedResult =
SerializableUtils.serialiseAndEncodeObject( object);
assertEquals( message, encodedExpected, encodedResult);
}
public static void assertDeserialisationExpected(
String message,
Object expectedObject,
String encodedSerialisedObject)
throws ClassNotFoundException, IOException {
byte[] serialisedData =
SerializableUtils.decode( encodedSerialisedObject);
ByteArrayInputStream byteStream =
new ByteArrayInputStream( serialisedData);
ObjectInput objectInput = new ObjectInputStream( byteStream);
Object deserialisedObject = objectInput.readObject();
assertEquals( message, expectedObject, deserialisedObject);
}
public static String serialiseAndEncodeObject( Object object)
throws IOException {
ByteArrayOutputStream storage = new ByteArrayOutputStream();
ObjectOutput objectOutput = new ObjectOutputStream( storage);
objectOutput.writeObject( object);
objectOutput.close();
return SerializableUtils.encode( storage.toByteArray());
}
// Based on code from http://...
public static String encode( byte[] byteStream) {
StringBuilder result = new StringBuilder();
for( byte curr : byteStream) {
result.append(Integer.toString((curr & 0xff) + 0x100, 16)
.substring(1));
}
return result.toString();
}
// Taken from
// http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
public static byte[] decode( final String encoded) {
if( (encoded.length() % 2) != 0) {
throw new IllegalArgumentException(
"Input string must contain an even number of characters");
}
final byte result[] = new byte[encoded.length() / 2];
final char enc[] = encoded.toCharArray();
for( int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder( 2);
curr.append( enc[i]).append( enc[i + 1]);
result[i / 2] = (byte) Integer.parseInt( curr.toString(), 16);
}
return result;
}
public static void emitJavaStringDeclaration( String name, String data) {
List<String> lines = breakStringIntoLines( data);
String declaration = buildJavaStringDeclaration( name, lines);
System.out.println( declaration);
}
public static String buildJavaStringDeclaration( String name,
List<String> lines) {
StringBuilder sb = new StringBuilder();
sb.append(" private static final String ").append(name)
.append(" =\n");
boolean isFirstLine = true;
for( String line : lines) {
if( isFirstLine) {
sb.append(" ");
} else {
sb.append("\n + ");
}
sb.append("\"").append(line).append("\"");
isFirstLine = false;
}
sb.append( ";\n");
return sb.toString();
}
public static List<String> breakStringIntoLines( String data) {
List<String> lines = new ArrayList<>();
String remaining;
for( String current = data; current.length() > 0; current = remaining) {
int thisLineLength =
current.length() < STRING_LINE_LENGTH ? current.length()
: STRING_LINE_LENGTH;
String thisLine = current.substring( 0, thisLineLength);
remaining = current.substring( thisLineLength, current.length());
lines.add( thisLine);
}
return lines;
}
}