OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

sdo message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: Possible Direction: SDO-156 - java.io.Serialization should alsobe able to handle non-closed DataGraph (WIP)


Hello All,

Below is an approach I am considering for SDO-156 - 
java.io.Serialization should also be able to handle non-closed DataGraph.

Introduce a new type called Serializable in the TypeHelper.SDO_JAVA_URI 
namespace.  This type would have two properties:  "value" to hold the 
data object being serialized, and "orphans" to hold the orphan data 
objects.  Then when a DataObject is serialized it is wrapped in the 
Serializable DO, and the Serializable DO is serialized.  In this way we 
are ensured that the root DataObject (an instance of Serializable) will 
always have an orphan holder property.

Attached is an untested version of what the new Resolvable class might 
look like.

-Blaise
/*
 * Copyright(C) OASIS(R) 2005,2009. All Rights Reserved.
 * OASIS trademark, IPR and other policies apply.
 */

package commonj.sdo.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.SDO;
import commonj.sdo.helper.TypeHelper;

/**
 * An implementation of DataObject returns an ExternalizableDelegator from its
 * writeReplace() method.
 *
 * The root DataObject is the object returned from do.getRootObject() where
 * do is the DataObject being serialized in a java.io.ObjectOutputStream.
 * When do.getContainer() == null then do is a root object.
 *
 * The byte format for each DataObject in the stream is:
 * [0] [path] [root]   // when do is not a root object
 * [1] [identifier] [rootXML]       // when do is a root object
 *
 * where:
 * [0] is the byte 0, serialized using writeByte(0).
 * [1] is the byte 1, serialized using writeByte(1).
 *
 * [path] is an SDO path expression from the root DataObject to the serialized
 *        DataObject such that root.getDataObject(path) == do.
 *        Serialized using writeUTF(path).
 *
 * [root] is the root object serialized using writeObject(root).
 *
 * [identifier] is the HelperContext identifier serialized using writeUTF(identifier)
 *
 * [rootXML] is the GZip of the XML serialization of the root DataObject wrapped by a Serializable DataObject.
 *           The XML serialization is the same as
 *           HelperContext helperContext = root.getType().getHelperContext();
 *           DataObject serializableDO = helperContext.getDataFactory().create(TypeHelper.SDO_JAVA_URI, "Serializable");
 *           serializableDO.setDataObject("value", dataObject);
 *           root.getType().getHelperContext().getXMLHelper().save(serializableDO, TypeHelper.SDO_URI, "dataObject", stream);
 *           where stream is a GZIPOutputStream, length is the number of bytes
 *           in the stream, and bytes are the contents of the stream.
 *           Serialized using writeInt(length), write(bytes).
 * @since SDO 3.0
 */
public class Resolvable implements Externalizable, ExternalizableDelegator.Resolvable {

    private DataObject dataObject;

    public Resolvable() {
    }

    public Resolvable(DataObject dataObject) {
        this.dataObject = dataObject;
    }

    public Object readResolve() throws ObjectStreamException {
        return dataObject;
    }

    public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
        if(objectInput.read() == 1) { // [1] [identifier] [rootXML]
            HelperContext helperContext = SDO.getHelperContext(objectInput.readUTF());
            byte[] bytes = new byte[objectInput.readInt()];
            objectInput.readFully(bytes);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
            dataObject = helperContext.getXMLHelper().load(gzipInputStream).getRootObject().getDataObject("value");
        } else { // [0] [path] [root]
            String path = objectInput.readUTF();
            DataObject rootObject = (DataObject) objectInput.readObject();
            dataObject = rootObject.getDataObject("value").getDataObject(path);
        }
    }

    public void writeExternal(ObjectOutput objectOutput) throws IOException {
        if (null == dataObject.getContainer()) { // [1] [identifier] [rootXML]
            HelperContext helperContext = dataObject.getType().getHelperContext();

            // [1] is the byte 1, serialized using writeByte(1).
            objectOutput.writeByte(1);

            // [identifier] is the HelperContext identifier serialized using writeUTF(identifier)
            String identifier = helperContext.getIdentifier();
            if(null == identifier) {
                identifier = "";
            }
            objectOutput.writeUTF(identifier);

            // [rootXML] is the GZip of the XML serialization of the root DataObject wrapped by a Serializable DataObject.
            //           The XML serialization is the same as
            //           HelperContext helperContext = root.getType().getHelperContext();
            //           DataObject serializableDO = helperContext.getDataFactory().create(TypeHelper.SDO_JAVA_URI, "Serializable");
            //           serializableDO.setDataObject("value", dataObject);
            //           root.getType().getHelperContext().getXMLHelper().save(serializableDO, TypeHelper.SDO_URI, "dataObject", stream);
            //           where stream is a GZIPOutputStream, length is the number of bytes
            //           in the stream, and bytes are the contents of the stream.
            //           Serialized using writeInt(length), write(bytes).
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);

            DataObject serializableDO = helperContext.getDataFactory().create(TypeHelper.SDO_JAVA_URI, "Serializable");
            serializableDO.setDataObject("value", dataObject);
            helperContext.getXMLHelper().save(serializableDO, TypeHelper.SDO_URI, "dataObject", gzipOutputStream);
            gzipOutputStream.finish();
            byte[] bytes = byteArrayOutputStream.toByteArray();
            objectOutput.writeInt(bytes.length);
            objectOutput.write(bytes);
            gzipOutputStream.close();
        } else { // [0] [path] [root]
            // [0] is the byte 0, serialized using writeByte(0).
            objectOutput.writeByte(0);

            // [path] is an SDO path expression from the root DataObject to the serialized
            //        DataObject such that root.getDataObject(path) == do.
            //        Serialized using writeUTF(path).
            objectOutput.writeUTF(getPath(dataObject).substring(1));

            // [root] is the root object serialized using writeObject(root).
            objectOutput.writeObject(dataObject.getRootObject());
        }
    }

    private String getPath(DataObject childDataObject) {
        if(null == childDataObject.getContainer()) {
            return "";
        } else {
            Property containmentProperty = childDataObject.getContainmentProperty();
            if(containmentProperty.isMany()) {
                int index = childDataObject.getContainer().getList(containmentProperty).indexOf(childDataObject) + 1;
                return getPath(childDataObject.getContainer()) + '/' + containmentProperty.getName() + '[' + index + ']';
            } else {
                return getPath(childDataObject.getContainer()) + '/' + containmentProperty.getName();
            }
        }
    }

}


[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]