All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.bind.serial.SerialBinding Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.bind.serial;

import java.io.IOException;

import com.sleepycat.bind.EntryBinding;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.util.FastInputStream;
import com.sleepycat.util.FastOutputStream;
import com.sleepycat.util.RuntimeExceptionWrapper;

/**
 * A concrete EntryBinding that treats a key or data entry as
 * a serialized object.
 *
 * 

This binding stores objects in serialized object format. The * deserialized objects are returned by the binding, and their * Class must implement the Serializable * interface.

* *

For key bindings, a tuple binding is usually a better choice than a * serial binding. A tuple binding gives a reasonable sort order, and works * with comparators in all cases -- see below.

* *

WARNING: SerialBinding should not be used with Berkeley DB Java * Edition for key bindings, when a custom comparator is used. In JE, * comparators are instantiated and called internally at times when databases * are not accessible. Because serial bindings depend on the class catalog * database, a serial binding cannot be used during these times. An attempt * to use a serial binding with a custom comparator will result in a * NullPointerException during environment open or close.

* *

Class Evolution

* *

{@code SerialBinding} and other classes in this package use standard Java * serialization and all rules of Java serialization apply. This includes the * rules for class evolution. Once an instance of a class is stored, the class * must maintain its {@code serialVersionUID} and follow the rules defined in * the Java specification. To use a new incompatible version of a class, a * different {@link ClassCatalog} must be used or the class catalog database * must be truncated.

* *

If more advanced class evolution features are required, consider using * the {@link com.sleepycat.persist.evolve Direct Persistence Layer}.

* * @author Mark Hayes */ public class SerialBinding extends SerialBase implements EntryBinding { private ClassCatalog classCatalog; private Class baseClass; /** * Creates a serial binding. * * @param classCatalog is the catalog to hold shared class information and * for a database should be a {@link StoredClassCatalog}. * * @param baseClass is the base class for serialized objects stored using * this binding -- all objects using this binding must be an instance of * this class. Note that if this parameter is non-null, then this binding * will not support serialization of null values. */ public SerialBinding(ClassCatalog classCatalog, Class baseClass) { if (classCatalog == null) { throw new NullPointerException("classCatalog must be non-null"); } this.classCatalog = classCatalog; this.baseClass = baseClass; } /** * Returns the base class for this binding. * * @return the base class for this binding. */ public final Class getBaseClass() { return baseClass; } /** * Returns the class loader to be used during deserialization, or null if a * default class loader should be used. The default implementation of this * method returns {@link ClassCatalog#getClassLoader()}, if it returns a * non-null value. If {@link ClassCatalog#getClassLoader()} returns null, * then Thread.currentThread().getContextClassLoader() is * returned. * *

This method may be overridden to return a dynamically determined * class loader. For example, getBaseClass().getClassLoader() * could be called to use the class loader for the base class, assuming * that a base class has been specified.

* *

If this method returns null, a default class loader will be used as * determined by the java.io.ObjectInputStream.resolveClass * method.

* * @return the ClassLoader or null. */ public ClassLoader getClassLoader() { final ClassLoader loader = classCatalog.getClassLoader(); if (loader != null) { return loader; } return Thread.currentThread().getContextClassLoader(); } /** * Deserialize an object from an entry buffer. May only be called for data * that was serialized using {@link #objectToEntry}, since the fixed * serialization header is assumed to not be included in the input data. * {@link SerialInput} is used to deserialize the object. * * @param entry is the input serialized entry. * * @return the output deserialized object. */ public E entryToObject(DatabaseEntry entry) { int length = entry.getSize(); byte[] hdr = SerialOutput.getStreamHeader(); byte[] bufWithHeader = new byte[length + hdr.length]; System.arraycopy(hdr, 0, bufWithHeader, 0, hdr.length); System.arraycopy(entry.getData(), entry.getOffset(), bufWithHeader, hdr.length, length); try { SerialInput jin = new SerialInput( new FastInputStream(bufWithHeader, 0, bufWithHeader.length), classCatalog, getClassLoader()); return (E) jin.readObject(); } catch (IOException e) { throw RuntimeExceptionWrapper.wrapIfNeeded(e); } catch (ClassNotFoundException e) { throw RuntimeExceptionWrapper.wrapIfNeeded(e); } } /** * Serialize an object into an entry buffer. The fixed serialization * header is not included in the output data to save space, and therefore * to deserialize the data the complementary {@link #entryToObject} method * must be used. {@link SerialOutput} is used to serialize the object. * *

Note that this method sets the DatabaseEntry offset property to a * non-zero value and the size property to a value less than the length of * the byte array.

* * @param object is the input deserialized object. * * @param entry is the output serialized entry. * * @throws IllegalArgumentException if the object is not an instance of the * base class for this binding, including if the object is null and a * non-null base class was specified. */ public void objectToEntry(E object, DatabaseEntry entry) { if (baseClass != null && !baseClass.isInstance(object)) { throw new IllegalArgumentException (((object != null) ? ("Data object class (" + object.getClass() + ')') : "Null value") + " is not an instance of binding's base class (" + baseClass + ')'); } FastOutputStream fo = getSerialOutput(object); try { SerialOutput jos = new SerialOutput(fo, classCatalog); jos.writeObject(object); } catch (IOException e) { throw RuntimeExceptionWrapper.wrapIfNeeded(e); } byte[] hdr = SerialOutput.getStreamHeader(); entry.setData(fo.getBufferBytes(), hdr.length, fo.getBufferLength() - hdr.length); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy