/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2003
* Sleepycat Software. All rights reserved.
*
* $Id: SerialFormat.java,v 1.10 2003/10/18 19:54:24 mhayes Exp $
*/
package com.sleepycat.bdb.bind.serial;
import com.sleepycat.bdb.bind.DataBuffer;
import com.sleepycat.bdb.bind.DataFormat;
import com.sleepycat.bdb.util.FastInputStream;
import com.sleepycat.bdb.util.FastOutputStream;
import com.sleepycat.bdb.util.IOExceptionWrapper;
import java.io.IOException;
/**
* The format for serialized data. In addition to identifying a serial format
* this class provides utility methods for use by bindings.
*
* @author Mark Hayes
*/
public class SerialFormat implements DataFormat {
private ClassCatalog classCatalog;
private Class baseClass;
/**
* Creates a serial format.
*
* @param classCatalog is the catalog to hold shared class information and
* for a database should be a {@link
* com.sleepycat.bdb.StoredClassCatalog}.
*
* @param baseClass is the base class for serialized objects stored using
* this format -- all objects using this format must be an instance of
* this class.
*/
public SerialFormat(ClassCatalog classCatalog, Class baseClass) {
this.classCatalog = classCatalog;
this.baseClass = baseClass;
}
/**
* Returns the base class for this format.
*
* @return the base class for this format.
*/
public final Class getBaseClass() {
return baseClass;
}
/**
* Utility method for use by bindings to deserialize an object. May only
* be called for data that was serialized using {@link #objectToData},
* since the fixed serialization header is assumed to not be included in
* the input data. {@link SerialInput} is used to deserialize the object.
* If a deserialized object is cached in the buffer's data formation
* property, it is returned directly.
*
* @param data is the input serialized data.
*
* @return the output deserialized object.
*/
public final Object dataToObject(DataBuffer data)
throws IOException {
Object object = data.getDataFormation();
if (object != null) return object;
int length = data.getDataLength();
byte[] hdr = SerialOutput.getStreamHeader();
byte[] bufWithHeader = new byte[length + hdr.length];
System.arraycopy(hdr, 0, bufWithHeader, 0, hdr.length);
System.arraycopy(data.getDataBytes(), data.getDataOffset(),
bufWithHeader, hdr.length, length);
SerialInput jin = new SerialInput(
new FastInputStream(bufWithHeader, 0, bufWithHeader.length),
classCatalog);
try {
object = jin.readObject();
} catch (ClassNotFoundException e) {
throw new IOExceptionWrapper(e);
}
data.setDataFormation(object);
return object;
}
/**
* Utility method for use by bindings to serialize an object. The fixed
* serialization header is not included in the output data to save space,
* and therefore to deserialize the data the complementary {@link
* #dataToObject} method must be used. {@link SerialOutput} is used to
* serialize the object. The deserialized object is cached in the buffer's
* data formation property.
*
* @param object is the input deserialized object.
*
* @param data is the output serialized data.
*
* @throws IllegalArgumentException if the object is not an instance of the
* base class for this format.
*/
public final void objectToData(Object object, DataBuffer data)
throws IOException {
if (baseClass != null && !baseClass.isInstance(object)) {
throw new IllegalArgumentException(
"Data object class (" + object.getClass() +
") not an instance of format's base class (" +
baseClass + ')');
}
FastOutputStream fo = new FastOutputStream();
SerialOutput jos = new SerialOutput(fo, classCatalog);
jos.writeObject(object);
byte[] hdr = SerialOutput.getStreamHeader();
data.setData(fo.getBufferBytes(), hdr.length,
fo.getBufferLength() - hdr.length);
data.setDataFormation(object);
}
}