Mercurial > hg > blitz_stable
diff src/org/dancres/blitz/mangler/MangledField.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/dancres/blitz/mangler/MangledField.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,147 @@ +package org.dancres.blitz.mangler; + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.dancres.io.AnnotatingObjectOutputStream; +import org.dancres.io.AnnotatingObjectInputStream; + +/** + Each field within an Entry is held in a MangledField. We require the + field's name for indexing purposes. We also use our own hashing + algorithm which is known not to "funnel" in the vast majority of cases. + */ +public class MangledField implements Serializable { + static final long serialVersionUID = -6256197142057463399L; + + private String theName; + private byte[] theObjectBytes; + private byte[] theAnnotationBytes; + private int theHashCode; + + MangledField(String aName) { + theName = aName; + theObjectBytes = new byte[0]; + theAnnotationBytes = new byte[0]; + theHashCode = 0; + } + + MangledField(String aName, Object anObject) + throws IOException { + theName = aName; + mangle(anObject); + } + + MangledField(String aName, byte[] anObject, byte[] aAnnotation, int aHash) { + theName = aName; + theObjectBytes = anObject; + theAnnotationBytes = aAnnotation; + theHashCode = aHash; + } + + public int sizeOf() { + if (isNull()) + return 0; + else + return theName.length() + theObjectBytes.length + + theAnnotationBytes.length + 4 + 4; + } + + public Object unMangle(ClassLoader aDefault, boolean checkIntegrity) + throws IOException, ClassNotFoundException { + + ByteArrayInputStream myObjStream = + new ByteArrayInputStream(theObjectBytes); + ByteArrayInputStream myAnnoStream = + new ByteArrayInputStream(theAnnotationBytes); + + AnnotatingObjectInputStream myStream = + new AnnotatingObjectInputStream(aDefault, myObjStream, + myAnnoStream, checkIntegrity); + + Object myResult = myStream.readObject(); + + myStream.close(); + + return myResult; + } + + public boolean isNull() { + // System.err.println("isNull: " + theName); + // System.err.println("OLength: " + theObjectBytes.length); + // System.err.println("ALength: " + theAnnotationBytes.length); + return (theObjectBytes.length == 0); + } + + private void mangle(Object anObject) throws IOException { + ByteArrayOutputStream myObjectBytes = new ByteArrayOutputStream(); + ByteArrayOutputStream myAnnotBytes = new ByteArrayOutputStream(); + + AnnotatingObjectOutputStream myStream = + new AnnotatingObjectOutputStream(myObjectBytes, myAnnotBytes); + + myStream.writeObject(anObject); + myStream.close(); + + theObjectBytes = myObjectBytes.toByteArray(); + theAnnotationBytes = myAnnotBytes.toByteArray(); + + theHashCode = buildHash(theObjectBytes); + } + + /** + This algorithm is based on the "One at a time" hash published in + Dr Dobbs Journal '97 and authored by Bob Jenkins. A copy of the + article can be found at + <a href="http://burtleburtle.net/bob/hash/doobs.html"> + Burtleburtle.net</a> + */ + private int buildHash(byte[] aBytes) { + int myHash = 0; + + for (int i = 0; i < aBytes.length; i++) { + myHash += aBytes[i]; + myHash += (myHash << 10); + myHash ^= (myHash >> 6); + } + + myHash += (myHash << 3); + myHash ^= (myHash >> 11); + myHash += (myHash << 15); + + return myHash; + } + + public boolean matches(MangledField aField) { + if (aField.theHashCode == theHashCode) { + if (aField.theObjectBytes.length == theObjectBytes.length) { + for (int i = 0; i < theObjectBytes.length; i++) { + if (aField.theObjectBytes[i] != theObjectBytes[i]) + return false; + } + + return true; + } + } + + return false; + } + + public String getName() { + return theName; + } + + byte[] getContent() { + return theObjectBytes; + } + + byte[] getAnnotations() { + return theAnnotationBytes; + } + + public int hashCode() { + return theHashCode; + } +}