com.alachisoft.ncache.serialization.standard.io.ObjectOutputStream Maven / Gradle / Ivy
Show all versions of nc-serialization Show documentation
/*
* @(#)ObjectOutputStream.java 1.0
*
* Created on September 18, 2008, 12:59 PM
*
* Copyright 2008 NeXtreme Innovations, Inc. All rights reserved.
* "NeXtreme Innovations" PROPRIETARY/CONFIDENTIAL. Use is subject
* to license terms.
*/
package com.alachisoft.ncache.serialization.standard.io;
import com.alachisoft.ncache.serialization.core.io.BlockDataOutputStream;
import com.alachisoft.ncache.serialization.core.io.NCacheObjectOutput;
import com.alachisoft.ncache.serialization.core.io.SerializationContext;
import com.alachisoft.ncache.serialization.core.io.TypeSurrogateSelector;
import com.alachisoft.ncache.serialization.core.io.surrogates.NCacheIOException;
import com.alachisoft.ncache.serialization.core.io.surrogates.SerializationSurrogate;
import com.alachisoft.ncache.serialization.standard.io.surrogates.ObjectSerializationSurrogate;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
/**
* ObjectOutputStream class.
*
* @version 1.0, September 18, 2008
*/
public class ObjectOutputStream
extends OutputStream implements NCacheObjectOutput {
/**
* working arrays initialized on demand by readUTF
*/
private BlockDataOutputStream mOutput;
private SerializationContext mContext;
private TypeSurrogateSelector mSelector;
private String _cacheContext;
/**
* Creates an ObjectOutputStream that writes to the specified OutputStream.
* This constructor writes the serialization stream header to the
* underlying stream; callers may wish to flush the stream immediately to
* ensure that constructors for receiving ObjectInputStreams will not block
* when reading the header.
*
* If a security manager is installed, this constructor will check for
* the "enableSubclassImplementation" SerializablePermission when invoked
* directly or indirectly by the constructor of a subclass which overrides
* the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
* methods.
*
* @param out output stream to write to
* @throws IOException if an I/O error occurs while writing stream header
* @throws SecurityException if untrusted subclass illegally overrides
* security-sensitive methods
* @throws NullPointerException if out
is null
*/
public ObjectOutputStream(OutputStream out, String cacheContext) throws IOException {
this.mOutput = new BlockDataOutputStream(out);
this.mSelector = TypeSurrogateSelectorImpl.getDefault();
this.mContext = new SerializationContext(this.mSelector);
this.mContext.putUserItem("__bout", this.mOutput);
this._cacheContext = cacheContext;
}
/**
* Creates an ObjectOutputStream that writes to the specified OutputStream.
* This constructor writes the serialization stream header to the
* underlying stream; callers may wish to flush the stream immediately to
* ensure that constructors for receiving ObjectInputStreams will not block
* when reading the header.
*
*
If a security manager is installed, this constructor will check for
* the "enableSubclassImplementation" SerializablePermission when invoked
* directly or indirectly by the constructor of a subclass which overrides
* the ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared
* methods.
*
* @param out output stream to write to
* @param selector type surrogate selector to use
* @throws IOException if an I/O error occurs while writing stream header
* @throws SecurityException if untrusted subclass illegally overrides
* security-sensitive methods
* @throws NullPointerException if out
is null
*/
public ObjectOutputStream(OutputStream out, TypeSurrogateSelector selector) throws IOException {
this.mOutput = new BlockDataOutputStream(out);
this.mContext = new SerializationContext(selector);
this.mSelector = this.mContext.getSurrogateSelector();
this.mContext.putUserItem("__bout", this.mOutput);
}
/**
* Returns the current object.
*
* @return the current serialzation context
*/
public SerializationContext getContext() {
return this.mContext;
}
/**
* Returns the underlying InputStream object.
*/
public OutputStream getBaseStream() {
return this.mOutput;
}
/**
* Writes the specified byte (the low eight bits of the argument
* b
) to the underlying output stream. If no exception
* is thrown, the counter written
is incremented by
* 1
.
*
* Implements the write
method of OutputStream
.
*
* @param b the byte
to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public synchronized void write(int b) throws IOException {
this.mOutput.write(b);
}
/**
* Writes len
bytes from the specified byte array
* starting at offset off
to the underlying output stream.
* If no exception is thrown, the counter written
is
* incremented by len
.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
@Override
public synchronized void write(byte b[], int off, int len) throws IOException {
this.mOutput.write(b, off, len);
}
/**
* Flushes this data output stream. This forces any buffered output
* bytes to be written out to the stream.
*
* The flush
method of DataOutputStream
* calls the flush
method of its underlying output stream.
*
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
* @see java.io.OutputStream#flush()
*/
@Override
public void flush() throws IOException {
this.mOutput.flush();
}
/**
* Writes a boolean
to the underlying output stream as
* a 1-byte value. The value true
is written out as the
* value (byte)1
; the value false
is
* written out as the value (byte)0
. If no exception is
* thrown, the counter written
is incremented by
* 1
.
*
* @param v a boolean
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeBoolean(boolean v) throws IOException {
this.mOutput.writeBoolean(v);
}
/**
* Writes out a byte
to the underlying output stream as
* a 1-byte value. If no exception is thrown, the counter
* written
is incremented by 1
.
*
* @param v a byte
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeByte(int v) throws IOException {
this.mOutput.writeByte(v);
}
/**
* Writes a short
to the underlying output stream as two
* bytes, high byte first. If no exception is thrown, the counter
* written
is incremented by 2
.
*
* @param v a short
to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeShort(int v) throws IOException {
this.mOutput.writeShort(v);
}
/**
* Writes a char
to the underlying output stream as a
* 2-byte value, high byte first. If no exception is thrown, the
* counter written
is incremented by 2
.
*
* @param v a char
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeChar(int v) throws IOException {
this.mOutput.writeUTF8Char((char) v);
}
/**
* Writes an int
to the underlying output stream as four
* bytes, high byte first. If no exception is thrown, the counter
* written
is incremented by 4
.
*
* @param v an int
to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeInt(int v) throws IOException {
this.mOutput.writeInt(v);
}
/**
* Writes a long
to the underlying output stream as eight
* bytes, high byte first. In no exception is thrown, the counter
* written
is incremented by 8
.
*
* @param v a long
to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeLong(long v) throws IOException {
this.mOutput.writeLong(v);
}
/**
* Converts the float argument to an int
using the
* floatToIntBits
method in class Float
,
* and then writes that int
value to the underlying
* output stream as a 4-byte quantity, high byte first. If no
* exception is thrown, the counter written
is
* incremented by 4
.
*
* @param v a float
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
* @see java.lang.Float#floatToIntBits(float)
*/
public final void writeFloat(float v) throws IOException {
this.mOutput.writeFloat(v);
}
/**
* Converts the double argument to a long
using the
* doubleToLongBits
method in class Double
,
* and then writes that long
value to the underlying
* output stream as an 8-byte quantity, high byte first. If no
* exception is thrown, the counter written
is
* incremented by 8
.
*
* @param v a double
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
* @see java.lang.Double#doubleToLongBits(double)
*/
public final void writeDouble(double v) throws IOException {
this.mOutput.writeDouble(v);
}
/**
* Writes out the string to the underlying output stream as a
* sequence of bytes. Each character in the string is written out, in
* sequence, by discarding its high eight bits. If no exception is
* thrown, the counter written
is incremented by the
* length of s
.
*
* @param s a string of bytes to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeBytes(String s) throws IOException {
this.mOutput.writeBytes(s);
}
/**
* Writes a string to the underlying output stream as a sequence of
* characters. Each character is written to the data output stream as
* if by the writeChar
method. If no exception is
* thrown, the counter written
is incremented by twice
* the length of s
.
*
* @param s a String
value to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.DataOutputStream#writeChar(int)
* @see java.io.FilterOutputStream#out
*/
public final void writeChars(String s) throws IOException {
this.mOutput.writeChars(s);
}
/**
* Writes a string to the underlying output stream using
* modified UTF-8
* encoding in a machine-independent manner.
*
* First, two bytes are written to the output stream as if by the
* writeShort
method giving the number of bytes to
* follow. This value is the number of bytes actually written out,
* not the length of the string. Following the length, each character
* of the string is output, in sequence, using the modified UTF-8 encoding
* for the character. If no exception is thrown, the counter
* written
is incremented by the total number of
* bytes written to the output stream. This will be at least two
* plus the length of str
, and at most two plus
* thrice the length of str
.
*
* @param str a string to be written.
* @throws IOException if an I/O error occurs.
*/
public final void writeUTF(String str) throws IOException {
this.mOutput.writeUTF(str);
}
/**
* Writes a 'UInt16' vale portable with 'ushort' for .Net to the underlying output stream as four
* bytes. If no exception is thrown, the counter
* written
is incremented by 4
.
*
* @param i value to write
* @throws IOException either when EOF is reached or value is out of Range of 'ushort'
*/
public final void writeUInt16(int i) throws IOException {
if (i > 65535)
throw new IOException("Unable to serialize: Provided integer value [" + Integer.toString(i) + "] is greater than 65,535 and is out of Range of 'UInt16'");
else if (i < 0) {
throw new IOException("Unable to serialize: Provided integer value [" + Integer.toString(i) + "] is less than '0' and is out of Range of 'UInt16'");
}
this.mOutput.writeUInt16(i);
}
/**
* Writes a 'UInt32' vale portable with 'uInt' for .Net to the underlying output stream as four
* bytes. If no exception is thrown, the counter is incremented with 4 bytes
*
* @param i value to be written
* @throws IOException either when EOF is reached or value is out of Range of 'uInt'
*/
public final void writeUInt32(long i) throws IOException {
if (i > 4294967295L) {
throw new IOException("Unable to serialize: Provided long value [" + Long.toString(i) + "] is greater than 4,29,49,67,295 and is out of Range of 'UInt32'");
} else if (i < 0) {
throw new IOException("Unable to serialize: Provided long value [" + Long.toString(i) + "] is less than '0' and is out of Range of 'UInt32'");
}
this.mOutput.writeUInt32(i);
}
/**
* Writes a 'UInt64' vale portable with 'uLong' for .Net to the underlying output stream as four
* bytes. If no exception is thrown, the counter is incremented with 8 bytes
*
* @param bigInteger bigInteger value to write
* @throws IOException either when EOF is reached or value is out of Range of 'uLong'
*/
public final void writeUInt64(BigInteger bigInteger) throws IOException {
if (bigInteger == null)
throw new IOException("Unable to serialize: Provided BigInteger value is null which is incompatible with 'UInt64'");
if (bigInteger.compareTo(new BigInteger("18446744073709551615")) == 1) {
throw new IOException("Unable to serialize: Provided BigInteger value [" + bigInteger.toString() + "] is greater than 18,446,744,073,709,551,615 and is out of Range of 'UInt64'");
} else if (bigInteger.compareTo(new BigInteger("0")) == -1) {
throw new IOException("Unable to serialize: Provided BigInteger value [" + bigInteger.toString() + "] is less than 0 and is out of Range of 'UInt64'");
}
this.mOutput.writeUInt64(bigInteger);
}
/**
* Returns the current value of the counter written
,
* the number of bytes written to this data output stream so far.
* If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
*
* @return the value of the written
field.
* @see java.io.DataOutputStream#written
*/
public final int size() {
return this.mOutput.size();
}
/**
* Write the specified object to the ObjectOutputStream. Objects referenced by this
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*
*
Exceptions are thrown for problems with the OutputStream and for
* classes that should not be serialized. All exceptions are fatal to the
* OutputStream, which is left in an indeterminate state, and it is up to
* the caller to ignore or recover the stream state.
*
* @throws IOException Any exception thrown by the underlying
* OutputStream.
*/
public final void writeObject(Object obj)
throws IOException {
try {
// Find an appropriate surrogate for the object
SerializationSurrogate surrogate = this.mSelector.getSurrogateForObject(obj, _cacheContext);
// write type handle
Class[] type;
if (surrogate instanceof ObjectSerializationSurrogate) {
SerializationSurrogate testSurrogate = null;
testSurrogate = getType(surrogate, obj.getClass());
if (testSurrogate != null) {
surrogate = testSurrogate;
}
// type = obj.getClass().getInterfaces();
// for (int i = 0; i < type.length; i++)
// {
// Class class1 = type[i];
//
// surrogate = this.mSelector.getSurrogateForType(class1, true);
// if(surrogate != null)
// {
// break;
// }
// }
}
surrogate.writeHandle(this, obj);
if (surrogate.getSubHandle() > 0)
surrogate.writeSubHandle(this, obj);
surrogate.writeObject(this, obj);
} catch (NCacheIOException nCacheIOException) {
//nCacheIOException.printStackTrace();
this.writeObject(obj);
throw new IOException(nCacheIOException.toString() + " is not marked as serializable.");
} catch (Exception ex) {
//ex.printStackTrace();
throw new IOException(ex.toString());
}
}
SerializationSurrogate getType(SerializationSurrogate surrogate, Class type) {
Class[] typeClasses = type.getInterfaces();
for (int i = 0; i < typeClasses.length; i++) {
Class class1 = typeClasses[i];
surrogate = this.mSelector.getSurrogateForType(class1, true, _cacheContext);
if (surrogate != null) {
return surrogate;
} else {
surrogate = getType(surrogate, class1);
if (surrogate != null) {
return surrogate;
}
}
}
return null;
}
/**
* Write the specified object to the ObjectOutputStream. Objects referenced by this
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*
*
Exceptions are thrown for problems with the OutputStream and for
* classes that should not be serialized. All exceptions are fatal to the
* OutputStream, which is left in an indeterminate state, and it is up to
* the caller to ignore or recover the stream state.
*
* @param obj the object to be written
* @param objClass the class surrogate to use for writing the object.
* @throws IOException Any of the usual Input/Output related exceptions.
* @throws IOException Any exception thrown by the underlying
* OutputStream.
*/
public void writeObject(Object obj, Class objClass)
throws IOException {
if (obj == null) {
throw new NullPointerException("obj");
}
if (objClass == null) {
throw new NullPointerException("objClass");
}
try {
SerializationSurrogate surrogate = this.mSelector.getSurrogateForType(objClass, _cacheContext);
surrogate.writeObject(this, obj);
} catch (Exception ex) {
throw new IOException(ex.toString());
}
}
public void writeObject(Object obj, Object objClass) throws IOException {
this.writeObject(obj, objClass.getClass());
}
//
public void write(boolean v, String type) throws IOException {
writeBoolean(v);
}
public void write(int v, String type) throws IOException {
writeInt(v);
}
public void write(String v, String type) throws IOException {
writeUTF(v);
}
public String getCacheContext() {
return this._cacheContext;
}
//
public void writeUByte(short sh) throws IOException {
if (sh > 255) {
throw new IOException("Unable to serialize: Provided short value [" + Short.toString(sh) + "] is greater than 255 and is out of Range of 'UnsignedByte'");
} else if (sh < 0) {
throw new IOException("Unable to serialize: Provided integer value [" + Short.toString(sh) + "] is less than '0' and is out of Range of 'UnsignedByte'");
}
this.mOutput.writeUByte(sh);
}
}