Initial commit from SVN.
This commit is contained in:
929
Common/src/com/common/io/AbstractObjectInputStream.java
Normal file
929
Common/src/com/common/io/AbstractObjectInputStream.java
Normal file
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Externalizable;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import com.common.orb.Orb;
|
||||
import com.common.util.*;
|
||||
import com.common.debug.*;
|
||||
import com.common.exception.*;
|
||||
|
||||
/**
|
||||
* Defines a basic object input stream which can be subclassed as needed.
|
||||
*/
|
||||
public abstract class AbstractObjectInputStream extends AbstractStandardInputStream implements IObjectStream, java.io.ObjectInput, IObjectInputStream {
|
||||
/** A factory that will produce an instance of the given class. If provided, this will be used instead of calling Class.newInstance(). */
|
||||
private IInstanceFactory instanceFactory = null;
|
||||
/** The class tracker is notified every time a class is referenced by the stream. It allows the application to track what classes are utilized by the streams. */
|
||||
private IClassTracker classTracker = null;
|
||||
/** The list of classes that were serialized indexed by the number the stream will use to reference them in the future. */
|
||||
private IList classList = null;
|
||||
/** The optional class loader which is used if provided to lookup the class names. */
|
||||
private ClassLoader loader = null;
|
||||
/** The collection of objects deserialized in order of deserialization. Used to reference previously deserialized values by number in the stream to prevent recursive references from bloating the stream. */
|
||||
private IList deserializedValues = null;
|
||||
/** Called prior to looking up the deserialized class name - allows replacement of the class name. */
|
||||
private IClassReplacementHandler classReplacementHandler = null;
|
||||
/** Allows the input stream to replace one class with another <b>if the original class cannot be found</b>. */
|
||||
private IStreamManager streamManager = null;
|
||||
|
||||
/**
|
||||
* Provides customized deserialization of streamed application objects.
|
||||
* <p><b>WARNING: Circular reference to this serialized object may not occur within its deserialization.</b>
|
||||
* <p>The deserialize method will receive the object's class object and the stream reference. It should determine whether it can deserialize that type and either pass the request to the encapsulated handler, or return null indicating that the default action should occur within the stream.</p>
|
||||
* <p>The encapsulated handler allows the handlers to be chained together such that the stream calls the first handler in the chain and it will call the next handler until a handler deserializes the object, or all handlers return null.</p>
|
||||
* <p>TODO: Allow for circular references in the deserialized object.
|
||||
*/
|
||||
public static class CustomDeserializationHandler {
|
||||
private CustomDeserializationHandler encapsulatedHandler = null;
|
||||
|
||||
public CustomDeserializationHandler() {
|
||||
}//CustomDeserializationHandler()//
|
||||
public CustomDeserializationHandler(CustomDeserializationHandler encapsulatedHandler) {
|
||||
this.encapsulatedHandler = encapsulatedHandler;
|
||||
}//CustomDeserializationHandler()//
|
||||
/**
|
||||
* Gets the encapsulated handler providing deserialization services.
|
||||
* @return The handler that will be called if this handler cannot deserialize the object.
|
||||
*/
|
||||
public CustomDeserializationHandler getEncapsulatedHandler() {
|
||||
return encapsulatedHandler;
|
||||
}//getEncapsulatedHandler()//
|
||||
/**
|
||||
* Sets the encapsulated handler providing deserialization services.
|
||||
* @param encapsulatedHandler The handler that will be called if this handler cannot deserialize the object.
|
||||
*/
|
||||
public void setEncapsulatedHandler(CustomDeserializationHandler encapsulatedHandler) {
|
||||
this.encapsulatedHandler = encapsulatedHandler;
|
||||
}//setEncapsulatedHandler()//
|
||||
/**
|
||||
* Receives the object's class object and the stream reference and determines whether it can deserialize that type, either passing the request to the encapsulated handler, or returning null indicating that the default action should occur within the stream.
|
||||
* <p><b>WARNING: Circular reference to this serialized object may not occur within its deserialization.</b>
|
||||
* @param type The class for the object needing deserialization.
|
||||
* @param in The input stream containing the serialized object's bytes.
|
||||
* @return The object deserialized or null indicating that the stream should deserialize the object using the default deserialization algorithms.
|
||||
*/
|
||||
public Object deserialize(Class type, AbstractObjectInputStream in) {
|
||||
return encapsulatedHandler == null ? null : encapsulatedHandler.deserialize(type, in);
|
||||
}//deserialize()//
|
||||
}//CustomDeserializationHandler//
|
||||
/**
|
||||
* Adds a custom serialization handler to the mapping for use by the object input and output streams.
|
||||
* @param type The class the handler will be used to serialize and deserialize.
|
||||
* @param handler The handler used to serialize and deserialize instances of the given class.
|
||||
*/
|
||||
public static final void addCustomSerializationHandler(Class type, ISerializationHandler handler) {
|
||||
ObjectStream.serializationHandlersMap.put(type, handler);
|
||||
}//addCustomSerializationHandler()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IList classList) throws IOException {
|
||||
this(loader, null, classList, null, null, null);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IList classList, IInstanceFactory instanceFactory) throws IOException {
|
||||
this(loader, null, classList, instanceFactory, null, null);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker) throws IOException {
|
||||
this(loader, classReplacementHandler, classList, instanceFactory, classTracker, null);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
* @param deserializedValues The previously deserialized values.
|
||||
*/
|
||||
protected AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, IList deserializedValues) throws IOException {
|
||||
super();
|
||||
|
||||
this.classReplacementHandler = classReplacementHandler;
|
||||
this.classTracker = classTracker;
|
||||
this.loader = loader;
|
||||
this.classList = classList;
|
||||
this.deserializedValues = deserializedValues == null ? new LiteList(30, 10) : deserializedValues;
|
||||
this.instanceFactory = instanceFactory;
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IList classList, int defaultNumberStyle) throws IOException {
|
||||
this(loader, null, classList, null, null, null, defaultNumberStyle);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IList classList, IInstanceFactory instanceFactory, int defaultNumberStyle) throws IOException {
|
||||
this(loader, null, classList, instanceFactory, null, null, defaultNumberStyle);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, int defaultNumberStyle) throws IOException {
|
||||
this(loader, classReplacementHandler, classList, instanceFactory, classTracker, null, defaultNumberStyle);
|
||||
}//AbstractObjectInputStream()//
|
||||
/**
|
||||
* AbstractObjectInputStream constructor.
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
* @param deserializedValues The previously deserialized values.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
protected AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, IList deserializedValues, int defaultNumberStyle) throws IOException {
|
||||
super(defaultNumberStyle);
|
||||
|
||||
this.classReplacementHandler = classReplacementHandler;
|
||||
this.classTracker = classTracker;
|
||||
this.loader = loader;
|
||||
this.classList = classList;
|
||||
this.deserializedValues = deserializedValues == null ? new LiteList(30, 10) : deserializedValues;
|
||||
this.instanceFactory = instanceFactory;
|
||||
}//AbstractObjectInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getInstanceFactory()
|
||||
*/
|
||||
public IInstanceFactory getInstanceFactory() {
|
||||
return instanceFactory;
|
||||
}//()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getClassTracker()
|
||||
*/
|
||||
public IClassTracker getClassTracker() {
|
||||
return classTracker;
|
||||
}//getClassTracker()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getClassList()
|
||||
*/
|
||||
public IList getClassList() {
|
||||
return classList;
|
||||
}//getClassList()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getLoader()
|
||||
*/
|
||||
public ClassLoader getLoader() {
|
||||
return loader;
|
||||
}//getLoader()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getDeserializedValues()
|
||||
*/
|
||||
public IList getDeserializedValues() {
|
||||
return deserializedValues;
|
||||
}//getDeserializedValues()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getClassReplacementHandler()
|
||||
*/
|
||||
public IClassReplacementHandler getClassReplacementHandler() {
|
||||
return classReplacementHandler;
|
||||
}//getClassReplacementHandler()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectInputStream#getStreamManager()
|
||||
*/
|
||||
public IStreamManager getStreamManager() {
|
||||
return streamManager;
|
||||
}//getStreamManager()//
|
||||
/**
|
||||
* Allocates memory for a new object of the given type.
|
||||
* <p>WARNING: At this time, proper initialization of the object may not occur.
|
||||
* @param type The class to create a new object for.
|
||||
* @return The new initialized object.
|
||||
*/
|
||||
private Object allocateNewObject(Class type) throws InstantiationException, IllegalAccessException {
|
||||
Object result = null;
|
||||
|
||||
if(type == null) {
|
||||
throw new InstantiationException("Received a null class reference in ObjectInputStream.allocateNewObject(Class).");
|
||||
}//if//
|
||||
|
||||
if(classTracker != null) {
|
||||
classTracker.add(type.getName());
|
||||
}//if//
|
||||
|
||||
//First try to use the instance factory.//
|
||||
if(instanceFactory != null) {
|
||||
result = instanceFactory.createInstance(type);
|
||||
}//if/
|
||||
|
||||
//Second try using a default constructor.//
|
||||
if(result == null) {
|
||||
try {
|
||||
result = type.newInstance();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignore.//
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
//Last try the native system call.//
|
||||
if(result == null) {
|
||||
//TODO: Should make sure that this fails gracefully if the library is not available.//
|
||||
result = com.common.system.SystemManager.instantiateObject(type);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//allocateNewObject()//
|
||||
/**
|
||||
* Closes this input stream. Will also close the wrappered stream.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if(deserializedValues != null) {
|
||||
deserializedValues.removeAll();
|
||||
deserializedValues = null;
|
||||
}//if//
|
||||
}//close()//
|
||||
/**
|
||||
* Deserailizes an object from this stream.
|
||||
* @return The object that was deserialized.
|
||||
*/
|
||||
protected Object deserialize(Class type) throws IOException, ClassNotFoundException {
|
||||
Object result = null;
|
||||
ISerializationHandler handler = null;
|
||||
|
||||
if((ObjectStream.serializationHandlersMap != null) && ((handler = (ISerializationHandler) ObjectStream.serializationHandlersMap.get(type)) != null)) {
|
||||
result = handler.deserialize(this);
|
||||
}//if//
|
||||
else if(Throwable.class.isAssignableFrom(type)) {
|
||||
//Allow the exceptions to be deserialized, although we will be unable to set the message of stack.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new IOException("Unable to deserialize the object of type: " + type.getName());
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//deserialize()//
|
||||
/**
|
||||
* Deserializes an object from this stream.
|
||||
* @param object The object to deserialize.
|
||||
* @return The deserialized object. May differ from the passed object.
|
||||
*/
|
||||
protected Object deserialize(Object object) throws ClassNotFoundException, IOException {
|
||||
//Note: The proxy class can't implement IExternalizable, but the proxied class can. To avoid trying to make a remote call to the IExternalizable readExternal method, we need to ensure this isn't a proxy.//
|
||||
if(object instanceof IExternalizable/* && !Orb.isProxy(object)*/) {
|
||||
Object result = ((IExternalizable) object).readExternal(this);
|
||||
|
||||
if(result != null) {
|
||||
if(result == IExternalizable.NULL_VALUE) {
|
||||
object = null;
|
||||
}//if//
|
||||
else {
|
||||
object = result;
|
||||
}//else//
|
||||
}//if//
|
||||
}//if//
|
||||
else if(object instanceof Externalizable) {
|
||||
((Externalizable) object).readExternal(this);
|
||||
}//else if//
|
||||
else if(object instanceof Throwable) {
|
||||
//Allow the exceptions to be deserialized, although we will be unable to set the message of stack.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new IOException("Unable to deserialize the object of type: " + object.getClass().getName());
|
||||
}//else//
|
||||
|
||||
return object;
|
||||
}//deserialize()//
|
||||
/**
|
||||
* Loads a class using what ever class loader has been specified.
|
||||
* @param className The name of the class to load.
|
||||
* @return The loaded class.
|
||||
*/
|
||||
private Class loadClass(String className) throws ClassNotFoundException {
|
||||
try {
|
||||
if(classReplacementHandler != null) {
|
||||
className = classReplacementHandler.getReplacementClassName(className);
|
||||
}//if//
|
||||
|
||||
return Class.forName(className, true, loader == null ? getClass().getClassLoader() : loader);
|
||||
}//try//
|
||||
catch(IncompatibleClassChangeError e) {
|
||||
Debug.log(e);
|
||||
throw new ClassNotFoundException("The class " + className + " was not loadable.");
|
||||
}//catch//
|
||||
catch(NoClassDefFoundError e) {
|
||||
Debug.log(e);
|
||||
throw new ClassNotFoundException("The class " + className + " definition was not found.");
|
||||
}//catch//
|
||||
}//loadClass()//
|
||||
/**
|
||||
* Will allow the user of the stream to peek at a byte in the stream.
|
||||
* @param offset The offset from the current location in the stream.
|
||||
* @return Will return the byte at that offset.
|
||||
*/
|
||||
public byte peekByte(int offset) throws IOException {
|
||||
/* if((position + offset < count) && (position + offset >= 0)) {
|
||||
return buffer[position + offset];
|
||||
}//if//
|
||||
|
||||
throw new IOException("Invalid offset.");
|
||||
*/
|
||||
throw new IOException("ObjectInputStream.peakByte(int) not yet implemented.");
|
||||
}//peekByte()//
|
||||
/**
|
||||
* Reads an array from the stream.
|
||||
* @param isPrimitive Whether the array is of a primitive type.
|
||||
* @return The array object.
|
||||
*/
|
||||
private Object readArray() throws IOException, ClassNotFoundException {
|
||||
int deserializedValueIndex = deserializedValues.getSize();
|
||||
Object array = null;
|
||||
String typeName;
|
||||
Class type;
|
||||
int typeNumber;
|
||||
int dimensionCount;
|
||||
int dimensionSize;
|
||||
boolean isNative = readBoolean();
|
||||
|
||||
deserializedValues.add(null);
|
||||
|
||||
if(isNative) {
|
||||
switch(readByte()) {
|
||||
case BOOLEAN: {
|
||||
type = Boolean.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
type = Byte.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
type = Short.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
type = Integer.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
type = Float.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
type = Long.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
type = Double.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
type = Character.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log("Error: Unidentified primitive type.");
|
||||
type = null;
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
typeName = type.getName();
|
||||
}//if//
|
||||
else {
|
||||
typeName = readString();
|
||||
type = loadClass(typeName);
|
||||
}//else//
|
||||
|
||||
typeNumber = readByte();
|
||||
dimensionCount = readInt();
|
||||
//Read the first dimension's size so that we can create the array.//
|
||||
dimensionSize = readInt();
|
||||
|
||||
if(dimensionSize != -1) {
|
||||
//Create the array with a size for only the first dimension.//
|
||||
try {
|
||||
array = Array.newInstance(type, dimensionSize);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e, "Caught while trying to instantiate an instance of [" + typeName);
|
||||
throw new IOException("Error instantiating array.");
|
||||
}//catch//
|
||||
|
||||
deserializedValues.replace(deserializedValueIndex, array);
|
||||
readArray(array, typeName, typeNumber, 0, dimensionCount, dimensionSize);
|
||||
|
||||
if(classTracker != null) {
|
||||
classTracker.add(array.getClass().getName());
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
return array;
|
||||
}//readArray()//
|
||||
/**
|
||||
* A recusive method which will iterate over each item in the array and output it to the stream.
|
||||
* The arrayType should be Stream.OBJECT or one of the primitives (ie Stream.INTEGER or Stream.BYTE..etc).
|
||||
* @param array The array housing the data to be read. This array is already correctly sized for the data.
|
||||
* @param typeNumber The array type indicating what type of data is being read.
|
||||
* @param dimension The current dimension being read.
|
||||
* @param dimensionCount The number of dimensions to be read.
|
||||
* @param dimensionSize The count of elements in the given array to be read.
|
||||
*/
|
||||
private void readArray(Object array, String typeName, int typeNumber, int dimension, int dimensionCount, int dimensionSize) throws IOException, ClassNotFoundException {
|
||||
if(dimension + 1 == dimensionCount) {
|
||||
switch(typeNumber) {
|
||||
case OBJECT: {
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
Object obj = readObject();
|
||||
|
||||
if(obj != null) { //Temp fix for gcj.//
|
||||
Array.set(array, index, obj);
|
||||
}//if//
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
int[] typedArray = (int[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readInt();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
long[] typedArray = (long[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readLong();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
short[] typedArray = (short[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readShort();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
byte[] typedArray = (byte[]) array;
|
||||
|
||||
read(typedArray);
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
char[] typedArray = (char[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readChar();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case BOOLEAN: {
|
||||
boolean[] typedArray = (boolean[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readBoolean();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
float[] typedArray = (float[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readFloat();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
double[] typedArray = (double[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
typedArray[index] = readDouble();
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
throw new IOException("Invalid arrayType found.");
|
||||
}//default//
|
||||
}//switch//
|
||||
}//if//
|
||||
else {
|
||||
String nextTypeName;
|
||||
Class nextType;
|
||||
|
||||
if(dimension + 2 == dimensionCount) {
|
||||
if(typeNumber == OBJECT) {
|
||||
nextTypeName = typeName.substring(2, typeName.length() - 1);
|
||||
nextType = loadClass(nextTypeName);
|
||||
}//if//
|
||||
else {
|
||||
switch(typeNumber) {
|
||||
case BOOLEAN: {
|
||||
nextType = Boolean.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
nextType = Byte.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
nextType = Short.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
nextType = Integer.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
nextType = Float.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
nextType = Long.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
nextType = Double.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
nextType = Character.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log("Error: Unidentified primitive type.");
|
||||
nextType = null;
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
nextTypeName = nextType.getName();
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
nextTypeName = typeName.substring(1);
|
||||
nextType = loadClass(nextTypeName);
|
||||
}//else//
|
||||
|
||||
//Read the next dimension of the array.//
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
int nextDimensionSize = readInt();
|
||||
|
||||
//If the dimension is not null (as indicated by -1) then create it and read it.//
|
||||
if(nextDimensionSize != -1) {
|
||||
Object nextArray = Array.newInstance(nextType, nextDimensionSize);
|
||||
|
||||
Array.set(array, index, nextArray);
|
||||
readArray(nextArray, nextTypeName, typeNumber, dimension + 1, dimensionCount, nextDimensionSize);
|
||||
}//if//
|
||||
else {
|
||||
Array.set(array, index, null);
|
||||
}//else//
|
||||
}//for//
|
||||
}//else//
|
||||
}//readArray()//
|
||||
/**
|
||||
* Reads an object from the stream.
|
||||
* @return The object read from the stream.
|
||||
*/
|
||||
public Object readObject() throws ClassNotFoundException, IOException {
|
||||
return readObject(false);
|
||||
}//readObject()//
|
||||
/**
|
||||
* Reads an object from the stream.
|
||||
* @param loopDetect
|
||||
* @return The object read from the stream.
|
||||
*/
|
||||
protected Object readObject(boolean loopDetect) throws ClassNotFoundException, IOException {
|
||||
int objectType = readByte();
|
||||
Object result = null;
|
||||
boolean alreadyAddedToDeserializedValues = false; //Arrays and Object which may have internal recusive references must add to the list as soon as the object/array has been allocated.//
|
||||
|
||||
switch(objectType) {
|
||||
case ARRAY: {
|
||||
result = readArray();
|
||||
alreadyAddedToDeserializedValues = true;
|
||||
break;
|
||||
}//case//
|
||||
case NULL: {
|
||||
break;
|
||||
}//case//
|
||||
case RECURSIVE_OBJECT: {
|
||||
int number = readInt();
|
||||
|
||||
return deserializedValues.get(number);
|
||||
}//case//
|
||||
case CUSTOM_OBJECT: {
|
||||
if(loopDetect) {
|
||||
throw new IOException("Invalid stream detected due to unexpected looping.");
|
||||
}//if//
|
||||
|
||||
try {
|
||||
Class type;
|
||||
int deserializedValueIndex = deserializedValues.getSize();
|
||||
|
||||
//Add a place holder to the deserialized object list.//
|
||||
deserializedValues.add(null);
|
||||
type = (Class) readObject();
|
||||
|
||||
result = deserialize(type);
|
||||
deserializedValues.replace(deserializedValueIndex, result); //Replace the placeholder with the object.//
|
||||
alreadyAddedToDeserializedValues = true;
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
throw e;
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Stream corruption error or Stream setup error found while trying to read an Object.");
|
||||
}//catch//
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case OBJECT: {
|
||||
if(loopDetect) {
|
||||
throw new IOException("Invalid stream detected due to unexpected looping.");
|
||||
}//if//
|
||||
|
||||
try {
|
||||
Class type;
|
||||
int deserializedValueIndex = deserializedValues.getSize();
|
||||
|
||||
//Add a place holder to the deserialized object list.//
|
||||
deserializedValues.add(null);
|
||||
type = (Class) readObject();
|
||||
|
||||
//Create a new instance using the default constructor.//
|
||||
try {
|
||||
result = type.newInstance();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignore.//
|
||||
}//catch//
|
||||
|
||||
//Try to create a new instance using native code.//
|
||||
if(result == null) {
|
||||
try {
|
||||
result = allocateNewObject(type);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
throw new IOException("Error allocating type: " + type.getName().toString() + " Cannot finish reading stream due to finding unknown object type: " + type.getName() + "\r\n\tCausing exception: " + e.toString());
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
if(result != null) {
|
||||
deserializedValues.replace(deserializedValueIndex, result); //Replace the placeholder with the object.//
|
||||
alreadyAddedToDeserializedValues = true;
|
||||
result = deserialize(result);
|
||||
}//if//
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
throw e;
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Stream corruption error or Stream setup error found while trying to read an Object.");
|
||||
}//catch//
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case BOOLEAN: {
|
||||
result = new Boolean(readBoolean());
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
result = new Byte(readByte());
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
result = new Character(readChar());
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
result = new Short(readShort());
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
result = new Integer(readInt());
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
result = new Long(readLong());
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
result = new Float(readFloat());
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
result = new Double(readDouble());
|
||||
break;
|
||||
}//case//
|
||||
case STRING: {
|
||||
/*
|
||||
result = StringSupport.fromBytes(buffer, position, -1);
|
||||
pos += StringSupport.getStringLength((String) result) + 4;
|
||||
*/
|
||||
result = readUTF16();
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case UTF8: {
|
||||
/*
|
||||
result = StringSupport.fromUtfBytes(buffer, position, -1);
|
||||
pos += StringSupport.getUtfStringLength((String) result) + 4;
|
||||
*/
|
||||
result = readUTF8();
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case CLASS: {
|
||||
int deserializedValueIndex = deserializedValues.getSize();
|
||||
|
||||
//Add a place holder to the deserialized object list.//
|
||||
deserializedValues.add(null);
|
||||
//Read the type.//
|
||||
result = readType();
|
||||
//Replace the placeholder.//
|
||||
deserializedValues.replace(deserializedValueIndex, result);
|
||||
//Set the flag so we don't add the deserialized value twice.//
|
||||
alreadyAddedToDeserializedValues = true;
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case SHARED_BOOLEAN: {
|
||||
result = (readBoolean() == true ? Boolean.TRUE : Boolean.FALSE);
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
if(isDecrypting()) {
|
||||
throw new IOSecurityException("Stream corruption detected. Most likely cause was a failure to properly decrypt the stream.");
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException("Stream corruption detected. Unknown object type.");
|
||||
}//else//
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
if((result != null) && (!alreadyAddedToDeserializedValues)) {
|
||||
//Cache the return value in case the object is referenced again in this stream.//
|
||||
deserializedValues.add(result);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//readObject()//
|
||||
/**
|
||||
* Reads a string from the stream as an object. This is wholly different from using the readUTF() readUTF8() and readUTF16() methods.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public String readString() throws IOException {
|
||||
try {
|
||||
return (String) readObject(false);
|
||||
}//try//
|
||||
catch(ClassCastException e) {
|
||||
throw new IOException("Stream corruption: Unable to cast Object to String in readString().");
|
||||
}//catch//
|
||||
catch(ClassNotFoundException e) {
|
||||
throw new IOException("Stream corruption: Unable to find a class while reading a string: " + e.getMessage());
|
||||
}//catch//
|
||||
}//readString()//
|
||||
/**
|
||||
* Reads a class name or ID off of the stream.
|
||||
* If optimized class streaming is enabled on the remote process, then the classList will be used to cache the mapping of class objects to ID's.
|
||||
* @return The class object read from the stream.
|
||||
*/
|
||||
protected Class readType() throws IOException, ClassNotFoundException {
|
||||
Object object = readObject();
|
||||
Integer index = (Integer) readObject();
|
||||
Class result = null;
|
||||
|
||||
if(object != null) {
|
||||
try {
|
||||
if(object instanceof String) {
|
||||
result = loadClass((String) object);
|
||||
}//if//
|
||||
else {
|
||||
switch(((Byte) object).intValue()) {
|
||||
case BOOLEAN: {
|
||||
result = Boolean.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
result = Byte.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
result = Short.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
result = Integer.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
result = Float.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
result = Long.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
result = Double.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
result = Character.TYPE;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log("Error: Unidentified primitive type.");
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
}//else//
|
||||
}//try//
|
||||
catch(ClassNotFoundException e) {
|
||||
if(streamManager != null) {
|
||||
result = streamManager.replaceType((String) object);
|
||||
|
||||
if(result == null) {
|
||||
throw e;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
throw e;
|
||||
}//else//
|
||||
}//catch//
|
||||
|
||||
//Save the class reference if the index is non null.//
|
||||
if(index != null) {
|
||||
synchronized(classList) {
|
||||
//Only place the type in the classList when it will be the last item in the class list.//
|
||||
while(classList.getSize() != index.intValue()) {
|
||||
try {
|
||||
classList.wait();
|
||||
}//try//
|
||||
catch(InterruptedException e) {
|
||||
Thread.interrupted();
|
||||
}//catch//
|
||||
}//while//
|
||||
|
||||
classList.add(result);
|
||||
|
||||
classList.notifyAll();
|
||||
}//synchronized//
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
synchronized(classList) {
|
||||
if(classList.getSize() <= index.intValue()) {
|
||||
throw new IOException("Unable to find the class due to an invalid index being received.");
|
||||
}//if//
|
||||
|
||||
result = (Class) classList.get(index.intValue());
|
||||
}//synchronized//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//readType()//
|
||||
/**
|
||||
* Resets this stream so that it may be re-read.
|
||||
*/
|
||||
public void reset() throws java.io.IOException {
|
||||
if(deserializedValues != null) {
|
||||
deserializedValues.removeAll();
|
||||
}//if//
|
||||
}//reset()//
|
||||
}//AbstractObjectInputStream//
|
||||
697
Common/src/com/common/io/AbstractObjectOutputStream.java
Normal file
697
Common/src/com/common/io/AbstractObjectOutputStream.java
Normal file
@@ -0,0 +1,697 @@
|
||||
/*
|
||||
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Externalizable;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import com.common.orb.Orb;
|
||||
import com.common.util.*;
|
||||
import com.common.debug.*;
|
||||
import com.common.util.optimized.*;
|
||||
|
||||
/**
|
||||
* Defines a basic object output stream which can be subclassed as needed.
|
||||
*/
|
||||
public abstract class AbstractObjectOutputStream extends AbstractStandardOutputStream implements IObjectStream, java.io.ObjectOutput, IObjectOutputStream {
|
||||
/** The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming. */
|
||||
private IHashMap classMap;
|
||||
/** A collection of objects which have already been serialized, used to prevent recusive serialization. */
|
||||
private ObjectIntHashMap serializedObjectMap;
|
||||
/** The handler called when writing a class name to the stream. This allows the application to swap the name for another name. */
|
||||
private IClassReplacementHandler classReplacementHandler = null;
|
||||
/**
|
||||
* Adds a custom serialization handler to the mapping for use by the object input and output streams.
|
||||
* @param type The class the handler will be used to serialize and deserialize.
|
||||
* @param handler The handler used to serialize and deserialize instances of the given class.
|
||||
*/
|
||||
public static final void addCustomSerializationHandler(Class type, ISerializationHandler handler) {
|
||||
AbstractObjectInputStream.addCustomSerializationHandler(type, handler);
|
||||
}//addCustomSerializationHandler()//
|
||||
/**
|
||||
* AbstractObjectOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
*/
|
||||
public AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler) throws IOException {
|
||||
this(classMap, classReplacementHandler, null);
|
||||
}//AbstractObjectOutputStream()//
|
||||
/**
|
||||
* AbstractObjectOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param classMap The optional mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The optional handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
* @param serializedObjectMap The optional map of indices by class name - used in conjunction with the classMap to serialize class names.
|
||||
*/
|
||||
protected AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, ObjectIntHashMap serializedObjectMap) throws IOException {
|
||||
super();
|
||||
this.classReplacementHandler = classReplacementHandler;
|
||||
//Save the class mapping for later use. This will be used to substitute class identifiers for class names in the stream.//
|
||||
this.classMap = classMap;
|
||||
//Setup the mapping of serialized objects so that recursion can be detected.//
|
||||
this.serializedObjectMap = serializedObjectMap != null ? serializedObjectMap : new ObjectIntHashMap(30, com.common.comparison.Comparator.getIdentityComparator());
|
||||
}//AbstractObjectOutputStream()//
|
||||
/**
|
||||
* AbstractObjectOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, int defaultNumberStyle) throws IOException {
|
||||
this(classMap, classReplacementHandler, null, defaultNumberStyle);
|
||||
}//AbstractObjectOutputStream()//
|
||||
/**
|
||||
* AbstractObjectOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param classMap The optional mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The optional handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
* @param serializedObjectMap The optional map of indices by class name - used in conjunction with the classMap to serialize class names.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
protected AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, ObjectIntHashMap serializedObjectMap, int defaultNumberStyle) throws IOException {
|
||||
super(defaultNumberStyle);
|
||||
this.classReplacementHandler = classReplacementHandler;
|
||||
//Save the class mapping for later use. This will be used to substitute class identifiers for class names in the stream.//
|
||||
this.classMap = classMap;
|
||||
//Setup the mapping of serialized objects so that recursion can be detected.//
|
||||
this.serializedObjectMap = serializedObjectMap != null ? serializedObjectMap : new ObjectIntHashMap(30, com.common.comparison.Comparator.getIdentityComparator());
|
||||
}//AbstractObjectOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectOutputStream#getSerializedObjectMap()
|
||||
*/
|
||||
public ObjectIntHashMap getSerializedObjectMap() {
|
||||
return serializedObjectMap;
|
||||
}//getSerializedObjectMap()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectOutputStream#getClassMap()
|
||||
*/
|
||||
public IHashMap getClassMap() {
|
||||
return classMap;
|
||||
}//getClassMap()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IObjectOutputStream#getClassReplacementHandler()
|
||||
*/
|
||||
public IClassReplacementHandler getClassReplacementHandler() {
|
||||
return classReplacementHandler;
|
||||
}//getClassReplacementHandler()//
|
||||
/**
|
||||
* Closes this output stream and releases any system resources associated with this stream.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
//Clear out the serialized object map to help GC.//
|
||||
if(serializedObjectMap != null) {
|
||||
serializedObjectMap.removeAll();
|
||||
}//if//
|
||||
}//close()//
|
||||
/**
|
||||
* Flushes any buffered bytes to their destination.
|
||||
*/
|
||||
public abstract void flush() throws IOException;
|
||||
/**
|
||||
* Resets the stream so it may be reused.
|
||||
* It is the caller's reponsibility to ensure that other chained streams are also reset.
|
||||
*/
|
||||
protected void internalReset() {
|
||||
if(serializedObjectMap != null) {
|
||||
serializedObjectMap.removeAll();
|
||||
}//if//
|
||||
}//internalReset()//
|
||||
/**
|
||||
* Serializes the given object to this stream.
|
||||
* <p>NOTE: The OBJECT identifier and the object's type have already been serialized to the stream.
|
||||
* @param object The object to serialize.
|
||||
*/
|
||||
protected void serializeObject(Object object) throws IOException {
|
||||
//Note: The proxy class can't implement IExternalizable, but the proxied class can. To avoid trying to make a remote call to the IExternalizable writeExternal method, we need to ensure this isn't a proxy.//
|
||||
if(object instanceof IExternalizable/* && !Orb.isProxy(object)*/) {
|
||||
//Use the serialize handler.//
|
||||
write(OBJECT);
|
||||
//Write the object's class.//
|
||||
writeObject(object.getClass());
|
||||
//Call object to write its' self out.//
|
||||
((IExternalizable) object).writeExternal(this);
|
||||
}//if//
|
||||
else if(object instanceof Externalizable) {
|
||||
//Use the serialize handler.//
|
||||
write(OBJECT);
|
||||
//Write the object's class.//
|
||||
writeObject(object.getClass());
|
||||
//Call object to write its' self out.//
|
||||
((Externalizable) object).writeExternal(this);
|
||||
}//else if//
|
||||
else {
|
||||
ISerializationHandler serializeHandler = (ISerializationHandler) ObjectStream.serializationHandlersMap.get(object.getClass());
|
||||
|
||||
//Use the serialize handler.//
|
||||
write(CUSTOM_OBJECT);
|
||||
//Write the object's class.//
|
||||
writeObject(object.getClass());
|
||||
|
||||
if(serializeHandler != null) {
|
||||
serializeHandler.serialize(object, this);
|
||||
}//if//
|
||||
else if(object instanceof Throwable) {
|
||||
//Allow exceptions to be serialized, although the exception stack and message data will not be serialized because it cannot be reassembled on the other side.//
|
||||
}//else if//
|
||||
else {
|
||||
throw new IOException(object.getClass().getName() + " does not support serialization.");
|
||||
}//else//
|
||||
}//else//
|
||||
}//serialize()//
|
||||
/**
|
||||
* Will recusively write out the contents of the array. Will also optimize for primitive types.
|
||||
* @param array The array to write to the stream.
|
||||
*/
|
||||
private void writeArray(Object array) throws IOException, ClassNotFoundException {
|
||||
String className = array.getClass().getName();
|
||||
int dimensionCount = 0;
|
||||
char arrayTypeCharacter;
|
||||
int typeNumber;
|
||||
//Class arrayClass = null;
|
||||
|
||||
//Count the number of array dimensions.//
|
||||
while(className.charAt(dimensionCount) == '[') {
|
||||
dimensionCount++;
|
||||
}//while//
|
||||
|
||||
//Identify the array type (Object, int, byte, float, etc...).//
|
||||
arrayTypeCharacter = className.charAt(dimensionCount);
|
||||
|
||||
switch(arrayTypeCharacter) {
|
||||
case 'L': {
|
||||
typeNumber = OBJECT;
|
||||
break;
|
||||
}//case//
|
||||
case 'B': {
|
||||
typeNumber = BYTE;
|
||||
break;
|
||||
}//case//
|
||||
case 'D': {
|
||||
typeNumber = DOUBLE;
|
||||
break;
|
||||
}//case//
|
||||
case 'F': {
|
||||
typeNumber = FLOAT;
|
||||
break;
|
||||
}//case//
|
||||
case 'I': {
|
||||
typeNumber = INTEGER;
|
||||
break;
|
||||
}//case//
|
||||
case 'J': {
|
||||
typeNumber = LONG;
|
||||
break;
|
||||
}//case//
|
||||
case 'S': {
|
||||
typeNumber = SHORT;
|
||||
break;
|
||||
}//case//
|
||||
case 'V': {
|
||||
typeNumber = BOOLEAN;
|
||||
break;
|
||||
}//case//
|
||||
case 'C': {
|
||||
typeNumber = CHARACTER;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log("Error: Unable to determine the array type.");
|
||||
typeNumber = OBJECT;
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
//Write the array header to the stream.//
|
||||
write(ARRAY);
|
||||
|
||||
if(dimensionCount == 1) {
|
||||
if(typeNumber == OBJECT) {
|
||||
writeBoolean(false);
|
||||
//Remove the preceeding '[L' and ending ';'.//
|
||||
writeString(className.substring(2, className.length() - 1));
|
||||
}//if//
|
||||
else {
|
||||
writeBoolean(true);
|
||||
writeByte(typeNumber);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
writeBoolean(false);
|
||||
//Remove the preceeding '['.//
|
||||
writeString(className.substring(1));
|
||||
}//else//
|
||||
|
||||
writeByte((byte) typeNumber);
|
||||
writeInt(dimensionCount);
|
||||
writeArray(array, typeNumber, dimensionCount, 0);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* A recusive method which will iterate over each item in the array and output it to the stream.
|
||||
* The arrayType should be Stream.OBJECT or one of the primitives (ie Stream.INTEGER or Stream.BYTE..etc).
|
||||
* <p>NOTE: The length of the dimensionSizeList may not be the same as the numberOfDimensions.
|
||||
* @param array The array to write to the stream.
|
||||
* @param arrayType The type of the array we are writing.
|
||||
* @param numberOfDimensions The number of dimensions for this array.
|
||||
* @param dimensionIndex The index of the dimension we are currently writing.
|
||||
* @param dimensionSizeList ?
|
||||
*/
|
||||
private void writeArray(Object array, int typeNumber, int dimensionCount, int dimensionIndex) throws IOException {
|
||||
int dimensionSize = array != null ? Array.getLength(array) : -1;
|
||||
|
||||
//Write the dimension size or -1 if the array is null.//
|
||||
writeInt(dimensionSize);
|
||||
|
||||
//If the array is not null then write it out.//
|
||||
if(array != null) {
|
||||
if(dimensionCount == dimensionIndex + 1) {
|
||||
switch(typeNumber) {
|
||||
case OBJECT: {
|
||||
Object[] objects = (Object[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeObject(objects[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
int[] ints = (int[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeInt(ints[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
long[] longs = (long[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeLong(longs[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
short[] shorts = (short[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeShort(shorts[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
write((byte[]) array);
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
char[] chars = (char[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeChar(chars[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case BOOLEAN: {
|
||||
boolean[] booleans = (boolean[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeBoolean(booleans[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
float[] floats = (float[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeFloat(floats[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
double[] doubles = (double[]) array;
|
||||
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeDouble(doubles[index]);
|
||||
}//for//
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
throw new IOException("Invalid arrayType found while streaming the array.");
|
||||
}//default//
|
||||
}//switch//
|
||||
}//if//
|
||||
else {
|
||||
for(int index = 0; index < dimensionSize; index++) {
|
||||
writeArray(Array.get(array, index), typeNumber, dimensionCount, dimensionIndex + 1);
|
||||
}//for//
|
||||
}//else//
|
||||
}//if//
|
||||
}//writeArray()//
|
||||
/**
|
||||
* Writes a string in double byte format (two byte Unicode).
|
||||
* @param string The string to write.
|
||||
*/
|
||||
public void writeDoubleByte(String string) throws IOException {
|
||||
writeObject(string, STRING);
|
||||
}//writeDoubleByte()//
|
||||
/**
|
||||
* Writes a Boolean object to the stream.
|
||||
* @param object The boolean to write.
|
||||
*/
|
||||
public void writeObject(Boolean object) throws IOException {
|
||||
writeObject(object, (object == Boolean.TRUE || object == Boolean.FALSE) ? SHARED_BOOLEAN : BOOLEAN);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Byte object to the stream.
|
||||
* @param object The byte to write.
|
||||
*/
|
||||
public void writeObject(Byte object) throws IOException {
|
||||
writeObject(object, BYTE);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Character object to the stream.
|
||||
* @param object The character to write.
|
||||
*/
|
||||
public void writeObject(Character object) throws IOException {
|
||||
writeObject(object, CHARACTER);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Double object to the stream.
|
||||
* @param object The double to write.
|
||||
*/
|
||||
public void writeObject(Double object) throws IOException {
|
||||
writeObject(object, DOUBLE);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Float object to the stream.
|
||||
* @param object The float to write.
|
||||
*/
|
||||
public void writeObject(Float object) throws IOException {
|
||||
writeObject(object, FLOAT);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes an Integer object to the stream.
|
||||
* @param object The integer to write.
|
||||
*/
|
||||
public void writeObject(Integer object) throws IOException {
|
||||
writeObject(object, INTEGER);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Long object to the stream.
|
||||
* @param object The long to write.
|
||||
*/
|
||||
public void writeObject(Long object) throws IOException {
|
||||
writeObject(object, LONG);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes an object to the stream.
|
||||
* @param object The object to write to this stream.
|
||||
*/
|
||||
public void writeObject(Object object) throws IOException {
|
||||
writeObject(object, UNKNOWN_OBJECT);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* TODO: Update this documentation!<p>
|
||||
* Writes any object to the stream. The object must either be one of the optimized types, or it must implement Externalizable, IExternalizable, or it must have registered special serialization handlers.
|
||||
* @param object The object to serialize to this stream.
|
||||
* @param objectType The type code for the object. This should be UNKNOWN_OBJECT if the type code is not yet known.
|
||||
*/
|
||||
protected void writeObject(Object object, byte objectType) throws IOException {
|
||||
try {
|
||||
int objectNumber;
|
||||
|
||||
if(object == null) {
|
||||
//Write the null value to the stream.//
|
||||
write(NULL);
|
||||
}//if//
|
||||
else if((objectNumber = serializedObjectMap.get(object)) != IObjectIntHashMap.NULL_VALUE) { //Check to see if this object has already been serialized.//
|
||||
//Place the object number on the stream because the object has already been streamed.//
|
||||
write(RECURSIVE_OBJECT);
|
||||
writeInt(objectNumber);
|
||||
}//if//
|
||||
else {
|
||||
//Add the object to the collection of already sent objects.//
|
||||
objectNumber = serializedObjectMap.getSize();
|
||||
serializedObjectMap.put(object, objectNumber);
|
||||
|
||||
//Serialize the object.//
|
||||
if(object instanceof Class) {
|
||||
writeByte(CLASS);
|
||||
writeType((Class) object);
|
||||
}//if//
|
||||
else if(object.getClass().isArray()) {
|
||||
writeArray(object);
|
||||
}//else if//
|
||||
else {
|
||||
//Setup the type identifier so that some optimizations can occur.//
|
||||
if(objectType == UNKNOWN_OBJECT) {
|
||||
if(object instanceof java.lang.Number) {
|
||||
if(object instanceof java.lang.Integer) {
|
||||
objectType = INTEGER;
|
||||
}//if//
|
||||
else if(object instanceof java.lang.Long) {
|
||||
objectType = LONG;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.Byte) {
|
||||
objectType = BYTE;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.Short) {
|
||||
objectType = SHORT;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.Float) {
|
||||
objectType = FLOAT;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.Double) {
|
||||
objectType = DOUBLE;
|
||||
}//else if//
|
||||
}//if//
|
||||
else if(object instanceof java.lang.Character) {
|
||||
objectType = CHARACTER;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.String) {
|
||||
objectType = UTF8;
|
||||
}//else if//
|
||||
else if(object instanceof java.lang.Boolean) {
|
||||
if(object == Boolean.TRUE || object == Boolean.FALSE) {
|
||||
objectType = SHARED_BOOLEAN;
|
||||
}//if//
|
||||
else {
|
||||
objectType = BOOLEAN;
|
||||
}//else//
|
||||
}//else if//
|
||||
}//if//
|
||||
|
||||
//Write the object using either the optimized code, or the standard object serialization code.//
|
||||
if(objectType != UNKNOWN_OBJECT) {
|
||||
//Write the type code.//
|
||||
write(objectType);
|
||||
|
||||
//Determine which optimized type it is.//
|
||||
switch(objectType) {
|
||||
case BOOLEAN: {
|
||||
writeBoolean(((Boolean) object).booleanValue());
|
||||
break;
|
||||
}//case//
|
||||
case BYTE: {
|
||||
writeByte(((Byte) object).byteValue());
|
||||
break;
|
||||
}//case//
|
||||
case CHARACTER: {
|
||||
writeChar(((Character) object).charValue());
|
||||
break;
|
||||
}//case//
|
||||
case SHORT: {
|
||||
writeShort(((Short) object).shortValue());
|
||||
break;
|
||||
}//case//
|
||||
case INTEGER: {
|
||||
writeInt(((Integer) object).intValue());
|
||||
break;
|
||||
}//case//
|
||||
case LONG: {
|
||||
writeLong(((Long) object).longValue());
|
||||
break;
|
||||
}//case//
|
||||
case FLOAT: {
|
||||
writeFloat(((Float) object).floatValue());
|
||||
break;
|
||||
}//case//
|
||||
case DOUBLE: {
|
||||
writeDouble(((Double) object).doubleValue());
|
||||
break;
|
||||
}//case//
|
||||
case STRING: {
|
||||
/*
|
||||
String str = ((String) outObject);
|
||||
int length = str.length();
|
||||
char[] chars = str.toCharArray();
|
||||
|
||||
writeInt(length);
|
||||
|
||||
for(int i = 0; i < length; i++) {
|
||||
write((int) chars[i]);
|
||||
}//for//
|
||||
*/
|
||||
/*
|
||||
writeInt(((String) outObject).length());
|
||||
StringSupport.writeString((String) outObject, this);
|
||||
*/
|
||||
/*
|
||||
int numBytes;
|
||||
|
||||
//Calculate the number of bytes the string will write out.//
|
||||
numBytes = StringSupport.getUnicode16Length((String) object) + 4;
|
||||
//Write the string bytes.//
|
||||
outputStream.ensureSpace(numBytes);
|
||||
StringSupport.toBytes((String) object, outputStream.getBuffer(), outputStream.index);
|
||||
outputStream.index += numBytes;
|
||||
*/
|
||||
writeUTF16((String) object);
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case UTF8: {
|
||||
/*
|
||||
int numBytes;
|
||||
|
||||
//Calculate the number of bytes the string will write out.//
|
||||
numBytes = StringSupport.getUtf8Length((String) object) + 4;
|
||||
//Write the string bytes.//
|
||||
outputStream.ensureSpace(numBytes);
|
||||
StringSupport.toUtf8Bytes((String) object, outputStream.getBuffer(), outputStream.index);
|
||||
outputStream.index += numBytes;
|
||||
*/
|
||||
writeUTF8((String) object);
|
||||
|
||||
break;
|
||||
}//case//
|
||||
case SHARED_BOOLEAN: {
|
||||
writeBoolean(((Boolean) object).booleanValue());
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
throw new IOException("Unknown optimized type.");
|
||||
}//default//
|
||||
}//switch//
|
||||
}//if//
|
||||
else {
|
||||
//Write the object's attributes.//
|
||||
serializeObject(object);
|
||||
}//else//
|
||||
}//else//
|
||||
}//else//
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
throw e; //Rethrow//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Caught a " + e.getClass().getName() + " exception while serializing an object of the class " + object.getClass());
|
||||
}//catch//
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a Short object to the stream.
|
||||
* @param object The short to write.
|
||||
*/
|
||||
public void writeObject(Short object) throws IOException {
|
||||
writeObject(object, SHORT);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a String object to the stream.
|
||||
* @param object The string to write.
|
||||
*/
|
||||
public void writeObject(String object) throws IOException {
|
||||
writeObject(object, UTF8);
|
||||
}//writeObject()//
|
||||
/**
|
||||
* Writes a string using the default format (UTF8 or multi-byte Unicode).
|
||||
* @param string The string to stream.
|
||||
*/
|
||||
public void writeString(String string) throws IOException {
|
||||
writeObject(string, UTF8);
|
||||
}//writeString()//
|
||||
/**
|
||||
* Manages the type collections so that the stream may be optimized such that a class name only has to be written to the stream once.
|
||||
* @param type The class to write to the stream.
|
||||
*/
|
||||
protected void writeType(Class type) throws IOException {
|
||||
//Check to see if we are using optimized type streaming.//
|
||||
Object typeData = null;
|
||||
Integer typeNumber = null;
|
||||
|
||||
if((classMap != null) && (classMap.containsKey(type))) {
|
||||
typeNumber = (Integer) classMap.get(type);
|
||||
}//if//
|
||||
else {
|
||||
if(classMap != null) {
|
||||
//We can use the size of the class map as an index because values will never be removed from the map.//
|
||||
classMap.put(type, (typeNumber = new Integer(classMap.getSize())));
|
||||
}//if//
|
||||
|
||||
if(type.isPrimitive()) {
|
||||
String name = type.getName();
|
||||
|
||||
switch(Character.toLowerCase(name.charAt(0))) {
|
||||
case 'i': {
|
||||
typeData = new Byte(INTEGER);
|
||||
break;
|
||||
}//case//
|
||||
case 'b': {
|
||||
if(type.equals(Byte.TYPE)) {
|
||||
typeData = new Byte(BYTE);
|
||||
}//if//
|
||||
else {
|
||||
typeData = new Byte(BOOLEAN);
|
||||
}//else//
|
||||
break;
|
||||
}//case//
|
||||
case 's': {
|
||||
typeData = new Byte(SHORT);
|
||||
break;
|
||||
}//case//
|
||||
case 'l': {
|
||||
typeData = new Byte(LONG);
|
||||
break;
|
||||
}//case//
|
||||
case 'f': {
|
||||
typeData = new Byte(FLOAT);
|
||||
break;
|
||||
}//case//
|
||||
case 'd': {
|
||||
typeData = new Byte(DOUBLE);
|
||||
break;
|
||||
}//case//
|
||||
case 'c': {
|
||||
typeData = new Byte(CHARACTER);
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log("Error: Unidentified primitive type name.");
|
||||
break;
|
||||
}//case//
|
||||
}//switch//
|
||||
}//if//
|
||||
else {
|
||||
//Write the type name this one time so that the remote process knows what the index will map to.//
|
||||
typeData = type.getName();
|
||||
|
||||
if(classReplacementHandler != null) {
|
||||
typeData = classReplacementHandler.getReplacementClassName((String) typeData);
|
||||
}//if//
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
writeObject(typeData);
|
||||
writeObject(typeNumber);
|
||||
}//writeType()//
|
||||
}//AbstractObjectOutputStream//
|
||||
314
Common/src/com/common/io/AbstractStandardInputStream.java
Normal file
314
Common/src/com/common/io/AbstractStandardInputStream.java
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
|
||||
/**
|
||||
* Provides basic functionality for a standard stream that can deserialize basic java data types.
|
||||
*/
|
||||
public abstract class AbstractStandardInputStream extends InputStream implements IStandardInputStream {
|
||||
public static final int STYLE_LSF = StreamSupport.NUMBER_LSF;
|
||||
public static final int STYLE_MSF = StreamSupport.NUMBER_MSF;
|
||||
public static final int STYLE_VLSF = StreamSupport.NUMBER_VLSF;
|
||||
public static final int STYLE_VMSF = StreamSupport.NUMBER_VMSF;
|
||||
public static final int STYLE_DEFAULT = STYLE_MSF;
|
||||
|
||||
protected static final String READ_EOF_MESSAGE = "There are not enough bytes in the stream to read the requested value.";
|
||||
private int defaultNumberStyle = STYLE_DEFAULT;
|
||||
/**
|
||||
* AbstractStandardInputStream constructor.
|
||||
*/
|
||||
protected AbstractStandardInputStream() {
|
||||
super();
|
||||
}//AbstractStandardInputStream()//
|
||||
/**
|
||||
* AbstractStandardInputStream constructor.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
protected AbstractStandardInputStream(int defaultNumberStyle) {
|
||||
super();
|
||||
this.defaultNumberStyle = defaultNumberStyle;
|
||||
}//AbstractStandardInputStream()//
|
||||
/**
|
||||
* Gets the number style used by default when serializing numbers.
|
||||
* @return The number style identifier used by default.
|
||||
*/
|
||||
public int getDefaultNumberStyle() {
|
||||
return defaultNumberStyle;
|
||||
}//getDefaultNumberStyle()//
|
||||
/**
|
||||
* Gets the number of available bytes in this input stream.
|
||||
* @return The count of bytes that may be immediatly read from the stream.
|
||||
*/
|
||||
public abstract int available() throws IOException;
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return false;
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public abstract void close() throws IOException;
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//decrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return false;
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Marks the stream so that the reader can reset to the current position.
|
||||
* @param readLimit The number of bytes that may be read before the mark becomes invalid.
|
||||
*/
|
||||
public abstract void mark(int readLimit);
|
||||
/**
|
||||
* Determines whether the stream supports using the mark method.
|
||||
* @return Whether the mark method is supported.
|
||||
*/
|
||||
public abstract boolean markSupported();
|
||||
/**
|
||||
* Reads an unsigned byte from the stream.
|
||||
* @return The unsigned byte read from the stream.
|
||||
*/
|
||||
public abstract int read() throws IOException;
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public abstract int read(byte[] buffer) throws IOException;
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @param offset The offset where the first read byte should be placed in the buffer.
|
||||
* @param length The number of bytes that should be read into the buffer.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public abstract int read(byte[] buffer, int offset, int length) throws IOException;
|
||||
/**
|
||||
* @see IInputStream.read(java.io.OutputStream, int)
|
||||
*/
|
||||
public abstract int read(java.io.OutputStream out, int length) throws IOException;
|
||||
/**
|
||||
* Reads a boolean from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public boolean readBoolean() throws IOException {
|
||||
int value = read();
|
||||
|
||||
if(value == -1) {
|
||||
throw new EOFException(READ_EOF_MESSAGE);
|
||||
}//if//
|
||||
|
||||
return value > 0;
|
||||
}//readBoolean()//
|
||||
/**
|
||||
* Reads a byte from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public byte readByte() throws IOException {
|
||||
return (byte) read();
|
||||
}//readByte()//
|
||||
/**
|
||||
* Reads a (2 byte) character from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public char readChar() throws IOException {
|
||||
return StreamSupport.readCharacter(this);
|
||||
}//readChar()//
|
||||
/**
|
||||
* Reads a (8 byte) double from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public double readDouble() throws IOException {
|
||||
return StreamSupport.readDouble(this);
|
||||
}//readDouble()//
|
||||
/**
|
||||
* Reads a fixed length string from file removes the unnecessary padding.
|
||||
* @param length The fixed number of bytes in the string.
|
||||
* @return The read string minus all space at the beginning or end of the string.
|
||||
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the input stream has been closed.
|
||||
*/
|
||||
public String readFixedLengthString(int length) throws java.io.IOException {
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
if(read(bytes) != length) {
|
||||
throw new IOException("Unable to finish reading the fixed length string.");
|
||||
}//if//
|
||||
|
||||
while((length > 0) && (bytes[length - 1] == 32)) {
|
||||
length--;
|
||||
}//while//
|
||||
|
||||
return new String(bytes, 0, length, STRING_FORMAT_UTF8);
|
||||
}//writeFixedLengthString()//
|
||||
/**
|
||||
* Reads a (4 byte) float from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public float readFloat() throws IOException {
|
||||
return StreamSupport.readFloat(this);
|
||||
}//readFloat()//
|
||||
/**
|
||||
* Don't know why this method exists?
|
||||
* @param bytes
|
||||
*/
|
||||
public void readFully(byte[] bytes) throws IOException {
|
||||
read(bytes);
|
||||
}//readFully()//
|
||||
/**
|
||||
* Don't know why this method exists?
|
||||
* @param bytes
|
||||
* @param offset
|
||||
* @param length
|
||||
*/
|
||||
public void readFully(byte[] bytes, int offset, int length) throws IOException {
|
||||
read(bytes, offset, length);
|
||||
}//readFully()//
|
||||
/**
|
||||
* Reads a (4 byte) int from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public int readInt() throws IOException {
|
||||
return StreamSupport.readInt(this, defaultNumberStyle);
|
||||
}//readInt()//
|
||||
/**
|
||||
* Reads a (4 byte) int from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public int readInt(int style) throws IOException {
|
||||
return StreamSupport.readInt(this, style);
|
||||
}//readInt()//
|
||||
/**
|
||||
* Reads a (8 byte) long from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public long readLong() throws IOException {
|
||||
return StreamSupport.readLong(this, defaultNumberStyle);
|
||||
}//readLong()//
|
||||
/**
|
||||
* Reads a (8 byte) long from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public long readLong(int style) throws IOException {
|
||||
return StreamSupport.readLong(this, style);
|
||||
}//readLong()//
|
||||
/**
|
||||
* Reads a string value from this stream.
|
||||
* <p>WARNING: This method is for backward compatibility only! It will not read a single line of a string, but will rather read the entire string prefixed by the string length.
|
||||
* @return The string value read.
|
||||
*/
|
||||
public String readLine() throws IOException {
|
||||
return readUTF();
|
||||
}//readLine()//
|
||||
/**
|
||||
* Reads a (2 byte) short from the stream.
|
||||
* @return The value read from the stream.
|
||||
*/
|
||||
public short readShort() throws IOException {
|
||||
return StreamSupport.readShort(this);
|
||||
}//readShort()//
|
||||
public int readUnsignedByte() throws IOException {
|
||||
int retVal = read();
|
||||
|
||||
return (int) (retVal < 0 ? retVal + 256 : retVal);
|
||||
}//readUnsignedByte()//
|
||||
public int readUnsignedShort() throws IOException {
|
||||
short retVal = readShort();
|
||||
|
||||
return (int) (retVal < 0 ? retVal + 65536 : retVal);
|
||||
}//readUnsignedShort()//
|
||||
/**
|
||||
* Reads a UTF8 string from the stream.
|
||||
* @see #readUTF8()
|
||||
* @return The string read from the stream.
|
||||
*/
|
||||
public String readUTF() throws IOException {
|
||||
return readUTF8();
|
||||
}//readUTF()//
|
||||
/**
|
||||
* Reads a UTF16 string from the stream.
|
||||
* A UTF16 string is a fixed character size string using 2 bytes for each character.
|
||||
* <p>WARNING: The user must call writeUTF16(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @return The string read from the stream.
|
||||
*/
|
||||
public String readUTF16() throws IOException {
|
||||
int size = readInt();
|
||||
String result = null;
|
||||
|
||||
if(size != -1) {
|
||||
byte[] bytes = new byte[size];
|
||||
|
||||
read(bytes);
|
||||
result = new String(bytes, STRING_FORMAT_UNICODE);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//readUTF()//
|
||||
/**
|
||||
* Reads a UTF8 string from the stream.
|
||||
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
|
||||
* <p>WARNING: The user must call writeUTF8(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @return The string read from the stream.
|
||||
*/
|
||||
public String readUTF8() throws IOException {
|
||||
int size = readInt();
|
||||
String result = null;
|
||||
|
||||
if(size != -1) {
|
||||
byte[] bytes = null;
|
||||
|
||||
//TODO: Remove this - seems like old code - it flagged my big-data test that used a string with 100k characters in it.
|
||||
//if(size > 16767) {
|
||||
// throw new IOException("Corruption detected while reading a UTF8 string from a stream. Please check to make sure that you are reading in the same order you wrote to the stream.");
|
||||
//}//if//
|
||||
|
||||
bytes = new byte[size];
|
||||
read(bytes);
|
||||
result = new String(bytes, STRING_FORMAT_UTF8);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//readUTF8()//
|
||||
/**
|
||||
* Resets the stream by telling the encapsulated stream to reset.
|
||||
*/
|
||||
public abstract void reset() throws IOException;
|
||||
/**
|
||||
* Skips the next <code>count</code> bytes on the stream.
|
||||
* @param count The number of bytes to skip.
|
||||
* @return The number of bytes that were skipped.
|
||||
*/
|
||||
public abstract long skip(long count) throws IOException;
|
||||
/**
|
||||
* Skips the specified number of bytes so that they are never read.
|
||||
* @param byteCount The number of bytes to skip.
|
||||
* @return The number of bytes skipped.
|
||||
*/
|
||||
public int skipBytes(int byteCount) throws IOException {
|
||||
return (int) skip((long) byteCount);
|
||||
}//skipBytes()//
|
||||
/**
|
||||
* Skips the specified number of bytes so that they are never read.
|
||||
* @param byteCount The number of bytes to skip.
|
||||
* @return The number of bytes skipped.
|
||||
*/
|
||||
public long skipBytes(long byteCount) throws IOException {
|
||||
return skip(byteCount);
|
||||
}//skipBytes()//
|
||||
}//AbstractStandardInputStream//
|
||||
275
Common/src/com/common/io/AbstractStandardOutputStream.java
Normal file
275
Common/src/com/common/io/AbstractStandardOutputStream.java
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2007 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Provides basic functionality for a standard stream that can serialize basic java data types.
|
||||
*/
|
||||
public abstract class AbstractStandardOutputStream extends OutputStream implements IStandardOutputStream {
|
||||
public static final int STYLE_LSF = StreamSupport.NUMBER_LSF;
|
||||
public static final int STYLE_MSF = StreamSupport.NUMBER_MSF;
|
||||
public static final int STYLE_VLSF = StreamSupport.NUMBER_VLSF;
|
||||
public static final int STYLE_VMSF = StreamSupport.NUMBER_VMSF;
|
||||
public static final int STYLE_DEFAULT = STYLE_MSF;
|
||||
|
||||
private boolean containsEncryptedSegments = false;
|
||||
private int defaultNumberStyle = STYLE_DEFAULT;
|
||||
/**
|
||||
* AbstractStandardOutputStream constructor.
|
||||
*/
|
||||
protected AbstractStandardOutputStream() {
|
||||
super();
|
||||
}//AbstractStandardOutputStream()//
|
||||
/**
|
||||
* AbstractStandardOutputStream constructor.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
protected AbstractStandardOutputStream(int defaultNumberStyle) {
|
||||
super();
|
||||
this.defaultNumberStyle = defaultNumberStyle;
|
||||
}//AbstractStandardOutputStream()//
|
||||
/**
|
||||
* Gets the number style used by default when serializing numbers.
|
||||
* @return The number style identifier used by default.
|
||||
*/
|
||||
public int getDefaultNumberStyle() {
|
||||
return defaultNumberStyle;
|
||||
}//getDefaultNumberStyle()//
|
||||
/**
|
||||
* @see IObjectOutputStream.canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return false;
|
||||
}//canEncrypt()//
|
||||
/**
|
||||
* Closes this output stream and the encapsulated output stream.
|
||||
*/
|
||||
public abstract void close() throws IOException;
|
||||
/**
|
||||
* Determines whether encryption was used for some or all of the stream.
|
||||
* @return Whether the stream utilized encryption.
|
||||
*/
|
||||
public boolean containsEncryptedSegments() {
|
||||
return containsEncryptedSegments;
|
||||
}//containsEncryptedSegments()//
|
||||
/**
|
||||
* Determines whether encryption was used for some or all of the stream.
|
||||
* @param containsEncryptedSegments Whether the stream utilized encryption.
|
||||
*/
|
||||
protected void containsEncryptedSegments(boolean containsEncryptedSegments) {
|
||||
this.containsEncryptedSegments = containsEncryptedSegments;
|
||||
}//containsEncryptedSegments()//
|
||||
/**
|
||||
* @see IObjectOutputStream.encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Flushes this output stream and the encapsulated output stream.
|
||||
*/
|
||||
public abstract void flush() throws IOException;
|
||||
/**
|
||||
* @see IObjectOutputStream.isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return false;
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Writes the bytes to the stream.
|
||||
* @param bytes The bytes to write to the stream.
|
||||
*/
|
||||
public abstract void write(byte[] bytes) throws IOException;
|
||||
/**
|
||||
* Writes the bytes to the stream.
|
||||
* @param bytes The bytes to write to the stream.
|
||||
* @param offset The offset of the first byte to write.
|
||||
* @param length the number of bytes to write.
|
||||
*/
|
||||
public abstract void write(byte[] bytes, int offset, int length) throws IOException;
|
||||
/**
|
||||
* Writes the unsigned byte to the stream.
|
||||
* @param b The unsigned byte to write to the stream.
|
||||
*/
|
||||
public abstract void write(int b) throws IOException;
|
||||
/**
|
||||
* Writes a boolean to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeBoolean(boolean value) throws IOException {
|
||||
write(value ? 1 : 0);
|
||||
}//writeBoolean()//
|
||||
/**
|
||||
* Writes a byte to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeByte(byte value) throws IOException {
|
||||
write(value);
|
||||
}//writeByte()//
|
||||
/**
|
||||
* Writes an unsigned byte to the stream.
|
||||
* @param value The unsigned value to write to the stream.
|
||||
*/
|
||||
public void writeByte(int value) throws IOException {
|
||||
write(value);
|
||||
}//writeByte()//
|
||||
/**
|
||||
* Writes a string in the default UTF8 (multi-byte Unicode) format.
|
||||
* @param string The string to stream.
|
||||
* @deprecated Use writeUTF16(String).
|
||||
*/
|
||||
public void writeBytes(String string) throws IOException {
|
||||
writeUTF16(string);
|
||||
}//writeBytes()//
|
||||
/**
|
||||
* Writes a character to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeChar(char value) throws IOException {
|
||||
StreamSupport.writeCharacter(value, this);
|
||||
}//writeChar()//
|
||||
/**
|
||||
* Writes a character to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeChar(int value) throws IOException {
|
||||
StreamSupport.writeCharacter((char) value, this);
|
||||
}//writeChar()//
|
||||
/**
|
||||
* Writes a string in the default UTF8 (multi-byte Unicode) format.
|
||||
* @param string The string to stream.
|
||||
* @deprecated Use writeUTF8(String).
|
||||
*/
|
||||
public void writeChars(String string) throws IOException {
|
||||
writeUTF8(string);
|
||||
}//writeChars()//
|
||||
/**
|
||||
* Writes a double to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeDouble(double value) throws IOException {
|
||||
StreamSupport.writeDouble(value, this);
|
||||
}//writeDouble()//
|
||||
/**
|
||||
* Writes a fixed length string to file and pads it with spaces where necessary.
|
||||
* @param string The string to write. This string must be under the byte size limit and an IOException will result from an improperly sized string.
|
||||
* @param length The fixed number of bytes in the string.
|
||||
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.
|
||||
*/
|
||||
public void writeFixedLengthString(String string, int length) throws java.io.IOException {
|
||||
byte[] bytes = string.getBytes(STRING_FORMAT_UTF8);
|
||||
int underflow;
|
||||
|
||||
if(bytes.length > length) {
|
||||
throw new IOException("Fixed string length exceeds expected length.");
|
||||
}//if//
|
||||
|
||||
write(bytes);
|
||||
underflow = length - bytes.length;
|
||||
|
||||
while(underflow-- > 0) {
|
||||
write(32);
|
||||
}//while//
|
||||
}//writeFixedLengthString()//
|
||||
/**
|
||||
* Writes a float to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeFloat(float value) throws IOException {
|
||||
StreamSupport.writeFloat(value, this);
|
||||
}//writeFloat()//
|
||||
/**
|
||||
* Writes a int to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeInt(int value) throws IOException {
|
||||
StreamSupport.writeInt(value, this, defaultNumberStyle);
|
||||
}//writeInt()//
|
||||
/**
|
||||
* Writes a int to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
* @param style One of the style identifiers defined by this output stream.
|
||||
*/
|
||||
public void writeInt(int value, int style) throws IOException {
|
||||
StreamSupport.writeInt(value, this, style);
|
||||
}//writeInt()//
|
||||
/**
|
||||
* Writes a long to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeLong(long value) throws IOException {
|
||||
StreamSupport.writeLong(value, this, defaultNumberStyle);
|
||||
}//writeLong()//
|
||||
/**
|
||||
* Writes a long to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
* @param style One of the style identifiers defined by this output stream.
|
||||
*/
|
||||
public void writeLong(long value, int style) throws IOException {
|
||||
StreamSupport.writeLong(value, this, style);
|
||||
}//writeLong()//
|
||||
/**
|
||||
* Writes an unsigned short to the stream.
|
||||
* @param value The unsigned value to write to the stream.
|
||||
*/
|
||||
public void writeShort(int value) throws IOException {
|
||||
StreamSupport.writeShort((short) (value & 0xFFFF), this);
|
||||
}//writeShort()//
|
||||
/**
|
||||
* Writes a short to the stream.
|
||||
* @param value The value to write to the stream.
|
||||
*/
|
||||
public void writeShort(short value) throws IOException {
|
||||
StreamSupport.writeShort(value, this);
|
||||
}//writeShort()//
|
||||
/**
|
||||
* Writes a UTF8 string to the stream.
|
||||
* @see #writeUTF8()
|
||||
* @param string The string to write to the stream.
|
||||
*/
|
||||
public void writeUTF(String string) throws IOException {
|
||||
writeUTF8(string);
|
||||
}//writeUTF()//
|
||||
/**
|
||||
* Writes a UTF16 string to the stream.
|
||||
* A UTF16 string is a fixed character size string using 2 bytes for each character.
|
||||
* <p>WARNING: The user must call readUTF16(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @param string The string to write to the stream.
|
||||
*/
|
||||
public void writeUTF16(String string) throws IOException {
|
||||
if(string != null) {
|
||||
byte[] bytes = string.getBytes(STRING_FORMAT_UNICODE);
|
||||
|
||||
writeInt(bytes.length);
|
||||
write(bytes);
|
||||
}//if//
|
||||
else {
|
||||
writeInt(-1);
|
||||
}//else//
|
||||
}//writeUTF16()//
|
||||
/**
|
||||
* Writes a UTF8 string to the stream.
|
||||
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
|
||||
* <p>WARNING: The user must call readUTF8(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @param string The string to write to the stream.
|
||||
*/
|
||||
public void writeUTF8(String string) throws IOException {
|
||||
if(string != null) {
|
||||
byte[] bytes = string.getBytes(STRING_FORMAT_UTF8);
|
||||
|
||||
writeInt(bytes.length);
|
||||
write(bytes);
|
||||
}//if//
|
||||
else {
|
||||
writeInt(-1);
|
||||
}//else//
|
||||
}//writeUTF8()//
|
||||
}//StandardOutputStream//
|
||||
34
Common/src/com/common/io/AsymmetricInputStream.java
Normal file
34
Common/src/com/common/io/AsymmetricInputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an asymmetricly encrypted stream to be plugged into an input stream so that read bytes are decrypted using the private key.
|
||||
*/
|
||||
public class AsymmetricInputStream extends CryptoInputStream implements IInputStream {
|
||||
private IAsymmetricAlgorithm algorithm = null;
|
||||
/**
|
||||
* AsymmetricInputStream constructor.
|
||||
*/
|
||||
public AsymmetricInputStream(InputStream stream, IAsymmetricAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
|
||||
}//AsymmetricInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#decrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.decrypt(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//decrypt()//
|
||||
}//AsymmetricInputStream//
|
||||
34
Common/src/com/common/io/AsymmetricOutputStream.java
Normal file
34
Common/src/com/common/io/AsymmetricOutputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an asymmetric stream to be plugged into an output stream so that written bytes are encrypted using the public key.
|
||||
*/
|
||||
public class AsymmetricOutputStream extends CryptoOutputStream implements IOutputStream {
|
||||
private IAsymmetricAlgorithm algorithm = null;
|
||||
/**
|
||||
* AsymmetricOutputStream constructor.
|
||||
*/
|
||||
public AsymmetricOutputStream(OutputStream stream, IAsymmetricAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
|
||||
}//AsymmetricOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#encrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.encrypt(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//encrypt()//
|
||||
}//AsymmetricOutputStream//
|
||||
272
Common/src/com/common/io/BufferedInputStream.java
Normal file
272
Common/src/com/common/io/BufferedInputStream.java
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The buffered input stream is used for two reasons. The first reason is to allow the user to peek
|
||||
* at future values in the stream. The second reason is to all more efficient read operations when
|
||||
* dealing with streams where reading one byte at a time is inefficient.
|
||||
* <p>TODO: Should add a close method which will close the underlying stream.</p>
|
||||
*/
|
||||
public class BufferedInputStream extends InputStream {
|
||||
public static final int DEFAULT_BLOCK_BUFFER_SIZE = 10;
|
||||
|
||||
private InputStream inputStream = null; //The input stream that source will be read from.//
|
||||
private byte[] buffer = null; //The buffer that will hold unread values.//
|
||||
private int bufferedSize = 0; //The number of bytes currently in the buffer.//
|
||||
private int firstByteOffset = 0; //The offset of the first byte in the buffer. This is necessary because we are using a rotating scheme where the first byte in the buffer is not always at index zero and the last byte may be at a smaller index than the first byte.//
|
||||
/**
|
||||
* BufferedInputStream constructor.
|
||||
* @param inputStream The stream containing the source data.
|
||||
*/
|
||||
public BufferedInputStream(InputStream inputStream) {
|
||||
this(inputStream, DEFAULT_BLOCK_BUFFER_SIZE);
|
||||
}//BufferedInputStream()//
|
||||
/**
|
||||
* BufferedInputStream constructor.
|
||||
* @param inputStream The stream containing the source data.
|
||||
* @param bufferSize The number of bytes to buffer at one time. This value must be greater than zero and it will determine how far the user can peek in the stream.
|
||||
*/
|
||||
public BufferedInputStream(InputStream inputStream, int bufferSize) {
|
||||
super();
|
||||
|
||||
if(bufferSize < 1) {
|
||||
throw new RuntimeException("The BufferedInputStream requires a buffer size > 0.");
|
||||
}//if//
|
||||
|
||||
this.inputStream = inputStream;
|
||||
this.buffer = new byte[bufferSize];
|
||||
}//BufferedInputStream()//
|
||||
/**
|
||||
* Determines how many more bytes of source data are available to be read.
|
||||
* @return The number of source bytes that are readable.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return inputStream.available();
|
||||
}//available()//
|
||||
/**
|
||||
* Fills the buffer with source bytes until either the buffer is full or there are no more source bytes.
|
||||
*/
|
||||
protected void fillBuffer() throws IOException {
|
||||
if(bufferedSize == 0) {
|
||||
firstByteOffset = 0;
|
||||
bufferedSize = inputStream.read(buffer);
|
||||
}//if//
|
||||
else {
|
||||
int offset = firstByteOffset + bufferedSize;
|
||||
int length;
|
||||
|
||||
if(offset < buffer.length) {
|
||||
bufferedSize += inputStream.read(buffer, offset, buffer.length - offset);
|
||||
}//if//
|
||||
|
||||
//Calculate the number of bytes remaining to be read (so that the buffer is full).//
|
||||
length = buffer.length - bufferedSize;
|
||||
|
||||
if(length > 0) {
|
||||
bufferedSize += inputStream.read(buffer, 0, length);
|
||||
}//if//
|
||||
}//else//
|
||||
}//fillBuffer()//
|
||||
/**
|
||||
* Gets the encapsulated input stream.
|
||||
* @return Gets the input stream that this object wrappers.
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}//getInputStream()//
|
||||
/**
|
||||
* Peeks at a single unsigned byte value in the stream of future values.
|
||||
* This method does NOT consume the value and the value will eventually be returned durring a read operation.
|
||||
* @param offset The offset in the stream for the byte that should be returned. A value of zero will return the byte that will next be returned by the read() operation. This value must be greater than or equal to zero and less than the buffer size used when creating this stream.
|
||||
* @return The byte at the given offset from the current position in the stream.
|
||||
*/
|
||||
public int peek(int offset) throws IOException {
|
||||
int retVal;
|
||||
|
||||
if((offset > buffer.length) || (offset < 0)) {
|
||||
throw new RuntimeException("Unable to peek at a byte that cannot be buffered. Please make sure you specify a large enough buffer size when constructing the BufferedInputStream object. You also may not peek at bytes already read from the stream.");
|
||||
}//if//
|
||||
else {
|
||||
int bufferOffset = offset + firstByteOffset;
|
||||
|
||||
if(bufferedSize < offset + 1) {
|
||||
fillBuffer();
|
||||
|
||||
if(bufferedSize < offset + 1) {
|
||||
throw new RuntimeException("Unable to peek at a byte that does not exist in the stream. Please make sure you verify there are enough bytes in the stream by calling inputStream.available().");
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
if(bufferOffset > buffer.length) {
|
||||
bufferOffset -= buffer.length;
|
||||
}//if//
|
||||
|
||||
retVal = buffer[bufferOffset];
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//peek()//
|
||||
/**
|
||||
* Peeks at a group of bytes in the stream's future.
|
||||
* This method does NOT consume the values and the values will eventually be returned durring a read operation.
|
||||
* @param streamOffset The offset in the stream for the first byte that should be returned. A value of zero will return the byte that will next be returned by the read() operation. This value must be greater than or equal to zero and less than the buffer size (used when creating this stream) minus the requested length.
|
||||
* @param outputBuffer The buffer that should be filled with the output bytes.
|
||||
* @param offset The offset in the output buffer where the first output byte will be placed.
|
||||
* @param length The number of output bytes requested for this operation. All requested bytes will be supplied or an exception will be raised because the stream either does not have enough bytes to fulfill the request, or because the buffer being used is smaller than the length + stream offset.
|
||||
* @return The byte at the given offset from the current position in the stream.
|
||||
*/
|
||||
public void peek(int streamOffset, byte[] outputBuffer, int offset, int length) throws IOException {
|
||||
if((streamOffset + length > buffer.length) || (streamOffset < 0)) {
|
||||
throw new RuntimeException("Unable to peek at a byte that cannot be buffered. Please make sure you specify a large enough buffer size when constructing the BufferedInputStream object. You also may not peek at bytes already read from the stream.");
|
||||
}//if//
|
||||
else {
|
||||
int bufferOffset = streamOffset + firstByteOffset;
|
||||
|
||||
if(bufferedSize < streamOffset + length) {
|
||||
fillBuffer();
|
||||
|
||||
if(bufferedSize < offset + length) {
|
||||
throw new RuntimeException("Unable to peek at a byte that does not exist in the stream. Please make sure you verify there are enough bytes in the stream by calling inputStream.available().");
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
while(length < 0) {
|
||||
//Adjust the starting point within the buffer.//
|
||||
if(bufferOffset > buffer.length) {
|
||||
bufferOffset -= buffer.length;
|
||||
}//if//
|
||||
|
||||
outputBuffer[offset++] = buffer[bufferOffset++];
|
||||
}//while//
|
||||
}//else//
|
||||
}//peek()//
|
||||
/**
|
||||
* Reads a single unsigned byte value from the stream.
|
||||
* @return The next unsigned byte value in the stream.
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
int retVal;
|
||||
|
||||
if(bufferedSize == 0) {
|
||||
fillBuffer();
|
||||
|
||||
if(bufferedSize > 0) {
|
||||
retVal = buffer[firstByteOffset++];
|
||||
bufferedSize--;
|
||||
|
||||
if(firstByteOffset == buffer.length) {
|
||||
firstByteOffset = 0;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException("No more source data.");
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
retVal = buffer[firstByteOffset++];
|
||||
bufferedSize--;
|
||||
|
||||
if(firstByteOffset == buffer.length) {
|
||||
firstByteOffset = 0;
|
||||
}//if//
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/**
|
||||
* Reads a bytes off the source stream and places them in the bytes buffer.
|
||||
* @param bytes The buffer that will contain the source bytes read from the stream.
|
||||
* @return The number of bytes read.
|
||||
*/
|
||||
public int read(byte[] bytes) throws IOException {
|
||||
return read(bytes, 0, bytes.length);
|
||||
}//read()//
|
||||
/**
|
||||
* Reads a bytes off the source stream and places them in the bytes buffer.
|
||||
* @param bytes The buffer that will contain the source bytes read from the stream.
|
||||
* @param offset The offset in the bytes buffer where the first source byte will be placed.
|
||||
* @param length The number of source bytes that will be placed in the bytes buffer. Note that <code>bytes.length - offset >= length</code> - this is not checked and non-compliance will result in a ArrayIndexOutOfBounds exception.
|
||||
* @return The number of bytes read.
|
||||
*/
|
||||
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||
int retVal = 0;
|
||||
|
||||
//If we have buffered bytes then first add them.//
|
||||
if(bufferedSize > 0) {
|
||||
int endLength = length > bufferedSize ? bufferedSize : length;
|
||||
int beginLength = 0;
|
||||
|
||||
//Save the number of bytes being copied.//
|
||||
retVal = endLength;
|
||||
|
||||
//Adjust the end length if it will over run the buffer size.//
|
||||
if(endLength + firstByteOffset > buffer.length) {
|
||||
beginLength = endLength - (buffer.length - firstByteOffset);
|
||||
endLength -= beginLength;
|
||||
}//if//
|
||||
|
||||
//Copy the bytes at the end of the buffer.//
|
||||
System.arraycopy(buffer, firstByteOffset, bytes, offset, endLength);
|
||||
|
||||
//Copy the bytes at the beginning of the buffer.//
|
||||
if(beginLength > 0) {
|
||||
System.arraycopy(buffer, 0, bytes, offset + endLength, beginLength);
|
||||
}//if//
|
||||
|
||||
//Adjust the buffer indexes.//
|
||||
bufferedSize = length > bufferedSize ? 0 : bufferedSize - length;
|
||||
firstByteOffset = bufferedSize == 0 ? 0 : firstByteOffset + length;
|
||||
|
||||
if(firstByteOffset >= buffer.length) {
|
||||
firstByteOffset = firstByteOffset - buffer.length;
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//If we did not have enough buffered bytes to fill the array then we will need to send the array to the source stream.//
|
||||
if(retVal < length) {
|
||||
retVal += inputStream.read(bytes, offset + retVal, length - retVal);
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/**
|
||||
* Skips <code>count</code> bytes in the stream.
|
||||
* @param count The number to skip.
|
||||
* @return The number of bytes skipped.
|
||||
*/
|
||||
public long skip(long count) throws IOException {
|
||||
int skipCount = 0;
|
||||
|
||||
//Skip the buffered values as necessary.//
|
||||
if(bufferedSize != 0) {
|
||||
//If the count is greater than the buffer size then clear the buffer, otherwise clear part of the buffer.//
|
||||
if(count > bufferedSize) {
|
||||
skipCount = bufferedSize;
|
||||
bufferedSize = 0;
|
||||
firstByteOffset = 0;
|
||||
}//if//
|
||||
else {
|
||||
skipCount = (int) count;
|
||||
bufferedSize -= count;
|
||||
firstByteOffset += count;
|
||||
|
||||
//Adjust the first byte offset so it is in the correct range.//
|
||||
if(firstByteOffset >= buffer.length) {
|
||||
firstByteOffset -= buffer.length;
|
||||
}//if//
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
//Skip any unbuffered values as necessary.//
|
||||
return skipCount < count ? inputStream.skip(count - skipCount) + skipCount : skipCount;
|
||||
}//skip()//
|
||||
}//BufferedInputStream//
|
||||
603
Common/src/com/common/io/BufferedOutputStream.java
Normal file
603
Common/src/com/common/io/BufferedOutputStream.java
Normal file
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.util.*;
|
||||
import com.common.debug.*;
|
||||
|
||||
/**
|
||||
* Implements a buffer around another output stream such that the user can insert values into the stream at a later time, and can track the byte location of a specific point in the stream so that it is updated when the stream is modified.
|
||||
* <p><b>WARNING: This class is not the least bit thread safe and is not designed to ever be thread safe.</b></p>
|
||||
* <p>TODO: It would be nice to be able to have a buffered output stream wrapper a byte array stream such that the buffered stream writes directly to the byte stream except when necessary (because of insert streams for example).</p>
|
||||
*/
|
||||
public class BufferedOutputStream extends OutputStream implements IOutputStreamLocation {
|
||||
public static final int DEFAULT_BUFFER_INCREMENT_SIZE = 1000;
|
||||
public static final int DEFAULT_INSERT_BUFFER_INCREMENT_SIZE = 100;
|
||||
public static final int DEFAULT_BUFFER_SIZE = 2000;
|
||||
public static final int DEFAULT_INSERT_BUFFER_SIZE = 200;
|
||||
|
||||
private int streamLocation = 0; //The location that the current stream is inserting into its parent output stream. If this stream is not inserting then it is the number of bytes already flushed to the encapuslated stream.//
|
||||
private boolean isFixedSize = false; //TODO: May determine by checking whether the buffer attribute is null.//
|
||||
private boolean isInsertStream = false; //Whether the stream is inserting into another buffer stream.//
|
||||
private int reservedByteCount = 0; //Only applies to fixed size insert streams. The number of bytes reserved in the encapsulated buffered output stream. This value goes down as bytes are written.//
|
||||
|
||||
private OutputStream outputStream = null; //The stream being buffered.//
|
||||
private int bufferIncrementSize = DEFAULT_BUFFER_INCREMENT_SIZE; //The number of bytes to increment the buffer by (when it is necessary).//
|
||||
private LiteList locations = new LiteList(10, 20); //The ordered collection of stream location objects.//
|
||||
private byte[] buffer = null; //The collection of bytes currently buffered.//
|
||||
private int bufferSize = 0; //The number of bytes currently buffered.// //TODO:Rename this to bufferIndex or bufferCount. BufferSize is very confusing.//
|
||||
/**
|
||||
* BufferedOutputStream constructor.
|
||||
* This constructor creates a simple location marker within a parent buffered output stream. The location will be updated as bytes are inserted earlier in the stream, and the updated location is accessable by the user.
|
||||
* @param streamLocation The location within the parent buffered output stream. This location will be updated by the parent stream as necessary.
|
||||
*/
|
||||
protected BufferedOutputStream(int streamLocation) {
|
||||
super();
|
||||
|
||||
this.streamLocation = streamLocation;
|
||||
this.isInsertStream = false;
|
||||
}//BufferedOutputStream()//
|
||||
/**
|
||||
* BufferedOutputStream constructor.
|
||||
* @param outputStream The destination for written data.
|
||||
* @param streamLocation The location of this output stream in the context of the parent buffered output stream. This location will be the index of the last reserved byte, or if there are no reserved bytes then it will be the location at which bytes will be inserted into the parent stream.
|
||||
* @param reservedByteCount The initial size of the buffer used for buffering the data when necessary, or if this is a fixed size stream then it will be the number of bytes reserved in the parent stream.
|
||||
*/
|
||||
protected BufferedOutputStream(BufferedOutputStream outputStream, int streamLocation, int reservedByteCount) {
|
||||
super();
|
||||
|
||||
this.outputStream = outputStream;
|
||||
this.streamLocation = streamLocation;
|
||||
this.buffer = null;
|
||||
this.reservedByteCount = reservedByteCount;
|
||||
this.isFixedSize = true;
|
||||
this.isInsertStream = true;
|
||||
}//BufferedOutputStream()//
|
||||
/**
|
||||
* BufferedOutputStream constructor.
|
||||
* @param outputStream The destination for written data.
|
||||
* @param streamLocation The location of this output stream in the context of the parent buffered output stream. This location will be the index of the last reserved byte, or if there are no reserved bytes then it will be the location at which bytes will be inserted into the parent stream.
|
||||
* @param byteCount The initial size of the buffer used for buffering the data when necessary, or if this is a fixed size stream then it will be the number of bytes reserved in the parent stream.
|
||||
* @param isFixedSize Whether the parent stream has reserved a fixed number of bytes allocated to this stream. If it is not fixed size then the user can write as many bytes as desired before closing the stream.
|
||||
*/
|
||||
protected BufferedOutputStream(BufferedOutputStream outputStream, int streamLocation, int bufferSize, int incrementSize) {
|
||||
super();
|
||||
|
||||
this.outputStream = outputStream;
|
||||
this.streamLocation = streamLocation;
|
||||
this.buffer = new byte[bufferSize <= 0 ? DEFAULT_BUFFER_SIZE : bufferSize];
|
||||
this.bufferIncrementSize = incrementSize <= 0 ? DEFAULT_BUFFER_INCREMENT_SIZE : incrementSize;
|
||||
this.isFixedSize = false;
|
||||
this.isInsertStream = true;
|
||||
}//BufferedOutputStream()//
|
||||
/**
|
||||
* BufferedOutputStream constructor.
|
||||
*/
|
||||
public BufferedOutputStream(OutputStream outputStream) {
|
||||
this(outputStream, DEFAULT_BUFFER_SIZE);
|
||||
}//BufferedOutputStream()//
|
||||
/**
|
||||
* BufferedOutputStream constructor.
|
||||
* @param outputStream The destination for written data.
|
||||
* @param bufferSize The initial size of the buffer used for buffering the data when necessary.
|
||||
*/
|
||||
public BufferedOutputStream(OutputStream outputStream, int bufferSize) {
|
||||
super();
|
||||
|
||||
this.outputStream = outputStream;
|
||||
this.buffer = new byte[bufferSize];
|
||||
this.streamLocation = 0;
|
||||
this.isFixedSize = false;
|
||||
this.isInsertStream = false;
|
||||
}//BufferedOutputStream()//
|
||||
/**
|
||||
* Closes the stream and flushes any remaining buffered data.
|
||||
* <p>If this stream is an insertion stream then it will not close the encapsulated (parent) stream because the close only means no more bytes will be inserted.
|
||||
* <p>If this stream is not an insertion stream then the encapsulated stream will be told to close. If for example, this is a buffered output stream encapsulating a FileOutputStream, then the file output stream will receive all buffered data, and then will be told to close.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
|
||||
if(bufferSize > 0) {
|
||||
throw new IOException("Unable to close the buffered output stream because there are open insertion buffer output streams in existance preventing the stream data from flushing to the encapsulated output stream. Please close all related insertion streams before closing this stream.");
|
||||
}//if//
|
||||
|
||||
if(isInsertStream) {
|
||||
if((isFixedSize) && (reservedByteCount != 0)) {
|
||||
throw new IOException("Unable to close the insertion stream because the reserved bytes have not all been filled. Either don't reserve bytes, or you must fill exactly that number of bytes.");
|
||||
}//if//
|
||||
|
||||
isInsertStream = false;
|
||||
}//if//
|
||||
else {
|
||||
//Close the encapsulated output stream.//
|
||||
//TODO: Modify to not set the isInsertStream = false when the stream can no longer insert. Then this can be turned back on.//
|
||||
//TODO: Why is this commented out? We need to notify the underlying stream that it should close.//
|
||||
// outputStream.close();
|
||||
}//else//
|
||||
}//close()//
|
||||
/**
|
||||
* Flushes all or some of the buffer to the stream.
|
||||
* <p>Note: The flush method may only flush bytes that occur earlier than the first insert stream's location because the insert opertion will add or modify bytes and those bytes must stay buffered to allow this.
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if((!isFixedSize) && (buffer != null) && (bufferSize > 0)) {
|
||||
//Remove locations such that the first location in the collection is an insertable BufferedOutputStream object.//
|
||||
while((locations.getSize() > 0) && (!((BufferedOutputStream) locations.getFirst()).isInsertStream())) {
|
||||
locations.remove(0);
|
||||
}//while//
|
||||
|
||||
//Flush the buffer up to the first active BufferedOutputStream's location.//
|
||||
if(locations.getSize() == 0) {
|
||||
if(bufferSize > 0) {
|
||||
if(isInsertStream) {
|
||||
//Insert the bytes into the encapsulated buffered output stream.//
|
||||
((BufferedOutputStream) outputStream).insert(streamLocation, buffer, 0, bufferSize, false);
|
||||
}//if//
|
||||
else {
|
||||
//Append the bytes to the encapsulated output stream.//
|
||||
outputStream.write(buffer, 0, bufferSize);
|
||||
}//else//
|
||||
|
||||
//Update the overall stream location.//
|
||||
//streamLocation += bufferSize; //This is automatically done by the underlying buffered output stream.//
|
||||
//Update the buffer size.//
|
||||
bufferSize = 0;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
BufferedOutputStream location = (BufferedOutputStream) locations.getFirst();
|
||||
int flushableByteCount = location.getByteIndex() - streamLocation;
|
||||
|
||||
//Adjust the number of flushable bytes if the first location has unused reserved bytes.//
|
||||
if(location.getReservedByteCount() > 0) {
|
||||
flushableByteCount -= location.getReservedByteCount();
|
||||
}//if//
|
||||
|
||||
//Flush those bytes that we can.//
|
||||
if(flushableByteCount > 0) {
|
||||
if(isInsertStream) {
|
||||
//Insert the bytes into the encapsulated buffered output stream.//
|
||||
((BufferedOutputStream) outputStream).insert(streamLocation, buffer, 0, flushableByteCount, false);
|
||||
}//if//
|
||||
else {
|
||||
//Append the bytes to the encapsulated output stream.//
|
||||
outputStream.write(buffer, 0, flushableByteCount);
|
||||
}//else//
|
||||
|
||||
//Update the overall stream location.//
|
||||
streamLocation += flushableByteCount;
|
||||
//Update the buffer size.//
|
||||
bufferSize -= flushableByteCount;
|
||||
//Shift remaining buffered bytes so that they begin at the first index in the buffer.//
|
||||
System.arraycopy(buffer, flushableByteCount, buffer, 0, bufferSize);
|
||||
}//if//
|
||||
}//else//
|
||||
}//if//
|
||||
}//flush()//
|
||||
/**
|
||||
* Gets the stream index of the location in the stream when this object was created.
|
||||
* This value will change if there is an update location object that the users writes data to (unless it has reserved space), or if this location is an update location and did not reserve space and writes data.
|
||||
* The location will be the last byte index in the set of values written to the stream, or the index of the stream at the time the location was created (updated if any new bytes were written to the stream at an earlier index).
|
||||
* @return The index within the stream of this location object (or the ending index if the location allows updating).
|
||||
*/
|
||||
public int getByteIndex() {
|
||||
return streamLocation + bufferSize;
|
||||
}//getByteIndex()//
|
||||
/**
|
||||
* Gets an output stream object that allows the user to write a fixed amount of data to the stream at some future time at the current location.
|
||||
* @param reservedByteCount The number of bytes to reserve in the stream. The user must write exactly this many bytes before the stream can be successfully flushed.
|
||||
* @return An IStreamUpdateLocation object that can provide the index within the stream and allows the user to write data to the stream at the current position at some future time.
|
||||
*/
|
||||
public BufferedOutputStream getInsertOutputStream(int reservedByteCount) throws IOException {
|
||||
BufferedOutputStream stream = null;
|
||||
|
||||
if(reservedByteCount > 0) {
|
||||
//Add the reserved bytes to the buffer.//
|
||||
if(bufferSize + reservedByteCount > buffer.length) {
|
||||
resizeBuffer(reservedByteCount);
|
||||
}//if//
|
||||
|
||||
bufferSize += reservedByteCount;
|
||||
}//if//
|
||||
|
||||
//Create an update location.//
|
||||
stream = new BufferedOutputStream(this, streamLocation + bufferSize, reservedByteCount);
|
||||
|
||||
locations.add(stream);
|
||||
|
||||
return stream;
|
||||
}//getInsertOutputStream()//
|
||||
/**
|
||||
* Gets an output stream object that allows the user to write data to the stream at some future time at the current location.
|
||||
* @param initialBufferSize The size of the initial buffer. This value should be large enough to provide efficient writes to the buffered stream, but small enough not to be wasteful.
|
||||
* @param incrementSize The number of bytes to increment the buffer by if it is necessary. The buffer will first try to flush to the buffered stream, and will only increase in size if necessary.
|
||||
* @return An IStreamUpdateLocation object that can provide the index within the stream and allows the user to write data to the stream at the current position at some future time.
|
||||
*/
|
||||
public BufferedOutputStream getInsertOutputStream(int initialBufferSize, int incrementSize) throws IOException {
|
||||
BufferedOutputStream stream = new BufferedOutputStream(this, streamLocation + bufferSize, initialBufferSize, incrementSize);
|
||||
|
||||
locations.add(stream);
|
||||
|
||||
return stream;
|
||||
}//getInsertOutputStream()//
|
||||
/**
|
||||
* Gets the encapsulated output stream.
|
||||
* @return Gets the output stream that this object wrappers.
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}//getOutputStream()//
|
||||
/**
|
||||
* Gets a location object associated with the current location in the stream.
|
||||
* This location object can be used to access the current stream position at the location.
|
||||
* This is useful for the user because the user could also get a dynamic update location which allows the stream to be dynamically modified at some future time.
|
||||
* A location after the dynamic update location would tell the user what the byte index is after the dynamic update location was completed (all bytes written).
|
||||
* @return An IStreamLocation object that can provide the index within the stream. It will be updated automatically if a dynamic update location is used to insert byte earlier in the stream.
|
||||
*/
|
||||
public IOutputStreamLocation getOutputStreamLocation() throws IOException {
|
||||
BufferedOutputStream location = new BufferedOutputStream(streamLocation + bufferSize);
|
||||
|
||||
if(locations.getSize() > 0) {
|
||||
locations.add(location);
|
||||
}//if//
|
||||
|
||||
return location;
|
||||
}//getOutputStreamLocation()//
|
||||
/**
|
||||
* Gets the number of bytes reserved in the encapsulated buffered output stream.
|
||||
* <p>Note: This value is only valid if this stream encapsulates a buffered output stream and is an insert buffer with a fixed number of insertable bytes.
|
||||
* <p>Note: If this value is non-zero then the parent stream may not flush bytes (beyond the reserved bytes in the stream) to its encapsulated output stream. Thus the user must use ALL reserved bytes, no more, no less.
|
||||
* @return The number of reserved bytes. This value goes down as bytes are written, until the value reaches zero. If this value is zero then no more bytes may be written.
|
||||
*/
|
||||
public int getReservedByteCount() {
|
||||
return reservedByteCount;
|
||||
}//getReservedByteCount()//
|
||||
/**
|
||||
* Inserts the specified byte values to the stream.
|
||||
* @param streamIndex The index of the first array byte within the stream (where index zero is the very first byte written to the stream).
|
||||
* @param bytes The array of values to write to the stream.
|
||||
* @param offset The offset of the first value to write to the stream.
|
||||
* @param length The number of values to write to the stream.
|
||||
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
|
||||
*/
|
||||
protected void insert(int streamIndex, byte[] bytes, int offset, int length, boolean isReserved) throws IOException {
|
||||
//If this value is going into a reserved space in the buffer then simply write to the buffer, otherwise we will add it to the insert buffer.//
|
||||
if(isReserved) {
|
||||
System.arraycopy(bytes, offset, buffer, streamIndex - streamLocation, length);
|
||||
}//if//
|
||||
else {
|
||||
int availableSpace = buffer.length - bufferSize;
|
||||
int remainingBytes = length;
|
||||
int bufferInsertLocation = streamIndex - streamLocation;
|
||||
|
||||
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
|
||||
if(availableSpace < remainingBytes) {
|
||||
//Keep writing and flushing as long as there is data and buffer space.//
|
||||
while((availableSpace > 0) && (remainingBytes > 0)) {
|
||||
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
|
||||
|
||||
//Shift the buffered bytes so that there is space for the inserted bytes.//
|
||||
if(bufferSize > bufferInsertLocation) {
|
||||
System.arraycopy(buffer, bufferInsertLocation, buffer, copyLength + bufferInsertLocation, bufferSize - bufferInsertLocation);
|
||||
}//if//
|
||||
|
||||
//Copy the data into the correct place in the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, copyLength);
|
||||
bufferSize += copyLength;
|
||||
remainingBytes -= copyLength;
|
||||
offset += copyLength;
|
||||
|
||||
if(remainingBytes > 0) {
|
||||
flush();
|
||||
//Recompute the location to insert the remaining bytes.//
|
||||
bufferInsertLocation = streamIndex - streamLocation + offset;
|
||||
//Recompute the amount of available space in the buffer.//
|
||||
availableSpace = buffer.length - bufferSize;
|
||||
|
||||
//Make sure we are not being grossly inefficient by ensuring that we at least flush some substantial number of bytes each round.//
|
||||
if(availableSpace < bufferIncrementSize) {
|
||||
resizeBuffer(bufferIncrementSize);
|
||||
availableSpace = buffer.length - bufferSize;
|
||||
}//if//
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
//If we must, then resize the buffer to accomidate the data.//
|
||||
if((availableSpace == 0) && (remainingBytes > 0)) {
|
||||
//Resize the buffer so it can contain the new data.//
|
||||
resizeBuffer(remainingBytes);
|
||||
|
||||
//Shift the buffered bytes so that there is space for the inserted bytes.//
|
||||
if(bufferSize > bufferInsertLocation) {
|
||||
System.arraycopy(buffer, bufferInsertLocation, buffer, remainingBytes + bufferInsertLocation, bufferSize - bufferInsertLocation);
|
||||
}//if//
|
||||
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, remainingBytes);
|
||||
//Update the buffer size.//
|
||||
bufferSize += remainingBytes;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Shift the buffered bytes so that there is space for the inserted bytes.//
|
||||
if(bufferSize > bufferInsertLocation) {
|
||||
System.arraycopy(buffer, bufferInsertLocation, buffer, bufferInsertLocation + length, bufferSize - bufferInsertLocation);
|
||||
}//if//
|
||||
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, length);
|
||||
//Update the buffer size.//
|
||||
bufferSize += length;
|
||||
}//else//
|
||||
/* The code above replaces this code - it provides better buffer usage.
|
||||
int bufferInsertLocation = streamIndex - streamLocation;
|
||||
|
||||
//Resize the buffer if necessary.//
|
||||
if(length + bufferSize > buffer.length) {
|
||||
resizeBuffer(length);
|
||||
}//if//
|
||||
|
||||
//Shift the buffered bytes so that there is space for the inserted bytes.//
|
||||
if(bufferSize > bufferInsertLocation) {
|
||||
System.arraycopy(buffer, bufferInsertLocation, buffer, length + bufferInsertLocation, bufferSize - bufferInsertLocation);
|
||||
}//if//
|
||||
|
||||
//Copy the inserted bytes.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, length);
|
||||
*/
|
||||
|
||||
//Notify the location objects that their positions may have changed.//
|
||||
updateLocations(streamIndex, length);
|
||||
}//else//
|
||||
}//insert()//
|
||||
/**
|
||||
* Inserts the specified byte values to the stream.
|
||||
* @param streamIndex The index of the first array byte within the stream (where index zero is the very first byte written to the stream).
|
||||
* @param bytes The array of values to write to the stream.
|
||||
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
|
||||
*/
|
||||
protected void insert(int streamIndex, byte[] bytes, boolean isReserved) throws IOException {
|
||||
insert(streamIndex, bytes, 0, bytes.length, isReserved);
|
||||
}//insert()//
|
||||
/**
|
||||
* Inserts the specified unsigned byte value to the stream.
|
||||
* @param streamIndex The index of the byte within the stream (where index zero is the very first byte written to the stream).
|
||||
* @param b The unsigned byte value to write to the stream.
|
||||
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
|
||||
*/
|
||||
protected void insert(int streamIndex, int b, boolean isReserved) throws IOException {
|
||||
//If this value is going into a reserved space in the buffer then simply write to the buffer, otherwise we will add it to the insert buffer.//
|
||||
if(isReserved) {
|
||||
buffer[streamIndex - streamLocation] = (byte) b;
|
||||
}//if//
|
||||
else {
|
||||
Debug.halt(); //Should not occur.//
|
||||
}//else//
|
||||
}//insert()//
|
||||
/**
|
||||
* Determines whether this stream is performing an insert of bytes into another BufferedOutputStream object.
|
||||
* @return Whether this stream is inserting into another stream.
|
||||
*/
|
||||
protected boolean isInsertStream() {
|
||||
return isInsertStream;
|
||||
}//isInsertStream()//
|
||||
/**
|
||||
* Shifts the location of the buffered output stream.
|
||||
* <p>This will occur if this stream is either a simple marker, or an insertable stream into the encapsulated buffered output stream.
|
||||
* The encapsulated buffered output stream will call this method if another insertable stream inserts some data into the stream at an earlier stream location.
|
||||
* @param offset The number of bytes to move the location forward (higher or later in the stream).
|
||||
*/
|
||||
protected void moveLocation(int offset) {
|
||||
streamLocation += offset;
|
||||
}//moveLocation()//
|
||||
/**
|
||||
* Resizes the buffer so that it can contain <code>count</code> more bytes (at a minimum).
|
||||
* @param count The number of bytes the user expects to add immediatly.
|
||||
*/
|
||||
protected void resizeBuffer(int count) throws IOException {
|
||||
byte[] tempBuffer = new byte[buffer.length + (count > bufferIncrementSize ? count + bufferIncrementSize : bufferIncrementSize)];
|
||||
|
||||
System.arraycopy(buffer, 0, tempBuffer, 0, buffer.length);
|
||||
buffer = tempBuffer;
|
||||
}//resizeBuffer()//
|
||||
/**
|
||||
* Copies the contents of the stream's buffer into a new byte array.
|
||||
* @return A byte array containing all of the bytes written to this stream.
|
||||
*/
|
||||
public byte[] toByteArray() throws IOException {
|
||||
byte[] bytes = null;
|
||||
|
||||
flush();
|
||||
|
||||
if(outputStream instanceof java.io.ByteArrayOutputStream) {
|
||||
bytes = ((java.io.ByteArrayOutputStream) outputStream).toByteArray();
|
||||
}//if//
|
||||
else if(outputStream instanceof ByteArrayOutputStream) {
|
||||
bytes = ((ByteArrayOutputStream) outputStream).toByteArray();
|
||||
}//else if//
|
||||
else if(outputStream instanceof BufferedOutputStream) {
|
||||
bytes = ((BufferedOutputStream) outputStream).toByteArray();
|
||||
}//else if//
|
||||
else {
|
||||
throw new com.common.exception.MethodNotSupportedException("toByteArray() not supported except for java.io.ByteArrayOutputStream and com.common.io.ByteArrayOutputStream");
|
||||
}//else//
|
||||
|
||||
return bytes;
|
||||
}//toByteArray()//
|
||||
/**
|
||||
* Updates the location objects after bytes were inserted into the stream.
|
||||
* @param byteIndex The stream byte index that the bytes were inserted at.
|
||||
* @param insertedByteCount The number of bytes inserted.
|
||||
*/
|
||||
protected void updateLocations(int byteIndex, int insertedByteCount) {
|
||||
IIterator iterator = locations.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
BufferedOutputStream location = (BufferedOutputStream) iterator.next();
|
||||
|
||||
if(((location.isFixedSize) && ((location.getByteIndex() - location.reservedByteCount) >= byteIndex)) || ((!location.isFixedSize) && (location.getByteIndex() >= byteIndex))) {
|
||||
location.moveLocation(insertedByteCount);
|
||||
}//if//
|
||||
}//while//
|
||||
}//updateLocations()//
|
||||
/**
|
||||
* Writes the specified byte values to the stream.
|
||||
* @param bytes The array of values to write to the stream.
|
||||
*/
|
||||
public void write(byte[] bytes) throws IOException {
|
||||
if((isInsertStream) && (isFixedSize)) {
|
||||
if(bytes.length > reservedByteCount) {
|
||||
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
|
||||
}//if//
|
||||
|
||||
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
|
||||
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, bytes, isFixedSize);
|
||||
//Update the count of reserved bytes.//
|
||||
reservedByteCount -= bytes.length;
|
||||
|
||||
if(reservedByteCount == 0) {
|
||||
close();
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
int offset = 0;
|
||||
int availableSpace = buffer.length - bufferSize;
|
||||
int remainingBytes = bytes.length;
|
||||
|
||||
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
|
||||
if(availableSpace < remainingBytes) {
|
||||
//Keep writing and flushing as long as there is data and buffer space.//
|
||||
while((availableSpace > 0) && (remainingBytes > 0)) {
|
||||
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
|
||||
|
||||
System.arraycopy(bytes, offset, buffer, bufferSize, copyLength);
|
||||
bufferSize += copyLength;
|
||||
remainingBytes -= copyLength;
|
||||
offset += copyLength;
|
||||
|
||||
if(remainingBytes > 0) {
|
||||
flush();
|
||||
availableSpace = buffer.length - bufferSize;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
//If we must, then resize the buffer to accomidate the data.//
|
||||
if((availableSpace == 0) && (remainingBytes > 0)) {
|
||||
//Resize the buffer so it can contain the new data.//
|
||||
resizeBuffer(remainingBytes);
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferSize, remainingBytes);
|
||||
//Update the buffer size.//
|
||||
bufferSize += remainingBytes;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, 0, buffer, bufferSize, bytes.length);
|
||||
//Update the buffer size.//
|
||||
bufferSize += bytes.length;
|
||||
}//else//
|
||||
}//else//
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the specified byte values to the stream.
|
||||
* @param bytes The array of values to write to the stream.
|
||||
* @param offset The offset of the first value to write to the stream.
|
||||
* @param length The number of values to write to the stream.
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws IOException {
|
||||
if((isInsertStream) && (isFixedSize)) {
|
||||
if(length > reservedByteCount) {
|
||||
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
|
||||
}//if//
|
||||
|
||||
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
|
||||
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, bytes, offset, length, isFixedSize);
|
||||
//Update the count of reserved bytes.//
|
||||
reservedByteCount -= length;
|
||||
|
||||
if(reservedByteCount == 0) {
|
||||
close();
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
int availableSpace = buffer.length - bufferSize;
|
||||
int remainingBytes = length;
|
||||
|
||||
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
|
||||
if(availableSpace < remainingBytes) {
|
||||
//Keep writing and flushing as long as there is data and buffer space.//
|
||||
while((availableSpace > 0) && (remainingBytes > 0)) {
|
||||
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
|
||||
|
||||
System.arraycopy(bytes, offset, buffer, bufferSize, copyLength);
|
||||
bufferSize += copyLength;
|
||||
remainingBytes -= copyLength;
|
||||
offset += copyLength;
|
||||
|
||||
if(remainingBytes > 0) {
|
||||
flush();
|
||||
availableSpace = buffer.length - bufferSize;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
//If we must, then resize the buffer to accomidate the data.//
|
||||
if((availableSpace == 0) && (remainingBytes > 0)) {
|
||||
//Resize the buffer so it can contain the new data.//
|
||||
resizeBuffer(remainingBytes);
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferSize, remainingBytes);
|
||||
//Update the buffer size.//
|
||||
bufferSize += remainingBytes;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Copy the bytes into the buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, bufferSize, length);
|
||||
//Update the buffer size.//
|
||||
bufferSize += length;
|
||||
}//else//
|
||||
}//else//
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the specified unsigned byte value to the stream.
|
||||
* @param b The unsigned byte value to write to the stream.
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
if((isInsertStream) && (isFixedSize)) {
|
||||
if(reservedByteCount == 0) {
|
||||
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
|
||||
}//if//
|
||||
|
||||
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
|
||||
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, b, isFixedSize);
|
||||
//Update the count of reserved bytes.//
|
||||
reservedByteCount--;
|
||||
|
||||
if(reservedByteCount == 0) {
|
||||
close();
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//If there is not enough room in the buffer then try to flush it, and if still no room then resize it.//
|
||||
if(bufferSize == buffer.length) {
|
||||
flush();
|
||||
|
||||
if(bufferSize == buffer.length) {
|
||||
resizeBuffer(1);
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//Write the byte to the buffer.//
|
||||
buffer[bufferSize++] = (byte) b;
|
||||
}//else//
|
||||
}//write()//
|
||||
}//BufferedOutputStream//
|
||||
328
Common/src/com/common/io/ByteArrayInputStream.java
Normal file
328
Common/src/com/common/io/ByteArrayInputStream.java
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A simple stream that reads bytes from a byte array.
|
||||
* This stream is capable of decrypting the bytes as they are read.
|
||||
*/
|
||||
public class ByteArrayInputStream extends java.io.InputStream implements IInputStream {
|
||||
/** The default initial size of the buffer. */
|
||||
private static final int DEFAULT_SIZE = 1001;
|
||||
|
||||
private byte[] buffer;
|
||||
private int position;
|
||||
private int count;
|
||||
private int expectedSize;
|
||||
//private boolean reuseBuffer;
|
||||
private int originalPosition = 0;
|
||||
private int originalCount = 0;
|
||||
/**
|
||||
* Creates the byte array input stream with a buffer containing source data.
|
||||
* @param buffer A buffer containing the source data for this stream.
|
||||
*/
|
||||
public ByteArrayInputStream(byte[] buffer) {
|
||||
this(buffer, 0, (buffer != null ? buffer.length : 0));
|
||||
}//ByteArrayInputStream()//
|
||||
/**
|
||||
* Creates the byte array input stream with a buffer containing source data.
|
||||
* @param buffer A buffer containing the source data for this stream.
|
||||
* @param offset The offset of the first byte of source data in the buffer.
|
||||
* @param length The number of bytes of source data in the buffer.
|
||||
*/
|
||||
public ByteArrayInputStream(byte[] buffer, int offset, int length) {
|
||||
//this.reuseBuffer = false;
|
||||
this.expectedSize = DEFAULT_SIZE;
|
||||
internalSetBuffer(buffer, offset, length);
|
||||
}//ByteArrayInputStream()//
|
||||
/**
|
||||
* Creates the byte array input stream with the estimated number of source bytes to be put in the stream.
|
||||
* @param expectedSize The number of bytes the user expects will be in this stream.
|
||||
*/
|
||||
public ByteArrayInputStream(int expectedSize) {
|
||||
//this.reuseBuffer = true;
|
||||
this.expectedSize = expectedSize;
|
||||
this.buffer = null;
|
||||
this.position = 0;
|
||||
this.count = 0;
|
||||
}//ByteArrayInputStream()//
|
||||
/**
|
||||
* Gets the current position in the stream.
|
||||
* @return The current position.
|
||||
*/
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}//getPosition()//
|
||||
/**
|
||||
* Sets the current position in the stream.
|
||||
* @param position The current position.
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}//setPosition()//
|
||||
/**
|
||||
* Gets the number of available bytes in the input stream.
|
||||
* @return The number of bytes that have not yet been read from the input stream.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return count - position;
|
||||
}//available()//
|
||||
/**
|
||||
* @see IInputStream.canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return false;
|
||||
}//canDecrypt()//
|
||||
/**
|
||||
* @see IInputStream.canReadFrom()
|
||||
*/
|
||||
public boolean canReadFrom() {
|
||||
return true;
|
||||
}//canReadFrom()//
|
||||
/**
|
||||
* Closes the stream and releases all held resources.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
internalRelease();
|
||||
}//close()//
|
||||
/**
|
||||
* Switches decryption of the stream off and on.
|
||||
* Nothing will occur if no symmetric algorithm was provided to the stream.
|
||||
* The stream does maintain a decryption count which is incremented when decryption is turned on and only stops the decrypting when this count reaches zero.
|
||||
* Since data written to the ByteArrayOutputStream is never double encrypted, the data read will also not be double decrypted.
|
||||
* @param decrypt Whether to turn decryption on (<code>true</code>) or off (<code>false</code>).
|
||||
* @see IInputStream.decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws java.io.IOException {
|
||||
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Makes sure the buffer is large enough to hold <code>size</code> bytes in addition to any bytes already held.
|
||||
* @param size The number of new bytes the buffer must be able to hold.
|
||||
*/
|
||||
protected void ensureSpace(int size) {
|
||||
byte[] oldBuffer = buffer;
|
||||
|
||||
if(oldBuffer == null) {
|
||||
buffer = new byte[expectedSize < size ? size + 50 : expectedSize];
|
||||
}//if//
|
||||
else if(oldBuffer.length - count < size) {
|
||||
byte[] newBuffer = new byte[oldBuffer.length + size + 50];
|
||||
|
||||
System.arraycopy(oldBuffer, 0, newBuffer, 0, count);
|
||||
buffer = newBuffer;
|
||||
}//else if//
|
||||
}//ensureSpace()//
|
||||
/**
|
||||
* Will release any held resources.
|
||||
*/
|
||||
public void finalize() {
|
||||
//Release the stream resources.//
|
||||
internalRelease();
|
||||
}//finalize()//
|
||||
/**
|
||||
* Initializes the stream with the given source material.
|
||||
* @param buffer The new byte array buffer to use for source bytes.
|
||||
*/
|
||||
public void initialize(byte[] buffer) {
|
||||
if(buffer != null) {
|
||||
internalInitialize(buffer, 0, buffer.length);
|
||||
}//if//
|
||||
else {
|
||||
throw new com.common.exception.InvalidArgumentException("Must supply a valid buffer.");
|
||||
}//else//
|
||||
}//initialize()//
|
||||
/**
|
||||
* Initializes the stream with the given source material.
|
||||
* @param buffer The new byte array buffer to use for source bytes.
|
||||
* @param offset The offset in the buffer where the first source byte can be found.
|
||||
* @param length The number of source bytes available in the supplied buffer.
|
||||
*/
|
||||
public void initialize(byte[] buffer, int offset, int length) {
|
||||
internalInitialize(buffer, offset, length);
|
||||
}//initialize()//
|
||||
/**
|
||||
* Initializes the stream with the given source material.
|
||||
* @param buffer The new byte array buffer to use for source bytes.
|
||||
* @param offset The offset in the buffer where the first source byte can be found.
|
||||
* @param length The number of source bytes available in the supplied buffer.
|
||||
*/
|
||||
private void internalInitialize(byte[] buffer, int offset, int length) {
|
||||
//Cleanup in case this stream is being reused.//
|
||||
internalRelease();
|
||||
//The buffer is not reusable.//
|
||||
//reuseBuffer = false;
|
||||
//Initialize the stream with the new source material.//
|
||||
internalSetBuffer(buffer, offset, length);
|
||||
}//internalInitialize()//
|
||||
/**
|
||||
* Releases the held resources and resets the stream indexes.
|
||||
* This is useful if the stream will be reused, if the buffers are reuseable, or to assist GC.
|
||||
*/
|
||||
private void internalRelease() {
|
||||
//Clean the stream.//
|
||||
buffer = null;
|
||||
originalPosition = 0;
|
||||
originalCount = 0;
|
||||
position = 0;
|
||||
count = 0;
|
||||
}//internalRelease()//
|
||||
/**
|
||||
* Resets the stream so that it may be re-read.
|
||||
*/
|
||||
private void internalReset() {
|
||||
//Reset the position and count to the original values.//
|
||||
position = originalPosition;
|
||||
count = originalCount;
|
||||
}//internalReset()//
|
||||
/**
|
||||
* Sets the buffer to be used by this stream as a source of bytes.
|
||||
* @param buffer The new byte array buffer to use for source bytes.
|
||||
* @param offset The offset in the buffer where the first source byte can be found.
|
||||
* @param length The number of source bytes available in the supplied buffer.
|
||||
*/
|
||||
protected void internalSetBuffer(byte[] buffer, int offset, int length) {
|
||||
//Set the position variables.//
|
||||
this.originalPosition = offset;
|
||||
this.originalCount = length + offset;
|
||||
this.buffer = buffer;
|
||||
this.position = offset;
|
||||
this.count = length + offset;
|
||||
}//internalSetBuffer()//
|
||||
/**
|
||||
* Gets the underlying buffer used by the input stream.
|
||||
* @return The underlying buffer.
|
||||
*/
|
||||
public byte[] getBuffer() {
|
||||
return buffer;
|
||||
}//getBuffer()//
|
||||
/**
|
||||
* @see IInputStream.isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return false;
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Gets the next byte from the stream without actually incrementing the stream.
|
||||
* @return The next byte in the stream.
|
||||
*/
|
||||
public byte peek() throws IOException {
|
||||
return peek(1);
|
||||
}//peek()//
|
||||
/**
|
||||
* Gets the byte from the stream at the requested offset without actually incrementing the stream.
|
||||
* @param offset The offset from the current location in the stream. This value must be positive and should not exceed the number of bytes left in the stream.
|
||||
* @return The byte found at the specified offset.
|
||||
*/
|
||||
public byte peek(int offset) throws IOException {
|
||||
if((position + offset < count) && (position + offset >= 0)) {
|
||||
return buffer[position + offset];
|
||||
}//if//
|
||||
|
||||
throw new IOException("Invalid offset.");
|
||||
}//peek()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
return position < count ? buffer[position++] & 0xFF : -1;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||
int newPosition = position + length;
|
||||
|
||||
//Check to see if there are any bytes available.//
|
||||
if(position < count) {
|
||||
//Update the number of requested bytes if there are not enough available.//
|
||||
if(newPosition > count) {
|
||||
length = count - position;
|
||||
newPosition = position + length;
|
||||
}//if//
|
||||
|
||||
//Copy the bytes from this stream to the buffer.//
|
||||
System.arraycopy(buffer, position, bytes, offset, length);
|
||||
//Update the stream position.//
|
||||
position = newPosition;
|
||||
}//if//
|
||||
else {
|
||||
//Note: I changed this to -1 to comply with the java.io.InputStream#read(byte[], int, int) commenting. This may cause problems with existing code that uses this class.//
|
||||
length = -1;
|
||||
}//else//
|
||||
|
||||
//Return the number of bytes pulled off the stream.//
|
||||
return length;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int newPosition = position + length;
|
||||
|
||||
//Check to see if there are any bytes available.//
|
||||
if(position < count) {
|
||||
//Update the number of requested bytes if there are not enough available.//
|
||||
if(newPosition > count) {
|
||||
length = count - position;
|
||||
newPosition = position + length;
|
||||
}//if//
|
||||
|
||||
//Copy the bytes from this stream to the output stream.//
|
||||
out.write(buffer, position, length);
|
||||
//Update the stream position.//
|
||||
position = newPosition;
|
||||
}//if//
|
||||
else {
|
||||
length = 0;
|
||||
}//else//
|
||||
|
||||
//Return the number of bytes pulled off the stream.//
|
||||
return length;
|
||||
}//read()//
|
||||
/**
|
||||
* Replaces the buffered data in this input stream with the bytes from the given input stream.
|
||||
* @param in The input stream containing the data to be buffered by this input stream.
|
||||
* @param numberOfBytes The number of bytes to be read.
|
||||
* @throws IOException If there are not enough bytes on the given input stream.
|
||||
*/
|
||||
public void readFrom(InputStream in, int numberOfBytes) throws IOException {
|
||||
int totalNumberOfBytes = numberOfBytes + count;
|
||||
int bytesRead;
|
||||
|
||||
//Ensure the length of the buffer.//
|
||||
ensureSpace(numberOfBytes);
|
||||
|
||||
//Read the bytes off the stream.//
|
||||
while(count != totalNumberOfBytes) {
|
||||
bytesRead = in.read(buffer, count, totalNumberOfBytes - count);
|
||||
|
||||
if(bytesRead == -1) {
|
||||
throw new IOException();
|
||||
}//if//
|
||||
|
||||
count += bytesRead;
|
||||
originalCount += bytesRead;
|
||||
}//while//
|
||||
}//readFrom()//
|
||||
/**
|
||||
* Releases the stream resources and resets the stream so that the object may be GC'd or reused.
|
||||
* This stream will no longer be re-readable.
|
||||
*/
|
||||
public void release() {
|
||||
internalRelease();
|
||||
}//release()//
|
||||
/**
|
||||
* Resets the stream so that it may be re-read.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
internalReset();
|
||||
}//reset()//
|
||||
}//ByteArrayInputStream//
|
||||
307
Common/src/com/common/io/ByteArrayOutputStream.java
Normal file
307
Common/src/com/common/io/ByteArrayOutputStream.java
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.common.security.*;
|
||||
|
||||
/**
|
||||
* A simple stream that writes bytes to a byte array.
|
||||
* This stream is capable of encrypting the bytes as they are written.
|
||||
*/
|
||||
public class ByteArrayOutputStream extends OutputStream implements IOutputStream {
|
||||
private byte[] buffer;
|
||||
protected int index;
|
||||
private int optimalSize = 0;
|
||||
//private boolean reuseBuffer;
|
||||
/**
|
||||
* ByteArrayOutputStream constructor.
|
||||
* @param optimalSize The estimated number of bytes that will be written to the stream.
|
||||
* @param reuseBuffer Whether the resources should be reused.
|
||||
*/
|
||||
public ByteArrayOutputStream(int optimalSize, boolean reuseBuffer) {
|
||||
//this.reuseBuffer = reuseBuffer;
|
||||
this.optimalSize = optimalSize;
|
||||
this.buffer = null;
|
||||
this.index = 0;
|
||||
}//ByteArrayOutputStream()//
|
||||
/**
|
||||
* @see IOutputStream.canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return true;
|
||||
}//canEncrypt()//
|
||||
/**
|
||||
* @see IOutputStream.canEncrypt()
|
||||
*/
|
||||
public boolean canGetSize() {
|
||||
return true;
|
||||
}//canGetSize()//
|
||||
/**
|
||||
* @see IOutputStream.canReset()
|
||||
*/
|
||||
public boolean canReset() {
|
||||
return true;
|
||||
}//canReset()//
|
||||
/**
|
||||
* @see IOutputStream.canWriteTo()
|
||||
*/
|
||||
public boolean canWriteTo() {
|
||||
return true;
|
||||
}//canWriteTo()//
|
||||
/**
|
||||
* Closes the stream and releases all held resources.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
internalRelease();
|
||||
}//close()//
|
||||
/**
|
||||
* Switches encryption of the stream off and on.
|
||||
* Nothing will occur if no symmetric algorithm was provided to the stream.
|
||||
* The stream does maintain an encryption count which is incremented when encryption is turned on and only stops the encrypting when this count reaches zero.
|
||||
* Since data written to the ByteArrayOutputStream is never double encrypted, the data read will also not be double decrypted.
|
||||
* @param encrypt Whether to turn encryption on (<code>true</code>) or off (<code>false</code>).
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws java.io.IOException {
|
||||
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Makes sure there is enough space available to write <code>size</code> bytes to the stream.
|
||||
* @param size The number of bytes of space that should be available.
|
||||
*/
|
||||
protected void ensureSpace(int size) {
|
||||
byte[] oldBuffer = buffer;
|
||||
|
||||
if(oldBuffer == null) {
|
||||
buffer = new byte[optimalSize < size ? size + 100 : optimalSize];
|
||||
}//if//
|
||||
else if(oldBuffer.length - index < size) {
|
||||
byte[] newBuffer = new byte[oldBuffer.length + size + 100];
|
||||
|
||||
System.arraycopy(oldBuffer, 0, newBuffer, 0, index);
|
||||
buffer = newBuffer;
|
||||
}//else if//
|
||||
}//ensureSpace()//
|
||||
/**
|
||||
* Will release any held resources.
|
||||
*/
|
||||
public void finalize() throws Throwable {
|
||||
internalRelease();
|
||||
}//finalize()//
|
||||
/**
|
||||
* Gets the buffer used by this stream.
|
||||
* @return The buffer used by the stream for storing bytes written.
|
||||
*/
|
||||
public byte[] getBuffer() {
|
||||
return buffer;
|
||||
}//getBuffer()//
|
||||
/**
|
||||
* Sets the buffer used by this stream.
|
||||
* @param buffer The buffer used by the stream for storing bytes written.
|
||||
*/
|
||||
protected void setBuffer(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
}//setBuffer()//
|
||||
/**
|
||||
* Gets the number of bytes in the stream (including reserved or inset bytes if there are any).
|
||||
* @return The number of bytes in the stream.
|
||||
*/
|
||||
public int getSize() {
|
||||
return index;
|
||||
}//getSize()//
|
||||
/**
|
||||
* Initializes the stream with a new buffer.
|
||||
*/
|
||||
public void initialize(int insetSize, ISymmetricAlgorithm symmetricAlgorithm) {
|
||||
internalInitialize(insetSize, symmetricAlgorithm);
|
||||
}//initialize()//
|
||||
/**
|
||||
* Initializes the stream with a new buffer.
|
||||
*/
|
||||
protected void internalInitialize(int insetSize, ISymmetricAlgorithm symmetricAlgorithm) {
|
||||
//Make sure we are clean.//
|
||||
internalRelease();
|
||||
//Get a new buffer.//
|
||||
internalSetBuffer(new byte[optimalSize]);
|
||||
//Set the current index.//
|
||||
this.index = insetSize;
|
||||
}//internalInitialize()//
|
||||
/**
|
||||
* Resets the stream and releases any held resources.
|
||||
*/
|
||||
private void internalRelease() {
|
||||
buffer = null;
|
||||
index = 0;
|
||||
}//internalRelease()//
|
||||
/**
|
||||
* Resets the stream so it may be reused.
|
||||
*/
|
||||
private void internalReset() {
|
||||
index = 0;
|
||||
}//internalReset()//
|
||||
/**
|
||||
* Sets the stream's buffer.
|
||||
* @param buffer The byte array buffer to be used by this stream.
|
||||
*/
|
||||
private void internalSetBuffer(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
}//internalSetBuffer()//
|
||||
/**
|
||||
* @see IOutputStream.isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return false;
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Will add padding to the stream up to the given index within the stream.
|
||||
* <p>NOTE: The purpose of this method is to get around timing problems in win95/98 where streams of a size less than 255 bytes causes 150ms delays in reading from the stream.
|
||||
* @param index The index (position) within the stream to pad to.
|
||||
*/
|
||||
public void padTo(int index) throws IOException {
|
||||
int paddingSize = index - this.index;
|
||||
|
||||
//Write zeros to the stream for padding.//
|
||||
if(paddingSize > 0) {
|
||||
while(paddingSize != 0) {
|
||||
write(0);
|
||||
paddingSize--;
|
||||
}//while//
|
||||
}//if//
|
||||
}//padTo()//
|
||||
/**
|
||||
* Adds padding to the stream.
|
||||
* @param size The number of padding bytes to be written to the stream.
|
||||
*/
|
||||
public void pad(int size) throws IOException {
|
||||
//Write zeros to the stream for padding.//
|
||||
if(size > 0) {
|
||||
while(size != 0) {
|
||||
write(0);
|
||||
size--;
|
||||
}//while//
|
||||
}//if//
|
||||
}//pad()//
|
||||
/**
|
||||
* Resets the stream so that it may be reused.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
internalReset();
|
||||
}//reset()//
|
||||
/**
|
||||
* Gets the current position in the output stream.
|
||||
* @return The current stream position. Same as calling getSize().
|
||||
*/
|
||||
public int getPosition() {
|
||||
return index;
|
||||
}//getPosition()//
|
||||
/**
|
||||
* Sets the stream position for writing.
|
||||
* @param position The position of the stream. This will change the size of the stream.
|
||||
*/
|
||||
public void setPosition(int position) {
|
||||
if(position > buffer.length) {
|
||||
ensureSpace(position - index);
|
||||
}//if//
|
||||
|
||||
index = position;
|
||||
}//setPosition()//
|
||||
/**
|
||||
* Copies the contents of the stream's buffer into a new byte array.
|
||||
* @return A byte array containing all of the bytes written to this stream.
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] newbuffer = new byte[index];
|
||||
|
||||
if(buffer != null) {
|
||||
System.arraycopy(buffer, 0, newbuffer, 0, index);
|
||||
}//if//
|
||||
|
||||
return newbuffer;
|
||||
}//toByteArray()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
*/
|
||||
public void write(ByteBuffer bytes) throws java.io.IOException {
|
||||
int count = bytes.remaining();
|
||||
|
||||
//Make sure there is enough space.//
|
||||
ensureSpace(count);
|
||||
//Copy the bytes to the stream buffer.//
|
||||
bytes.get(buffer, index, count);
|
||||
//Update the index.//
|
||||
index += count;
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
* @param length The number of bytes to write to this stream.
|
||||
*/
|
||||
public void write(ByteBuffer bytes, int count) throws java.io.IOException {
|
||||
//Make sure there is enough space.//
|
||||
ensureSpace(count);
|
||||
//Copy the bytes to the stream buffer.//
|
||||
bytes.get(buffer, index, count);
|
||||
//Update the index.//
|
||||
index += count;
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
*/
|
||||
public void write(byte[] bytes) throws java.io.IOException {
|
||||
//Make sure there is enough space.//
|
||||
ensureSpace(bytes.length);
|
||||
//Copy the bytes to the stream buffer.//
|
||||
System.arraycopy(bytes, 0, buffer, index, bytes.length);
|
||||
//Update the index.//
|
||||
index += bytes.length;
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
* @param offset The offset of the first byte to write.
|
||||
* @param length The number of bytes to write to this stream.
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws java.io.IOException {
|
||||
//Make sure there is enough space.//
|
||||
ensureSpace(length);
|
||||
//Copy the bytes to the stream buffer.//
|
||||
System.arraycopy(bytes, offset, buffer, index, length);
|
||||
//Update the index.//
|
||||
index += length;
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the specified byte to this stream.
|
||||
* @param b The byte to append to this stream.
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
//Make sure there is enough space.//
|
||||
ensureSpace(1);
|
||||
//Append the new byte to the end of the buffer.//
|
||||
buffer[index] = (byte) b;
|
||||
//Adjust the count of bytes in the buffer.//
|
||||
index++;
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the contents of the stream buffer to the given output stream.
|
||||
* @param out The output stream to write the data to.
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
out.write(buffer, 0, index);
|
||||
}//writeTo()//
|
||||
/**
|
||||
* Writes the contents of the stream buffer to the given byte buffer.
|
||||
* @param out The output stream to write the data to.
|
||||
*/
|
||||
public void writeTo(ByteBuffer buffer) throws IOException {
|
||||
buffer.put(this.buffer, 0, index);
|
||||
}//writeTo()//
|
||||
}//ByteArrayOutputStream//
|
||||
204
Common/src/com/common/io/CompressionInputStream.java
Normal file
204
Common/src/com/common/io/CompressionInputStream.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.*;
|
||||
import com.common.debug.*;
|
||||
|
||||
public class CompressionInputStream extends InputStream implements IInputStream {
|
||||
public static final int DEFAULT_BUFFER_SIZE = 301;
|
||||
|
||||
protected InputStream stream = null;
|
||||
protected Inflater inflater = null;
|
||||
protected byte[] internalBuffer = null;
|
||||
protected byte[] bufferOfOne = new byte[1];
|
||||
/**
|
||||
* CompressionInputStream constructor.
|
||||
* @param stream The stream that will provide input to this compression stream.
|
||||
*/
|
||||
public CompressionInputStream(InputStream stream) {
|
||||
this(stream, new Inflater(true), DEFAULT_BUFFER_SIZE);
|
||||
}//CompressionInputStream()//
|
||||
/**
|
||||
* CompressionInputStream constructor.
|
||||
* @param stream The stream that will provide input to this compression stream.
|
||||
* @param inflater The inflater to be used to inflate the input data.
|
||||
*/
|
||||
public CompressionInputStream(InputStream stream, Inflater inflater) {
|
||||
this(stream, inflater, DEFAULT_BUFFER_SIZE);
|
||||
}//CompressionInputStream()//
|
||||
/**
|
||||
* CompressionInputStream constructor.
|
||||
* @param stream The stream that will provide input to this compression stream.
|
||||
* @param inflater The inflater to be used to inflate the input data.
|
||||
* @param bufferSize The size of the internal buffer used to shuttle data from the underlying stream through the inflater.
|
||||
*/
|
||||
public CompressionInputStream(InputStream stream, Inflater inflater, int bufferSize) {
|
||||
//Validate the inputs.//
|
||||
if(bufferSize < 1) {
|
||||
throw new IllegalArgumentException("Buffer size must be greater than zero.");
|
||||
}//if//
|
||||
else if(stream == null) {
|
||||
throw new IllegalArgumentException("A non-null input stream must be provided.");
|
||||
}//else if//
|
||||
else if(inflater == null) {
|
||||
inflater = new Inflater(true);
|
||||
}//else if//
|
||||
|
||||
this.stream = stream;
|
||||
this.inflater = inflater;
|
||||
this.internalBuffer = new byte[bufferSize];
|
||||
}//CompressionInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see IInputStream#canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).canDecrypt());
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see IInputStream#decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
if(stream instanceof IInputStream) {
|
||||
if(((IInputStream) stream).canDecrypt()) {
|
||||
((IInputStream) stream).decrypt(decrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//decrypt()//
|
||||
/**
|
||||
* Inflates the next section of compressed data.
|
||||
* @return Whether there was a next section to be decompressed.
|
||||
*/
|
||||
private boolean inflate() throws IOException {
|
||||
int readSize = (int) (StreamSupport.readShort(stream) & 0xFFFF);
|
||||
boolean result = false;
|
||||
|
||||
if((readSize = stream.read(internalBuffer, 0, readSize)) > 0) {
|
||||
inflater.setInput(internalBuffer, 0, readSize);
|
||||
result = true;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//inflate()//
|
||||
/* (non-Javadoc)
|
||||
* @see IInputStream#isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).isDecrypting());
|
||||
}//isDecrypting()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
int result = -2;
|
||||
|
||||
try {
|
||||
while(result == -2) {
|
||||
if(inflater.inflate(bufferOfOne, 0, 1) == 0) {
|
||||
if(inflater.needsDictionary()) {
|
||||
//TODO: Do we need to do anything special if a dictionary is needed?
|
||||
Debug.log(new RuntimeException("Needs dictionary."));
|
||||
result = -1;
|
||||
}//if//
|
||||
else if(inflater.finished()) {
|
||||
result = -1;
|
||||
}//else if//
|
||||
else if(inflater.needsInput()) {
|
||||
//int readSize = length > internalBuffer.length ? internalBuffer.length : length;
|
||||
//int readSize = internalBuffer.length;
|
||||
if(!inflate()) {
|
||||
break;
|
||||
}//if//
|
||||
}//else if//
|
||||
}//if//
|
||||
else {
|
||||
result = bufferOfOne[0] & 0xFF;
|
||||
}//else//
|
||||
}//while//
|
||||
}//try//
|
||||
catch(DataFormatException e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Stream corruption error in decompressing.");
|
||||
}//catch//
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[])
|
||||
*/
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
return read(buffer, 0, buffer.length);
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
int result = 0;
|
||||
|
||||
try {
|
||||
int count = 0;
|
||||
|
||||
while(count != -1 && length > 0) {
|
||||
if((count = inflater.inflate(buffer, offset, length)) == 0) {
|
||||
if(inflater.needsDictionary()) {
|
||||
//TODO: Do we need to do anything special if a dictionary is needed?
|
||||
Debug.log(new RuntimeException("Needs dictionary."));
|
||||
count = -1;
|
||||
}//if//
|
||||
else if(inflater.finished()) {
|
||||
count = -1;
|
||||
}//else if//
|
||||
else if(inflater.needsInput()) {
|
||||
//int readSize = length > internalBuffer.length ? internalBuffer.length : length;
|
||||
//int readSize = internalBuffer.length;
|
||||
if(!inflate()) {
|
||||
break;
|
||||
}//if//
|
||||
}//else if//
|
||||
}//if//
|
||||
else {
|
||||
offset += count;
|
||||
length -= count;
|
||||
result += count;
|
||||
}//else//
|
||||
}//while//
|
||||
}//try//
|
||||
catch(DataFormatException e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Stream corruption error in decompressing.");
|
||||
}//catch//
|
||||
|
||||
return result == 0 ? -1 : result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see IInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int result;
|
||||
|
||||
if(stream instanceof IInputStream) {
|
||||
result = ((IInputStream) stream).read(out, length);
|
||||
}//if//
|
||||
else {
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
result = stream.read(bytes, 0, bytes.length);
|
||||
out.write(bytes, 0, result);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
}//CompressionInputStream//
|
||||
152
Common/src/com/common/io/CompressionOutputStream.java
Normal file
152
Common/src/com/common/io/CompressionOutputStream.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.*;
|
||||
|
||||
public class CompressionOutputStream extends OutputStream implements IOutputStream {
|
||||
public static final int DEFAULT_BUFFER_SIZE = 301;
|
||||
public static final int MAX_BUFFER_SIZE = 65535;
|
||||
|
||||
protected OutputStream stream = null;
|
||||
protected Deflater deflater = null;
|
||||
protected byte[] outputBuffer = null;
|
||||
/**
|
||||
* CompressionOutputStream constructor.
|
||||
* @param stream The stream that will handle all output from this stream.
|
||||
*/
|
||||
public CompressionOutputStream(OutputStream stream) {
|
||||
this(stream, null, DEFAULT_BUFFER_SIZE);
|
||||
}//CompressionOutputStream()//
|
||||
/**
|
||||
* CompressionOutputStream constructor.
|
||||
* @param stream The stream that will handle all output from this stream.
|
||||
* @param deflater The deflater to be used.
|
||||
*/
|
||||
public CompressionOutputStream(OutputStream stream, Deflater deflater) {
|
||||
this(stream, deflater, DEFAULT_BUFFER_SIZE);
|
||||
}//CompressionOutputStream()//
|
||||
/**
|
||||
* CompressionOutputStream constructor.
|
||||
* @param stream The stream that will handle all output from this stream.
|
||||
* @param deflater The deflater to be used.
|
||||
* @param bufferSize The size of the buffer used to read from the deflater.
|
||||
*/
|
||||
public CompressionOutputStream(OutputStream stream, Deflater deflater, int bufferSize) {
|
||||
//Validate the inputs.//
|
||||
if(bufferSize < 1) {
|
||||
throw new IllegalArgumentException("Buffer size must be greater than zero.");
|
||||
}//if//
|
||||
else if(bufferSize > MAX_BUFFER_SIZE) {
|
||||
throw new IllegalArgumentException("Buffer size must be less than " + MAX_BUFFER_SIZE + ".");
|
||||
}//else if//
|
||||
else if(stream == null) {
|
||||
throw new IllegalArgumentException("A non-null output stream must be provided.");
|
||||
}//else if//
|
||||
else if(deflater == null) {
|
||||
deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
|
||||
}//else if//
|
||||
|
||||
this.stream = stream;
|
||||
this.deflater = deflater;
|
||||
this.outputBuffer = new byte[bufferSize];
|
||||
}//CompressionOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.IOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).canEncrypt());
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
deflater.finish();
|
||||
deflate();
|
||||
|
||||
super.close();
|
||||
}//close()//
|
||||
/**
|
||||
* Deflates the cached data.
|
||||
*/
|
||||
private void deflate() throws IOException {
|
||||
int count = 0;
|
||||
|
||||
while((count = deflater.deflate(outputBuffer, 2, outputBuffer.length - 2)) > 0) {
|
||||
StreamSupport.writeShort((short) count, outputBuffer, 0); //Note: count should never exceed the buffer length and thus should stay within two bytes in size.//
|
||||
stream.write(outputBuffer, 0, count + 2);
|
||||
}//while//
|
||||
|
||||
/* Another way of doing the same thing I think.
|
||||
while(!deflater.needsInput()) {
|
||||
int count = deflater.deflate(outputBuffer);
|
||||
|
||||
if(count > 0) {
|
||||
stream.write(outputBuffer, 0, count);
|
||||
}//if//
|
||||
}//while//
|
||||
*/
|
||||
}//deflate()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.IOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
if(stream instanceof IOutputStream) {
|
||||
if(((IOutputStream) stream).canEncrypt()) {
|
||||
flush();
|
||||
((IOutputStream) stream).encrypt(encrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//encrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if(deflater.getTotalIn() > 0) {
|
||||
deflater.finish();
|
||||
deflate();
|
||||
deflater.reset();
|
||||
}//if//
|
||||
|
||||
stream.flush();
|
||||
}//flush()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.IOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).isEncrypting());
|
||||
}//isEncrypting()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte[] buffer) throws IOException {
|
||||
write(buffer, 0, buffer.length);
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||
deflater.setInput(buffer, offset, length);
|
||||
deflate();
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
outputBuffer[0] = (byte) (b & 0xFF);
|
||||
write(outputBuffer, 0, 1);
|
||||
}//write()//
|
||||
}//CompressionOutputStream//
|
||||
209
Common/src/com/common/io/CryptoInputStream.java
Normal file
209
Common/src/com/common/io/CryptoInputStream.java
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an symmetricly encrypted stream to be plugged into an input stream so that read bytes are decrypted using the private key.
|
||||
*/
|
||||
public abstract class CryptoInputStream extends java.io.InputStream implements IInputStream {
|
||||
protected InputStream stream = null;
|
||||
protected int decryptionCount;
|
||||
protected byte[] encryptedBuffer = null;
|
||||
protected byte[] decryptedBuffer = null;
|
||||
protected int decryptedBufferOffset = 0;
|
||||
protected int decryptionLength = 0;
|
||||
protected boolean stopFlag = false; //Used to notify the read methods that the encrypted segments have ended and that wrappering streams attempting to buffer should be told there are no more bytes at this time.//
|
||||
/**
|
||||
* CryptoInputStream constructor.
|
||||
*/
|
||||
public CryptoInputStream(InputStream stream, IAlgorithm algorithm) {
|
||||
super();
|
||||
|
||||
if(stream == null) {
|
||||
throw new IllegalArgumentException("Must provide a valid output stream.");
|
||||
}//if//
|
||||
else if(algorithm == null) {
|
||||
throw new IllegalArgumentException("Must provide a valid algorithm.");
|
||||
}//if//
|
||||
|
||||
this.stream = stream;
|
||||
}//CryptoInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#available()
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return stream.available();
|
||||
}//available()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return true;
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/**
|
||||
* Decrypts or verifies (unsigns) data and strips all padding.
|
||||
* @param data The buffer containing encrypted data.
|
||||
* @param dataOffset The index of the first encrypted byte.
|
||||
* @param dataLength The number of encrypted data bytes.
|
||||
* @param output A buffer to contain the decrypted data.
|
||||
* @param outputOffset The location of the first decrypted byte in the output buffer.
|
||||
* @return The number of bytes decrypted.
|
||||
*/
|
||||
protected abstract int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
if(decrypt) {
|
||||
if(decryptionCount == 0) {
|
||||
refillBuffer();
|
||||
}//if//
|
||||
|
||||
decryptionCount++;
|
||||
}//if//
|
||||
else {
|
||||
decryptionCount--;
|
||||
|
||||
if(decryptionCount == 0) {
|
||||
if(stopFlag) {
|
||||
stopFlag = false;
|
||||
}//if//
|
||||
else if((stream.read() & 0xFF) != 0xF0) {
|
||||
throw new java.io.StreamCorruptedException("Error: Premature decryption completion.");
|
||||
}//else if//
|
||||
}//if//
|
||||
}//else//
|
||||
}//decrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return decryptionCount > 0;
|
||||
}//isDecrypting()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
int result = -1;
|
||||
|
||||
if(!stopFlag) {
|
||||
if(decryptionCount > 0) {
|
||||
if(decryptedBufferOffset == decryptionLength) {
|
||||
refillBuffer();
|
||||
}//if//
|
||||
|
||||
//The stop flag may be set when we refilled the buffer.//
|
||||
if(!stopFlag) {
|
||||
result = decryptedBuffer[decryptedBufferOffset++];
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
result = stream.read();
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
int result = -1;
|
||||
|
||||
if(!stopFlag) {
|
||||
if(decryptionCount > 0) {
|
||||
result = 0;
|
||||
|
||||
while((!stopFlag) && (result != length)) {
|
||||
int size = 0;
|
||||
|
||||
if(decryptedBufferOffset == decryptionLength) {
|
||||
refillBuffer();
|
||||
}//if//
|
||||
|
||||
//The stop flag may be set when we refilled the buffer.//
|
||||
if(!stopFlag) {
|
||||
size = decryptionLength - decryptedBufferOffset;
|
||||
|
||||
if(size > length - result) {
|
||||
size = length - result;
|
||||
}//if//
|
||||
|
||||
System.arraycopy(decryptedBuffer, decryptedBufferOffset, buffer, offset + result, size);
|
||||
result += size;
|
||||
decryptedBufferOffset += size;
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
if(result == 0) {
|
||||
result = -1;
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
result = stream.read(buffer, offset, length);
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int result = 0;
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
result = stream.read(bytes, 0, bytes.length);
|
||||
out.write(bytes, 0, result);
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
private boolean refillBuffer() throws IOException {
|
||||
boolean result = !stopFlag;
|
||||
|
||||
if(!stopFlag) {
|
||||
int flag = (stream.read() & 0xFF);
|
||||
|
||||
if(flag == 0xF0) {
|
||||
//Sometimes a wrappering stream will try to buffer beyond the encrypted segment. In such cases we will stop reading until the decryption flag is turned off.//
|
||||
stopFlag = true;
|
||||
result = false;
|
||||
}//if//
|
||||
else if(flag == 0xFF) {
|
||||
int size = StreamSupport.readInt(stream);
|
||||
int count = stream.read(encryptedBuffer, 0, size);
|
||||
|
||||
if(count != size) {
|
||||
throw new IOException("Error: Invalid read length.");
|
||||
}//if//
|
||||
|
||||
decryptionLength = decrypt(encryptedBuffer, 0, count, decryptedBuffer, 0);
|
||||
decryptedBufferOffset = 0;
|
||||
}//else if//
|
||||
else {
|
||||
throw new IOException("Stream corruption found while decrypting.");
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//refillBuffer()//
|
||||
}//CryptoInputStream//
|
||||
166
Common/src/com/common/io/CryptoOutputStream.java
Normal file
166
Common/src/com/common/io/CryptoOutputStream.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an asymmetric stream to be plugged into an output stream so that written bytes are encrypted using the public key.
|
||||
*/
|
||||
public abstract class CryptoOutputStream extends OutputStream implements IOutputStream {
|
||||
protected OutputStream stream = null;
|
||||
protected int encryptionCount;
|
||||
protected byte[] encryptedBuffer = null;
|
||||
protected byte[] decryptedBuffer = null;
|
||||
protected int decryptedBufferOffset = 0;
|
||||
/**
|
||||
* CryptoOutputStream constructor.
|
||||
*/
|
||||
public CryptoOutputStream(OutputStream stream, IAlgorithm algorithm) {
|
||||
super();
|
||||
|
||||
if(stream == null) {
|
||||
throw new IllegalArgumentException("Must provide a valid output stream.");
|
||||
}//if//
|
||||
else if(algorithm == null) {
|
||||
throw new IllegalArgumentException("Must provide a valid algorithm.");
|
||||
}//if//
|
||||
|
||||
this.stream = stream;
|
||||
}//CryptoOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return true;
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
while(isEncrypting()) {
|
||||
encrypt(false);
|
||||
}//while//
|
||||
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/**
|
||||
* Empties the buffer containing to-be encrypted data.
|
||||
*/
|
||||
protected void emptyBuffer() throws IOException {
|
||||
if(decryptedBufferOffset > 0) {
|
||||
int size = encrypt(decryptedBuffer, 0, decryptedBufferOffset, encryptedBuffer, 0);
|
||||
|
||||
//Write the block header.//
|
||||
stream.write(0xFF);
|
||||
//Write the encrypted size.//
|
||||
StreamSupport.writeInt(size, stream);
|
||||
//Write the block data.//
|
||||
stream.write(encryptedBuffer, 0, size);
|
||||
//Reset the block indexes.//
|
||||
decryptedBufferOffset = 0;
|
||||
}//if//
|
||||
}//emptyBuffer()//
|
||||
/**
|
||||
* Encrypts or signs the data.
|
||||
* @param data The buffer containing unencrypted data.
|
||||
* @param dataOffset The index of the first unencrypted byte.
|
||||
* @param dataLength The number of unencrypted data bytes.
|
||||
* @param output A buffer to contain the encrypted data.
|
||||
* @param outputOffset The location of the first encrypted byte in the output buffer.
|
||||
* @return The number of encrypted bytes (includes formatting and padding).
|
||||
*/
|
||||
protected abstract int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset);
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
if(encrypt) {
|
||||
//Flush any unencrypted data before beginning an encrypted segment.//
|
||||
if(encryptionCount == 0) {
|
||||
//TODO: Should flush data from all wrappering streams. This isn't possible with the current "pipe" design pattern for streams.//
|
||||
}//if//
|
||||
|
||||
encryptionCount++;
|
||||
}//if//
|
||||
else {
|
||||
encryptionCount--;
|
||||
|
||||
if(encryptionCount == 0) {
|
||||
//TODO: Should flush data from all wrappering streams. This isn't possible with the current "pipe" design pattern for streams.//
|
||||
//Empty the buffer and end the encrypted segment.//
|
||||
emptyBuffer();
|
||||
stream.write(0xF0);
|
||||
}//if//
|
||||
}//else//
|
||||
}//encrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
/* This could cause a lot of unnecessary padding.
|
||||
if(encryptionCount > 0) {
|
||||
emptyBuffer();
|
||||
}//if//
|
||||
*/
|
||||
stream.flush();
|
||||
}//flush()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return encryptionCount > 0;
|
||||
}//isEncrypting()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||
if(encryptionCount > 0) {
|
||||
int count = 0;
|
||||
|
||||
while(count != length) {
|
||||
int size = 0;
|
||||
|
||||
if(decryptedBufferOffset == decryptedBuffer.length) {
|
||||
emptyBuffer();
|
||||
}//if//
|
||||
|
||||
size = decryptedBuffer.length - decryptedBufferOffset;
|
||||
|
||||
if(size > length - count) {
|
||||
size = length - count;
|
||||
}//if//
|
||||
|
||||
System.arraycopy(buffer, offset + count, decryptedBuffer, decryptedBufferOffset, size);
|
||||
count += size;
|
||||
decryptedBufferOffset += size;
|
||||
}//while//
|
||||
}//if//
|
||||
else {
|
||||
stream.write(buffer, offset, length);
|
||||
}//else//
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
if(encryptionCount > 0) {
|
||||
if(decryptedBufferOffset == decryptedBuffer.length) {
|
||||
emptyBuffer();
|
||||
}//if//
|
||||
|
||||
decryptedBuffer[decryptedBufferOffset++] = (byte) b;
|
||||
}//if//
|
||||
else {
|
||||
stream.write(b);
|
||||
}//else//
|
||||
}//write()//
|
||||
}//CryptoOutputStream//
|
||||
80
Common/src/com/common/io/FileSupport.java
Normal file
80
Common/src/com/common/io/FileSupport.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2006,2007 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.util.StringSupport;
|
||||
|
||||
public class FileSupport {
|
||||
/**
|
||||
* FileSupport constructor.
|
||||
*/
|
||||
private FileSupport() {
|
||||
super();
|
||||
}//FileSupport()//
|
||||
/**
|
||||
* Gets the hash of the given file.
|
||||
* @param file The file whose contents will be hashed.
|
||||
* @param hashAlgorithm The hash algorithm to use.
|
||||
* @return The hash of the file.
|
||||
*/
|
||||
public static String getFileHash(File file, IHashAlgorithm hashAlgorithm) {
|
||||
try {
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
int available = fin.available();
|
||||
byte[] bytes = new byte[available > 100000 ? 100000 : available];
|
||||
int readCount = 0;
|
||||
|
||||
hashAlgorithm.reset();
|
||||
|
||||
while(readCount < available) {
|
||||
int read = fin.read(bytes, 0, available - readCount > bytes.length ? bytes.length : available - readCount);
|
||||
|
||||
readCount += read;
|
||||
hashAlgorithm.add(bytes, 0, read);
|
||||
}//while//
|
||||
|
||||
fin.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
return StringSupport.toHexString(hashAlgorithm.hash());
|
||||
}//getFileHash()//
|
||||
/**
|
||||
* Gets the contents of the given file.
|
||||
* @param file The file whose contents will be retrieved.
|
||||
* @return The contents of the file or null if there was a problem.
|
||||
*/
|
||||
public static byte[] getFileContents(File file) {
|
||||
byte[] result = null;
|
||||
|
||||
try {
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
int readCount = 0;
|
||||
|
||||
result = new byte[fin.available()];
|
||||
|
||||
while(readCount < result.length) {
|
||||
readCount += fin.read(result, readCount, result.length - readCount);
|
||||
}//while//
|
||||
|
||||
fin.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
return result;
|
||||
}//getFileHash()//
|
||||
}//FileSupport//
|
||||
188
Common/src/com/common/io/HashedInputStream.java
Normal file
188
Common/src/com/common/io/HashedInputStream.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.security.*;
|
||||
|
||||
/**
|
||||
* Maintains a hash of all streamed data and automates validating the hash with a hash embedded in the stream.
|
||||
*/
|
||||
public class HashedInputStream extends java.io.InputStream implements IInputStream {
|
||||
private InputStream stream = null;
|
||||
private IHashAlgorithm algorithm = null;
|
||||
private boolean isHashing = false;
|
||||
private byte[] oneByte = new byte[1];
|
||||
/**
|
||||
* HashedInputStream constructor.
|
||||
* <p>Note: The hashed input stream will default to hash all streamed data. Call hash(boolean) to turn hashing on and off.</p>
|
||||
* @param stream The input stream to retrieve data from.
|
||||
* @param algorithm The hashing algorithm to be used.
|
||||
*/
|
||||
public HashedInputStream(InputStream stream, IHashAlgorithm algorithm) {
|
||||
super();
|
||||
|
||||
this.stream = stream;
|
||||
this.algorithm = algorithm;
|
||||
this.isHashing = true;
|
||||
}//HashedInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).canDecrypt());
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
if(stream instanceof IInputStream) {
|
||||
if(((IInputStream) stream).canDecrypt()) {
|
||||
((IInputStream) stream).decrypt(decrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//decrypt()//
|
||||
/**
|
||||
* Gets the hash of all data streamed while we were hashing.
|
||||
* <p>Note: Calling this method will reset the hashing algorithm but will not turn hashing off.</p>
|
||||
* @return The hash or null if hashing is not on.
|
||||
*/
|
||||
public byte[] getHash() {
|
||||
byte[] retVal = null;
|
||||
|
||||
if(isHashing) {
|
||||
retVal = algorithm.hash();
|
||||
algorithm.reset();
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//getHash()//
|
||||
/**
|
||||
* Begins or ends hashing streamed data. Ending hashing does not reset the hash and hashing can resume at a later time.
|
||||
* @param hash Whether to hash read data.
|
||||
* @throws IOException Thrown if the stream is told to hash or stop hashing twice in a row.
|
||||
*/
|
||||
public void hash(boolean hash) throws IOException {
|
||||
if(isHashing == hash) {
|
||||
throw new IOException("Cannot start or end hashing twice.");
|
||||
}//if//
|
||||
|
||||
isHashing = hash;
|
||||
}//getHash()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).isDecrypting());
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Determines whether the data read from the stream is being hashed.
|
||||
* @return Whether the stream is currently being hashed.
|
||||
*/
|
||||
public boolean isHashing() {
|
||||
return isHashing;
|
||||
}//isHashing()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
int retVal = stream.read();
|
||||
|
||||
if(isHashing) {
|
||||
oneByte[0] = (byte) retVal;
|
||||
algorithm.add(oneByte);
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
int retVal = stream.read(buffer, offset, length);
|
||||
|
||||
if(isHashing) {
|
||||
algorithm.add(buffer, offset, length);
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int retVal = 0;
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
retVal = stream.read(bytes, 0, bytes.length);
|
||||
out.write(bytes, 0, retVal);
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/**
|
||||
* Reads a hash from the stream. This is useful if the application will manually check the hashes.
|
||||
* <p>In most cases the hash embedded in the stream will be signed or encrypted. If such is the case the application should enable decryption before calling this method.</p>
|
||||
* <p>Note: This does not reset the hash algorithm and does not automatically stop the stream hashing.</p>
|
||||
* @return The read hash value.
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public byte[] readHash() throws IOException {
|
||||
byte[] hash = null;
|
||||
|
||||
hash = new byte[(int) (StreamSupport.readShort(stream) & 0xFFFF)];
|
||||
read(hash, 0, hash.length);
|
||||
|
||||
return hash;
|
||||
}//read()//
|
||||
/**
|
||||
* Validates the stream by comparing the stream hash to the hash embedded in the stream.
|
||||
* <p>In most cases the hash embedded in the stream will be signed or encrypted. If such is the case the application should enable decryption before calling this method.</p>
|
||||
* <p>Note: This does reset the hash algorithm and will automatically pause all hashing to get a valid comparison.</p>
|
||||
* @return Whether a valid hash was read from the input stream.
|
||||
*/
|
||||
public boolean validateHash() throws IOException {
|
||||
boolean flag = isHashing;
|
||||
byte[] readHash = null;
|
||||
byte[] inputHash = getHash();
|
||||
boolean isValid = true;
|
||||
|
||||
algorithm.reset();
|
||||
isHashing = false;
|
||||
readHash = new byte[(int) (StreamSupport.readShort(stream) & 0xFFFF)];
|
||||
read(readHash, 0, readHash.length);
|
||||
isHashing = flag;
|
||||
|
||||
//Validate the hashes.//
|
||||
if(inputHash.length == readHash.length) {
|
||||
for(int index = 0; ((isValid) && (index < inputHash.length)); index++) {
|
||||
if(readHash[index] != inputHash[index]) {
|
||||
isValid = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
isValid = false;
|
||||
}//else//
|
||||
|
||||
return isValid;
|
||||
}//read()//
|
||||
}//HashedInputStream//
|
||||
147
Common/src/com/common/io/HashedOutputStream.java
Normal file
147
Common/src/com/common/io/HashedOutputStream.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.security.*;
|
||||
|
||||
/**
|
||||
* Maintains a hash of all streamed data and automates the embedding of the hash in the stream.
|
||||
*/
|
||||
public class HashedOutputStream extends OutputStream implements IOutputStream {
|
||||
private OutputStream stream = null;
|
||||
private IHashAlgorithm algorithm = null;
|
||||
private boolean isHashing = false;
|
||||
private byte[] oneByte = new byte[1];
|
||||
/**
|
||||
* HashedOutputStream constructor.
|
||||
* <p>Note: The hashed output stream will default to hash all streamed data. Call hash(boolean) to turn hashing on and off.</p>
|
||||
* @param stream The output stream to send all streamed data to.
|
||||
* @param algorithm The hashing algorithm to be used.
|
||||
*/
|
||||
public HashedOutputStream(OutputStream stream, IHashAlgorithm algorithm) {
|
||||
super();
|
||||
|
||||
this.stream = stream;
|
||||
this.algorithm = algorithm;
|
||||
this.isHashing = true;
|
||||
}//HashedOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).canEncrypt());
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
if(stream instanceof IOutputStream) {
|
||||
if(((IOutputStream) stream).canEncrypt()) {
|
||||
flush();
|
||||
((IOutputStream) stream).encrypt(encrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Flushes this output stream and the encapsulated output stream.
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
stream.flush();
|
||||
}//flush()//
|
||||
/**
|
||||
* Gets the hash of all data streamed while we were hashing.
|
||||
* <p>Note: Calling this method will reset the hashing algorithm but will not turn hashing off.</p>
|
||||
* @return The hash or null if hashing is not on.
|
||||
*/
|
||||
public byte[] getHash() {
|
||||
byte[] retVal = null;
|
||||
|
||||
if(isHashing) {
|
||||
retVal = algorithm.hash();
|
||||
algorithm.reset();
|
||||
}//if//
|
||||
|
||||
return retVal;
|
||||
}//getHash()//
|
||||
/**
|
||||
* Begins or ends hashing streamed data. Ending hashing does not reset the hash and hashing can resume at a later time.
|
||||
* @param hash Whether to hash read data.
|
||||
* @throws IOException Thrown if the stream is told to hash or stop hashing twice in a row.
|
||||
*/
|
||||
public void hash(boolean hash) throws IOException {
|
||||
if(isHashing == hash) {
|
||||
throw new IOException("Cannot start or end hashing twice.");
|
||||
}//if//
|
||||
|
||||
isHashing = hash;
|
||||
}//getHash()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).isEncrypting());
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Determines whether the data read from the stream is being hashed.
|
||||
* @return Whether the stream is currently being hashed.
|
||||
*/
|
||||
public boolean isHashing() {
|
||||
return isHashing;
|
||||
}//isHashing()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||
stream.write(buffer, offset, length);
|
||||
|
||||
if(isHashing) {
|
||||
algorithm.add(buffer, offset, length);
|
||||
}//if//
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
stream.write(b);
|
||||
|
||||
if(isHashing) {
|
||||
oneByte[0] = (byte) b;
|
||||
algorithm.add(oneByte);
|
||||
}//if//
|
||||
}//write()//
|
||||
/**
|
||||
* Gets the hash of all data streamed while we were hashing.
|
||||
* <p>Note: Calling this method will reset the hashing algorithm but will not turn hashing off.</p>
|
||||
* @return The hash or null if hashing is not on.
|
||||
*/
|
||||
public void writeHash() throws IOException {
|
||||
byte[] hash = algorithm.hash();
|
||||
boolean flag = isHashing;
|
||||
|
||||
algorithm.reset();
|
||||
isHashing = false;
|
||||
StreamSupport.writeShort((short) hash.length, this);
|
||||
write(hash, 0, hash.length);
|
||||
isHashing = flag;
|
||||
}//getHash()//
|
||||
}//HashedOutputStream//
|
||||
69
Common/src/com/common/io/HexInputStream.java
Normal file
69
Common/src/com/common/io/HexInputStream.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class HexInputStream extends InputStream {
|
||||
/** The input stream to read hex codes from. */
|
||||
private InputStream in = null;
|
||||
/**
|
||||
* HexInputStream constructor.
|
||||
*/
|
||||
public HexInputStream(InputStream in) {
|
||||
super();
|
||||
}//HexInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
return ((0x0F & in.read()) << 4) | (0x0F & in.read());
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int readCount = 0;
|
||||
|
||||
for(int index = off; index + off < len; index++) {
|
||||
int high = in.read();
|
||||
int low = in.read();
|
||||
|
||||
if(high != -1 && low != -1) {
|
||||
b[index] = (byte) (((0x0F & high) << 4) | (0x0F & low));
|
||||
readCount++;
|
||||
}//if//
|
||||
else {
|
||||
break;
|
||||
}//else//
|
||||
}//for//
|
||||
|
||||
return readCount;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[])
|
||||
*/
|
||||
public int read(byte[] b) throws IOException {
|
||||
int readCount = 0;
|
||||
|
||||
while(readCount < b.length) {
|
||||
int high = in.read();
|
||||
int low = in.read();
|
||||
|
||||
if(high != -1 && low != -1) {
|
||||
b[readCount++] = (byte) (((0x0F & high) << 4) | (0x0F & low));
|
||||
}//if//
|
||||
else {
|
||||
break;
|
||||
}//else//
|
||||
}//while//
|
||||
|
||||
return readCount;
|
||||
}//read()//
|
||||
}//HexInputStream//
|
||||
51
Common/src/com/common/io/HexOutputStream.java
Normal file
51
Common/src/com/common/io/HexOutputStream.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2006,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/*
|
||||
* Converts all bytes written to the stream into hexidecimal codes.
|
||||
*/
|
||||
public class HexOutputStream extends OutputStream {
|
||||
/** The output stream to send the hexidecimal values to. */
|
||||
private OutputStream out = null;
|
||||
/**
|
||||
* HexOutputStream constructor.
|
||||
*/
|
||||
public HexOutputStream(OutputStream out) {
|
||||
super();
|
||||
this.out = out;
|
||||
}//HexOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
out.write((b >> 4) & 0x0F);
|
||||
out.write(b & 0x0F);
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
for(int index = off; index + off < len; index++) {
|
||||
out.write((b[index] >> 4) & 0x0F);
|
||||
out.write(b[index] & 0x0F);
|
||||
}//for//
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte[] b) throws IOException {
|
||||
for(int index = 0; index < b.length; index++) {
|
||||
out.write((b[index] >> 4) & 0x0F);
|
||||
out.write(b[index] & 0x0F);
|
||||
}//for//
|
||||
}//write()//
|
||||
}//HexOutputStream//
|
||||
17
Common/src/com/common/io/IClassReplacementHandler.java
Normal file
17
Common/src/com/common/io/IClassReplacementHandler.java
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
public interface IClassReplacementHandler {
|
||||
/**
|
||||
* Allows the caller to receive an alternate name for the given class name.
|
||||
* @param className The name of the class as read by the stream.
|
||||
* @return The replacement class name to be used by the stream.
|
||||
*/
|
||||
public String getReplacementClassName(String className);
|
||||
}//IClassReplacementHandler//
|
||||
16
Common/src/com/common/io/IClassTracker.java
Normal file
16
Common/src/com/common/io/IClassTracker.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
public interface IClassTracker {
|
||||
/**
|
||||
* Adds the class name to the collection being tracked.
|
||||
* @param className The class name to be kept track of.
|
||||
*/
|
||||
public void add(String className);
|
||||
}//IClassTracker//
|
||||
23
Common/src/com/common/io/IExternalizable.java
Normal file
23
Common/src/com/common/io/IExternalizable.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
public interface IExternalizable {
|
||||
public static final Object NULL_VALUE = new Object();
|
||||
/**
|
||||
* Reads this object from the given stream.
|
||||
* @param in The input stream to read this object from.
|
||||
* @return The replacement object if applicable. Allows the read object to replace its self with an alternate. Useful if the object already exists as an identifier somewhere. If null then the stream will assume this instance is the result.
|
||||
*/
|
||||
public Object readExternal(IObjectInputStream in) throws java.io.IOException, ClassNotFoundException;
|
||||
/**
|
||||
* Writes this object to the given stream.
|
||||
* @param out The output stream to write this object to.
|
||||
*/
|
||||
public void writeExternal(IObjectOutputStream out) throws java.io.IOException;
|
||||
}//IExternalizable//
|
||||
42
Common/src/com/common/io/IInputStream.java
Normal file
42
Common/src/com/common/io/IInputStream.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines some common functionality associated with advanced streams.
|
||||
* Implementors can implement some or all of the functionality and users can determine whether an aggregate stream supports the functionality it requires.
|
||||
*/
|
||||
public interface IInputStream {
|
||||
public static final String ERROR_DECRYPTION_NOT_SUPPORTED = "Underlying stream does not provide decryption facilities. Please make sure that this (or the aggregate) stream supports decryption before calling this method.";
|
||||
/**
|
||||
* Determines whether the stream is capable of decrypting parts or all of the message.
|
||||
* @return Whether the data stream is capable of decryption.
|
||||
*/
|
||||
public boolean canDecrypt();
|
||||
/**
|
||||
* Starts or stops decrypting the message from the current index within the stream.
|
||||
* <p>Warning: The input stream does not have to support this functionality. A MethodNotSupportedException will be thrown if the functionality is not supported.
|
||||
* @param decrypt Whether to start or stop decrypting. This method call should occur at the same points in the stream as the calls were made in the output stream.
|
||||
* @see #canDecrypt()
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException;
|
||||
/**
|
||||
* Determines whether the stream is currently decrypting the part or all of the message being read.
|
||||
* @return Whether the data stream is currently being decrypted.
|
||||
*/
|
||||
public boolean isDecrypting();
|
||||
/**
|
||||
* Reads bytes from this stream and places them into the supplied output stream.
|
||||
* @param out The output stream to write the read bytes to.
|
||||
* @param length The number of bytes to read from the stream.
|
||||
* @return The number of bytes read from the stream.
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException;
|
||||
}//IInputStream//
|
||||
21
Common/src/com/common/io/IInstanceFactory.java
Normal file
21
Common/src/com/common/io/IInstanceFactory.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
/**
|
||||
* Provides for instance creation for streams requiring an instance of a class where the class is defined by the application.
|
||||
* <p>Most streams allow an instance factory to provide customized behavior when the default behavior is not acceptable.</p>
|
||||
*/
|
||||
public interface IInstanceFactory {
|
||||
/**
|
||||
* Creates an uninitialized instance of the given class. The method should only throw an InstantiationException if the caller does not want the user to locate the class via other means.
|
||||
* @param clazz The class to create an instance of.
|
||||
* @return The instance created, or null if an instance was not createable.
|
||||
*/
|
||||
public Object createInstance(Class clazz) throws InstantiationException;
|
||||
}//IInstanceFactory//
|
||||
50
Common/src/com/common/io/IObjectInputStream.java
Normal file
50
Common/src/com/common/io/IObjectInputStream.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import com.common.util.IList;
|
||||
|
||||
public interface IObjectInputStream extends IStandardInputStream, java.io.ObjectInput {
|
||||
/**
|
||||
* Gets the optional factory that generates class instances.
|
||||
* @return A factory that will produce an instance of the given class. If provided, this will be used instead of calling Class.newInstance().
|
||||
*/
|
||||
public IInstanceFactory getInstanceFactory();
|
||||
/**
|
||||
* Gets the optional class tracker which will be notified when a class is used.
|
||||
* @return The class tracker is notified every time a class is referenced by the stream. It allows the application to track what classes are utilized by the streams.
|
||||
*/
|
||||
public IClassTracker getClassTracker();
|
||||
/**
|
||||
* Gets the collection of Class instances ordered by the index the stream will reference them by furthor on in the stream.
|
||||
* <p>Warning: This is provided to allow sub-streams. Modifying this value out of context will cause stream corruption errors.</p>
|
||||
* @return The list of classes that were serialized indexed by the number the stream will use to reference them in the future.
|
||||
*/
|
||||
public IList getClassList();
|
||||
/**
|
||||
* Gets the optional class loader used to obtain a Class instance given a class name.
|
||||
* @return The optional class loader which is used if provided to lookup the class names.
|
||||
*/
|
||||
public ClassLoader getLoader();
|
||||
/**
|
||||
* Gets the collection of previously deserialized objects indexed by the number used in the stream to reference recursively.
|
||||
* <p>Warning: This is provided to allow sub-streams. Modifying this value out of context will cause stream corruption errors.</p>
|
||||
* @return The collection of objects deserialized in order of deserialization. Used to reference previously deserialized values by number in the stream to prevent recursive references from bloating the stream.
|
||||
*/
|
||||
public IList getDeserializedValues();
|
||||
/**
|
||||
* Gets the optional class replacement handler which if provided will always be called upon to alter the stream specified class name with another equivalent name prior to class lookup.
|
||||
* @return Called prior to looking up the deserialized class name - allows replacement of the class name.
|
||||
*/
|
||||
public IClassReplacementHandler getClassReplacementHandler();
|
||||
/**
|
||||
* Gets the optional stream manager which allows a class to be swapped for another at runtime if the original class cannot be identified.
|
||||
* @return Allows the input stream to replace one class with another <b>if the original class cannot be found</b>.
|
||||
*/
|
||||
public IStreamManager getStreamManager();
|
||||
}//IObjectInputStream//
|
||||
32
Common/src/com/common/io/IObjectOutputStream.java
Normal file
32
Common/src/com/common/io/IObjectOutputStream.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import com.common.util.IHashMap;
|
||||
import com.common.util.IList;
|
||||
import com.common.util.optimized.ObjectIntHashMap;
|
||||
|
||||
public interface IObjectOutputStream extends IStandardOutputStream, java.io.ObjectOutput {
|
||||
/**
|
||||
* Gets the mapping of serialized object's index number by the object that was serialized.
|
||||
* <p>Warning: This is provided to allow sub-streams. Modifying this value out of context will cause stream corruption errors.</p>
|
||||
* @return The mapping that allows a previously serialized object to be replaced by a number thus avoiding infinate loops and compressing the stream.
|
||||
*/
|
||||
public ObjectIntHashMap getSerializedObjectMap();
|
||||
/**
|
||||
* Gets the mapping of class names to index such that the index can be used in place of the class name in the stream.
|
||||
* <p>Warning: This is provided to allow sub-streams. Modifying this value out of context will cause stream corruption errors.</p>
|
||||
* @return The mapping that allows a previously serialized class name to be replaced by a number.
|
||||
*/
|
||||
public IHashMap getClassMap();
|
||||
/**
|
||||
* Gets the handler that will be called to swap one class with another.
|
||||
* @return The optional handler that performs class replacment.
|
||||
*/
|
||||
public IClassReplacementHandler getClassReplacementHandler();
|
||||
}//IObjectOutputStream//
|
||||
39
Common/src/com/common/io/IObjectStream.java
Normal file
39
Common/src/com/common/io/IObjectStream.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2006 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
/**
|
||||
* Defines some basic identifiers and values used by the object streams.
|
||||
*/
|
||||
public interface IObjectStream {
|
||||
//Stream identifiers.//
|
||||
public static final byte OBJECT = -1;
|
||||
public static final byte RECURSIVE_OBJECT = -2;
|
||||
public static final byte UNKNOWN_OBJECT = -3;
|
||||
public static final byte NULL = -4;
|
||||
public static final byte PRIMITIVE_ARRAY = -5;
|
||||
public static final byte ARRAY = -6;
|
||||
public static final byte CUSTOM_OBJECT = -7;
|
||||
//Optimized object types.//
|
||||
public static final byte BOOLEAN = 0;
|
||||
public static final byte BYTE = 1;
|
||||
public static final byte CHARACTER = 2;
|
||||
public static final byte SHORT = 3;
|
||||
public static final byte INTEGER = 4;
|
||||
public static final byte LONG = 5;
|
||||
public static final byte FLOAT = 6;
|
||||
public static final byte DOUBLE = 7;
|
||||
public static final byte STRING = 8;
|
||||
public static final byte CLASS = 9;
|
||||
public static final byte UTF8 = 10;
|
||||
public static final byte SHARED_BOOLEAN = 11;
|
||||
public static final byte LAST_OPTIMIZED_TYPE_NUMBER = 11;
|
||||
|
||||
public static final String STRING_FORMAT_UTF8 = StreamSupport.STRING_FORMAT_UTF8;
|
||||
public static final String STRING_FORMAT_UNICODE = StreamSupport.STRING_FORMAT_UNICODE;
|
||||
}//IObjectStream//
|
||||
34
Common/src/com/common/io/IOutputStream.java
Normal file
34
Common/src/com/common/io/IOutputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Specifies methods provided by all output streams defined in this package.
|
||||
*/
|
||||
public interface IOutputStream {
|
||||
public static final String ERROR_ENCRYPTION_NOT_SUPPORTED = "Underlying stream does not provide encryption facilities. Please make sure that this (or the aggregate) stream supports encryption before calling this method.";
|
||||
/**
|
||||
* Determines whether the stream is capable of encrypting parts or all of the message.
|
||||
* @return Whether the data stream is capable of encryption.
|
||||
*/
|
||||
public boolean canEncrypt();
|
||||
/**
|
||||
* Starts or stops encrypting the message at the current index within the stream.
|
||||
* <p>Warning: The output stream does not have to support this functionality. A MethodNotSupportedException will be thrown if the functionality is not supported.
|
||||
* @param encrypt Whether to start or stop encrypting.
|
||||
* @see #canEncrypt()
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException;
|
||||
/**
|
||||
* Determines whether the stream is currently encrypting the part or all of the message being written.
|
||||
* @return Whether the data stream is currently being encrypted.
|
||||
*/
|
||||
public boolean isEncrypting();
|
||||
}//IOutputStream//
|
||||
18
Common/src/com/common/io/IOutputStreamLocation.java
Normal file
18
Common/src/com/common/io/IOutputStreamLocation.java
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
public interface IOutputStreamLocation {
|
||||
/**
|
||||
* Gets the stream index of the location in the stream when this object was created.
|
||||
* This value will change if there is an update location object that the users writes data to (unless it has reserved space), or if this location is an update location and did not reserve space and writes data.
|
||||
* The location will be the last byte index in the set of values written to the stream, or the index of the stream at the time the location was created (updated if any new bytes were written to the stream at an earlier index).
|
||||
* @return The index within the stream of this location object (or the ending index if the location allows updating).
|
||||
*/
|
||||
public int getByteIndex();
|
||||
}//IOutputStreamLocation//
|
||||
29
Common/src/com/common/io/ISerializationHandler.java
Normal file
29
Common/src/com/common/io/ISerializationHandler.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines a serialization handler for a specific class of object. This handler will both serialize and deserialize instances of the class.
|
||||
*/
|
||||
public interface ISerializationHandler {
|
||||
/**
|
||||
* Handles the deserialization for the given type from the given stream.
|
||||
* @param object The object to deserialize.
|
||||
* @param in The input stream to deserialize from.
|
||||
* @return The deserialized object.
|
||||
*/
|
||||
public Object deserialize(IObjectInputStream in) throws IOException, ClassNotFoundException;
|
||||
/**
|
||||
* Handles the serialization for the given value to the given stream.
|
||||
* @param value The value to serialize.
|
||||
* @param out The output stream to serialize to.
|
||||
*/
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException;
|
||||
}//ISerializationHandler//
|
||||
39
Common/src/com/common/io/IStandardInputStream.java
Normal file
39
Common/src/com/common/io/IStandardInputStream.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface IStandardInputStream extends IObjectStream, IInputStream, java.io.DataInput {
|
||||
/**
|
||||
* Gets the number style used by default when deserializing numbers.
|
||||
* @return The number style identifier used by default.
|
||||
*/
|
||||
public int getDefaultNumberStyle();
|
||||
/**
|
||||
* Reads a fixed length string from file removes the unnecessary padding.
|
||||
* @param length The fixed number of bytes in the string.
|
||||
* @return The read string minus all space at the beginning or end of the string.
|
||||
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the input stream has been closed.
|
||||
*/
|
||||
public String readFixedLengthString(int length) throws java.io.IOException;
|
||||
/**
|
||||
* Reads a UTF16 string from the stream.
|
||||
* A UTF16 string is a fixed character size string using 2 bytes for each character.
|
||||
* <p>WARNING: The user must call writeUTF16(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @return The string read from the stream.
|
||||
*/
|
||||
public String readUTF16() throws IOException;
|
||||
/**
|
||||
* Reads a UTF8 string from the stream.
|
||||
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
|
||||
* <p>WARNING: The user must call writeUTF8(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @return The string read from the stream.
|
||||
*/
|
||||
public String readUTF8() throws IOException;
|
||||
}//IObjectInputStream//
|
||||
39
Common/src/com/common/io/IStandardOutputStream.java
Normal file
39
Common/src/com/common/io/IStandardOutputStream.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface IStandardOutputStream extends IObjectStream, IOutputStream, java.io.DataOutput {
|
||||
/**
|
||||
* Gets the number style used by default when serializing numbers.
|
||||
* @return The number style identifier used by default.
|
||||
*/
|
||||
public int getDefaultNumberStyle();
|
||||
/**
|
||||
* Writes a fixed length string to file and pads it with spaces where necessary.
|
||||
* @param string The string to write. This string must be under the byte size limit and an IOException will result from an improperly sized string.
|
||||
* @param length The fixed number of bytes in the string.
|
||||
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.
|
||||
*/
|
||||
public void writeFixedLengthString(String string, int length) throws java.io.IOException;
|
||||
/**
|
||||
* Writes a UTF16 string to the stream.
|
||||
* A UTF16 string is a fixed character size string using 2 bytes for each character.
|
||||
* <p>WARNING: The user must call readUTF16(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @param string The string to write to the stream.
|
||||
*/
|
||||
public void writeUTF16(String string) throws IOException;
|
||||
/**
|
||||
* Writes a UTF8 string to the stream.
|
||||
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
|
||||
* <p>WARNING: The user must call readUTF8(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
|
||||
* @param string The string to write to the stream.
|
||||
*/
|
||||
public void writeUTF8(String string) throws IOException;
|
||||
}//IObjectOutputStream//
|
||||
18
Common/src/com/common/io/IStreamManager.java
Normal file
18
Common/src/com/common/io/IStreamManager.java
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
public interface IStreamManager {
|
||||
/**
|
||||
* Allows the stream manager to replace one class with another while deserializing a stream.
|
||||
* <p>NOTE: This currently is only called if the stream cannot load the requested type.
|
||||
* @param typeName The name of the type to replace.
|
||||
* @return The replacement type (or same type if no replacement is required).
|
||||
*/
|
||||
public Class replaceType(String typeName);
|
||||
}//IStreamManager//
|
||||
31
Common/src/com/common/io/IWriter.java
Normal file
31
Common/src/com/common/io/IWriter.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
/**
|
||||
* Used by non-stream classes that want to allow writing via the stream support class.
|
||||
*/
|
||||
public interface IWriter {
|
||||
/**
|
||||
* Writes a single byte.
|
||||
* @param b The byte to write.
|
||||
*/
|
||||
public void write(byte b);
|
||||
/**
|
||||
* Writes a range of bytes.
|
||||
* @param bytes The bytes to write.
|
||||
*/
|
||||
public void write(byte[] bytes);
|
||||
/**
|
||||
* Writes a range of bytes.
|
||||
* @param bytes The bytes to write.
|
||||
* @param offset The offset in the bytes array of the first byte to write.
|
||||
* @param length The number of bytes from the bytes array to write.
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length);
|
||||
}//IWriter//
|
||||
224
Common/src/com/common/io/IndexedObjectInputStream.java
Normal file
224
Common/src/com/common/io/IndexedObjectInputStream.java
Normal file
@@ -0,0 +1,224 @@
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.common.util.IList;
|
||||
|
||||
/**
|
||||
* Allows the caller to read the components of the stream they are interested in.
|
||||
* Requests to read missing components will not corrupt the stream.
|
||||
*/
|
||||
public class IndexedObjectInputStream extends AbstractObjectInputStream {
|
||||
/** The stream being wrapped. */
|
||||
private InputStream wrapped = null;
|
||||
/** The buffered content. */
|
||||
private byte[] buffer = null;
|
||||
/** The array of element indices. Each element is an index for an element supplied during serialization. */
|
||||
private int[] indices = null;
|
||||
/** The array of index element offsets within the buffer. The index of the size corresponds to the index in the indices array. */
|
||||
private int[] offsets = null;
|
||||
/** The last used index from the indices array. */
|
||||
private int lastIndicesIndex = 0;
|
||||
/** The index within the indicies array of the index we are about to read, or -1. */
|
||||
private int nextIndex = -1;
|
||||
/** The offset within the buffer of the next data byte to be read, associated with the indexed data element referenced by nextIndex. */
|
||||
private int nextOffset = -1;
|
||||
/** The count of remaining bytes (within the buffer) of the data associated with the indexed data element referenced by nextIndex. */
|
||||
private int nextRemainingSize = -1;
|
||||
/**
|
||||
* IndexedObjectInputStream constructor.
|
||||
* @param in
|
||||
* @throws IOException
|
||||
*/
|
||||
public IndexedObjectInputStream(ObjectInput in) throws IOException {
|
||||
super(in instanceof IObjectInputStream ? ((IObjectInputStream) in).getLoader() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getClassReplacementHandler() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getClassList() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getInstanceFactory() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getClassTracker() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getDeserializedValues() : null, in instanceof IObjectInputStream ? ((IObjectInputStream) in).getDefaultNumberStyle() : AbstractStandardInputStream.STYLE_DEFAULT);
|
||||
this.wrapped = (InputStream) in;
|
||||
initialize();
|
||||
}//IndexedObjectInputStream()//
|
||||
/**
|
||||
* IndexedObjectInputStream constructor.
|
||||
* @param in
|
||||
* @throws IOException
|
||||
*/
|
||||
public IndexedObjectInputStream(IObjectInputStream in) throws IOException {
|
||||
super(in.getLoader(), in.getClassReplacementHandler(), in.getClassList(), in.getInstanceFactory(), in.getClassTracker(), in.getDeserializedValues(), in.getDefaultNumberStyle());
|
||||
this.wrapped = (InputStream) in;
|
||||
initialize();
|
||||
}//IndexedObjectInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#skip(long)
|
||||
*/
|
||||
public long skip(long count) throws IOException {
|
||||
//Not supported.//
|
||||
return 0;
|
||||
}//skip()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#mark(int)
|
||||
*/
|
||||
public void mark(int readLimit) {
|
||||
//Not supported.//
|
||||
}//mark()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#markSupported()
|
||||
*/
|
||||
public boolean markSupported() {
|
||||
//Not supported.//
|
||||
return false;
|
||||
}//markSupported()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#available()
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return wrapped.available();
|
||||
}//available()//
|
||||
/**
|
||||
* Initializes the stream.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void initialize() throws IOException {
|
||||
int count = StreamSupport.readInt(wrapped, StreamSupport.NUMBER_VLSF);
|
||||
int lastSize = -1;
|
||||
int totalSize = 0;
|
||||
|
||||
indices = new int[count];
|
||||
offsets = new int[count];
|
||||
|
||||
for(int i = 0; i < count; i++) {
|
||||
//Set the offset within the buffer.//
|
||||
offsets[i] = lastSize != -1 ? lastSize + offsets[i - 1] : 0;
|
||||
//Read the identifier for the value.//
|
||||
indices[i] = StreamSupport.readInt(wrapped, StreamSupport.NUMBER_VLSF);
|
||||
//Read the offset of the start of the value.//
|
||||
lastSize = StreamSupport.readInt(wrapped, StreamSupport.NUMBER_VLSF);
|
||||
//Update the total size of the data byte array.//
|
||||
totalSize += lastSize;
|
||||
}//for//
|
||||
|
||||
//Setup the content buffer.//
|
||||
buffer = new byte[totalSize];
|
||||
|
||||
//Buffer the whole content.//
|
||||
if(StreamSupport.readBytes(wrapped, buffer) != buffer.length) {
|
||||
throw new IOException("Failed to read enough bytes.");
|
||||
}//if//
|
||||
|
||||
lastIndicesIndex = offsets.length - 1;
|
||||
}//initialize()//
|
||||
/**
|
||||
* Begins the deserialization of the value at the given index.
|
||||
* <p>This must be called prior to any other read operation, for every read operation performed.</p>
|
||||
* @param index The index of the value to be deserialized.
|
||||
* @return Whether the stream contains a value associated with the index.
|
||||
*/
|
||||
public boolean begin(int index) {
|
||||
int i = lastIndicesIndex;
|
||||
|
||||
nextIndex = -1;
|
||||
|
||||
//Use a rotating loop over the indices starting with the index of the last match plus one. Often things are read in the same order they were written so this is just more efficient.//
|
||||
do {
|
||||
i++;
|
||||
|
||||
if(i == indices.length) {
|
||||
i = 0;
|
||||
}//if//
|
||||
|
||||
if(indices[i] == index) {
|
||||
nextIndex = i;
|
||||
nextOffset = offsets[i];
|
||||
nextRemainingSize = offsets.length > i + 1 ? offsets[i + 1] - offsets[i] : buffer.length - offsets[i];
|
||||
}//if//
|
||||
} while(nextIndex == -1 && i != lastIndicesIndex);
|
||||
|
||||
lastIndicesIndex = i;
|
||||
|
||||
return nextIndex != -1;
|
||||
}//begin()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
if(nextIndex == -1) {
|
||||
throw new IOException("Must call begin(int) prior to reading data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
else if(nextRemainingSize <= 0) {
|
||||
throw new IOException("End of element stream reached.");
|
||||
}//else if//
|
||||
|
||||
return buffer[nextOffset++];
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#read(byte[])
|
||||
*/
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
int result = Math.min(buffer.length, nextRemainingSize);
|
||||
|
||||
if(nextIndex == -1) {
|
||||
throw new IOException("Must call begin(int) prior to reading data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
else if(nextRemainingSize <= 0) {
|
||||
throw new IOException("End of element stream reached.");
|
||||
}//else if//
|
||||
|
||||
System.arraycopy(this.buffer, nextOffset, buffer, 0, result);
|
||||
nextOffset += result;
|
||||
nextRemainingSize -= result;
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
int result = Math.min(length, nextRemainingSize);
|
||||
|
||||
if(nextIndex == -1) {
|
||||
throw new IOException("Must call begin(int) prior to reading data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
else if(nextRemainingSize <= 0) {
|
||||
throw new IOException("End of element stream reached.");
|
||||
}//else if//
|
||||
|
||||
System.arraycopy(this.buffer, nextOffset, buffer, offset, result);
|
||||
nextOffset += result;
|
||||
nextRemainingSize -= result;
|
||||
|
||||
return result;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(OutputStream out, int length) throws IOException {
|
||||
byte[] bytes = new byte[Math.min(length, nextRemainingSize)];
|
||||
|
||||
if(nextIndex == -1) {
|
||||
throw new IOException("Must call begin(int) prior to reading data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
else if(nextRemainingSize <= 0) {
|
||||
throw new IOException("End of element stream reached.");
|
||||
}//else if//
|
||||
|
||||
System.arraycopy(this.buffer, nextOffset, bytes, 0, bytes.length);
|
||||
nextOffset += bytes.length;
|
||||
nextRemainingSize -= bytes.length;
|
||||
out.write(bytes);
|
||||
|
||||
return bytes.length;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractObjectInputStream#peekByte(int)
|
||||
*/
|
||||
public byte peekByte(int offset) throws IOException {
|
||||
if(nextIndex == -1) {
|
||||
throw new IOException("Must call begin(int) prior to reading data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
else if(nextRemainingSize <= 0) {
|
||||
throw new IOException("End of element stream reached.");
|
||||
}//else if//
|
||||
|
||||
return buffer[nextOffset];
|
||||
}//peekByte()//
|
||||
}//IndexedObjectInputStream//
|
||||
162
Common/src/com/common/io/IndexedObjectOutputStream.java
Normal file
162
Common/src/com/common/io/IndexedObjectOutputStream.java
Normal file
@@ -0,0 +1,162 @@
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.common.util.LiteHashMap;
|
||||
|
||||
/**
|
||||
* The indexed streams are designed to wrapper another stream (usually with a serialization handler) to allow for more independance from the stream structure.
|
||||
* The idea is that by indexing the values serialized, the stream will become more flexible, allowing the reader to skip unexpected values, and recognize that expected values were not provided.
|
||||
*/
|
||||
public class IndexedObjectOutputStream extends AbstractObjectOutputStream {
|
||||
/** The stream being wrapped. */
|
||||
private OutputStream wrapped = null;
|
||||
/** The buffer containing the element data for each indexed element. */
|
||||
private byte[] buffer;
|
||||
/** The offset within the buffer where the next byte of data will be written. */
|
||||
private int bufferOffset = 0;
|
||||
/** The next index being written. The index identifies the element being written to the stream as it is being read by the input stream. */
|
||||
private int nextIndex = -1;
|
||||
/** The offset within the buffer of the start of the nextIndex element. */
|
||||
private int nextOffset = -1;
|
||||
/** The count of index elements written to the stream. */
|
||||
private int indexCount = 0;
|
||||
/** The serialized index metadata. Contains integer pairs for each indexed element written. */
|
||||
private byte[] indexData = new byte[100];
|
||||
/** The offset within the indexData where the next index data will be written. */
|
||||
private int indexDataOffset = 0;
|
||||
/**
|
||||
* IndexedObjectOutputStream constructor.
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
public IndexedObjectOutputStream(ObjectOutput out) throws IOException {
|
||||
super(out instanceof IObjectOutputStream ? ((IObjectOutputStream) out).getClassMap() : null, out instanceof IObjectOutputStream ? ((IObjectOutputStream) out).getClassReplacementHandler() : null, out instanceof IObjectOutputStream ? ((IObjectOutputStream) out).getSerializedObjectMap() : null, out instanceof IObjectOutputStream ? ((IObjectOutputStream) out).getDefaultNumberStyle() : AbstractStandardInputStream.STYLE_DEFAULT);
|
||||
wrapped = (OutputStream) out;
|
||||
buffer = new byte[1000];
|
||||
}//IndexedObjectOutputStream()//
|
||||
/**
|
||||
* IndexedObjectOutputStream constructor.
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
public IndexedObjectOutputStream(IObjectOutputStream out) throws IOException {
|
||||
super(out.getClassMap(), out.getClassReplacementHandler(), out.getSerializedObjectMap(), out.getDefaultNumberStyle());
|
||||
wrapped = (OutputStream) out;
|
||||
buffer = new byte[1000];
|
||||
}//IndexedObjectOutputStream()//
|
||||
/**
|
||||
* Starts the writing of a new indexed value to the stream.
|
||||
* @param index The index of the value. The deserialization must supply this index to retrieve the value.
|
||||
*/
|
||||
public void begin(int index) {
|
||||
if(nextIndex != -1) {
|
||||
//Write the index and size to the index data buffer.//
|
||||
writeIndex();
|
||||
}//if//
|
||||
|
||||
nextIndex = index;
|
||||
nextOffset = bufferOffset;
|
||||
indexCount++;
|
||||
}//begin()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractObjectOutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
//Does nothing - cannot flush since we are writing the index to the stream at the top.//
|
||||
}//flush()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractObjectOutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if(nextIndex != -1) {
|
||||
//Write the index and size to the index data buffer.//
|
||||
writeIndex();
|
||||
}//if//
|
||||
|
||||
StreamSupport.writeInt(indexCount, wrapped, StreamSupport.NUMBER_VLSF);
|
||||
wrapped.write(indexData, 0, indexDataOffset);
|
||||
wrapped.write(buffer, 0, bufferOffset);
|
||||
super.close();
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte[] bytes) throws IOException {
|
||||
ensureSpace(bytes.length);
|
||||
System.arraycopy(bytes, 0, buffer, bufferOffset, bytes.length);
|
||||
bufferOffset += bytes.length;
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws IOException {
|
||||
ensureSpace(length);
|
||||
System.arraycopy(bytes, offset, buffer, bufferOffset, length);
|
||||
bufferOffset += length;
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
ensureSpace(1);
|
||||
buffer[bufferOffset++] = (byte) b;
|
||||
}//write()//
|
||||
/**
|
||||
* Ensures the buffer is capable of adding the passed number of bytes.
|
||||
* @param availableSpace The space being requested.
|
||||
*/
|
||||
protected void ensureSpace(int availableSpace) {
|
||||
if(buffer.length - bufferOffset < availableSpace) {
|
||||
byte[] temp = new byte[bufferOffset + Math.max(availableSpace, 1000)];
|
||||
|
||||
System.arraycopy(buffer, 0, temp, 0, bufferOffset);
|
||||
buffer = temp;
|
||||
}//if//
|
||||
}//ensureSpace()//
|
||||
/**
|
||||
* Writes the next index (set by calling begin(int)) and the size of the data element.
|
||||
*/
|
||||
protected void writeIndex() {
|
||||
//Ensure that begin(int) was called prior to streaming the value.//
|
||||
if(nextIndex == -1) {
|
||||
throw new RuntimeException("Must call begin(int) prior to writing data. Each piece of data must be indexed.");
|
||||
}//if//
|
||||
|
||||
//Ensure we have enough space for two integers.//
|
||||
if(indexData.length - indexDataOffset < 8) {
|
||||
byte[] temp = new byte[indexData.length + 100];
|
||||
|
||||
System.arraycopy(indexData, 0, temp, 0, indexDataOffset);
|
||||
indexData = temp;
|
||||
}//if//
|
||||
|
||||
//Write the index number for the data element.//
|
||||
indexDataOffset += StreamSupport.writeInt(nextIndex, indexData, indexDataOffset, StreamSupport.NUMBER_VLSF);
|
||||
//Write the size of the data element.//
|
||||
indexDataOffset += StreamSupport.writeInt(bufferOffset - nextOffset, indexData, indexDataOffset, StreamSupport.NUMBER_VLSF);
|
||||
//Reset the next variables.//
|
||||
nextIndex = -1;
|
||||
nextOffset = -1;
|
||||
}//writeIndex()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return false;
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
throw new IOException("Encryption not supported at this level. The underlying stream can be encrypted if so desired.");
|
||||
}//encrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return false;
|
||||
}//isEncrypting()//
|
||||
}//IndexedObjectOutputStream//
|
||||
235
Common/src/com/common/io/ObjectInputStream.java
Normal file
235
Common/src/com/common/io/ObjectInputStream.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.util.*;
|
||||
|
||||
public class ObjectInputStream extends AbstractObjectInputStream implements IObjectStream, java.io.ObjectInput, IObjectInputStream {
|
||||
private InputStream stream = null;
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList) throws IOException {
|
||||
super(loader, classList);
|
||||
|
||||
this.stream = stream;
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList, IInstanceFactory instanceFactory) throws IOException {
|
||||
super(loader, classList, instanceFactory);
|
||||
|
||||
this.stream = stream;
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker) throws IOException {
|
||||
super(loader, null, classList, instanceFactory, classTracker);
|
||||
|
||||
this.stream = stream;
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker) throws IOException {
|
||||
super(loader, classReplacementHandler, classList, instanceFactory, classTracker);
|
||||
|
||||
this.stream = stream;
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList, int defaultNumberStyle) throws IOException {
|
||||
this(stream, loader, null, classList, null, null, defaultNumberStyle);
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList, IInstanceFactory instanceFactory, int defaultNumberStyle) throws IOException {
|
||||
this(stream, loader, null, classList, instanceFactory, null, defaultNumberStyle);
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, int defaultNumberStyle) throws IOException {
|
||||
this(stream, loader, null, classList, instanceFactory, classTracker, defaultNumberStyle);
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* ObjectInputStream constructor.
|
||||
* @param stream The input stream that will be encapsulated. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
|
||||
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
|
||||
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectInputStream(InputStream stream, ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, int defaultNumberStyle) throws IOException {
|
||||
super(loader, classReplacementHandler, classList, instanceFactory, classTracker, defaultNumberStyle);
|
||||
|
||||
this.stream = stream;
|
||||
}//ObjectInputStream()//
|
||||
/**
|
||||
* Gets the number of available bytes in the input stream.
|
||||
* @return The number of bytes that have not yet been read from the input stream.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return stream.available();
|
||||
}//available()//
|
||||
/**
|
||||
* @see IInputStream.canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).canDecrypt());
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/**
|
||||
* @see IInputStream.decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
if(stream instanceof IInputStream) {
|
||||
if(((IInputStream) stream).canDecrypt()) {
|
||||
((IInputStream) stream).decrypt(decrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//decrypt()//
|
||||
/**
|
||||
* Gets the encapsulated input stream.
|
||||
* @return Gets the input stream that this object wrappers.
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return stream;
|
||||
}//getInputStream()//
|
||||
/**
|
||||
* @see IInputStream.isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return (stream instanceof IInputStream) && (((IInputStream) stream).isDecrypting());
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Marks the stream so that the reader can reset to the current position.
|
||||
* @param readLimit The number of bytes that may be read before the mark becomes invalid.
|
||||
*/
|
||||
public void mark(int readLimit) {
|
||||
stream.mark(readLimit);
|
||||
}//mark()//
|
||||
/**
|
||||
* Determines whether the stream supports using the mark method.
|
||||
* @return Whether the mark method is supported.
|
||||
*/
|
||||
public boolean markSupported() {
|
||||
return stream.markSupported();
|
||||
}//markSupported()//
|
||||
/**
|
||||
* Reads an unsigned byte from the stream.
|
||||
* @return The unsigned byte read from the stream.
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
return stream.read();
|
||||
}//read()//
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
return stream.read(buffer);
|
||||
}//read()//
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @param offset The offset where the first read byte should be placed in the buffer.
|
||||
* @param length The number of bytes that should be read into the buffer.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
return stream.read(buffer, offset, length);
|
||||
}//read()//
|
||||
/**
|
||||
* @see IInputStream.read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int retVal;
|
||||
|
||||
if(stream instanceof IInputStream) {
|
||||
retVal = ((IInputStream) stream).read(out,length);
|
||||
}//if//
|
||||
else {
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
retVal = stream.read(bytes, 0, bytes.length);
|
||||
out.write(bytes, 0, retVal);
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/**
|
||||
* Resets this stream so that it may be re-read.
|
||||
*/
|
||||
public void reset() throws java.io.IOException {
|
||||
super.reset();
|
||||
stream.reset();
|
||||
}//reset()//
|
||||
/**
|
||||
* Skips the next <code>count</code> bytes on the stream.
|
||||
* @param count The number of bytes to skip.
|
||||
* @return The number of bytes that were skipped.
|
||||
*/
|
||||
public long skip(long count) throws IOException {
|
||||
return stream.skip(count);
|
||||
}//skip()//
|
||||
}//ObjectInputStream//
|
||||
131
Common/src/com/common/io/ObjectOutputStream.java
Normal file
131
Common/src/com/common/io/ObjectOutputStream.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.util.*;
|
||||
|
||||
/**
|
||||
* This default implementation of an object output stream uses an encapsulated stream for performing the actual data output.
|
||||
* Users can create their own composite streams using this class, or when necessary can exend AbstractObjectOutputStream to create a customized stream.
|
||||
*/
|
||||
public class ObjectOutputStream extends AbstractObjectOutputStream {
|
||||
private OutputStream stream = null; //The underlying byte stream if buffering is used.//
|
||||
/**
|
||||
* QuickOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param stream The stream that the objects get written to. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
*/
|
||||
public ObjectOutputStream(OutputStream stream, LiteHashMap classMap) throws IOException {
|
||||
this(stream, classMap, null);
|
||||
}//ObjectOutputStream()//
|
||||
/**
|
||||
* QuickOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param stream The stream that the objects get written to. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
*/
|
||||
public ObjectOutputStream(OutputStream stream, LiteHashMap classMap, IClassReplacementHandler classReplacementHandler) throws IOException {
|
||||
super(classMap, classReplacementHandler);
|
||||
this.stream = stream;
|
||||
}//ObjectOutputStream()//
|
||||
/**
|
||||
* QuickOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param stream The stream that the objects get written to. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectOutputStream(OutputStream stream, LiteHashMap classMap, int defaultNumberStyle) throws IOException {
|
||||
this(stream, classMap, null, defaultNumberStyle);
|
||||
}//ObjectOutputStream()//
|
||||
/**
|
||||
* QuickOutputStream constructor.
|
||||
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
|
||||
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
|
||||
* @param stream The stream that the objects get written to. <b>Warning: If specialized functionality provided by the IOuputStream interface is required then the entire hierarchy of passed output streams *MUST* all implement this interface or it will not properly work.</b>
|
||||
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
|
||||
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public ObjectOutputStream(OutputStream stream, LiteHashMap classMap, IClassReplacementHandler classReplacementHandler, int defaultNumberStyle) throws IOException {
|
||||
super(classMap, classReplacementHandler, defaultNumberStyle);
|
||||
this.stream = stream;
|
||||
}//ObjectOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).canEncrypt());
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
stream.close();
|
||||
}//close()//
|
||||
/**
|
||||
* @see IOutputStream.encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
if(stream instanceof IOutputStream) {
|
||||
if(((IOutputStream) stream).canEncrypt()) {
|
||||
flush();
|
||||
((IOutputStream) stream).encrypt(encrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Flushes this output stream and the encapsulated output stream.
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
stream.flush();
|
||||
}//flush()//
|
||||
/**
|
||||
* @see IOutputStream.isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return (stream instanceof IOutputStream) && (((IOutputStream) stream).isEncrypting());
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Writes the bytes to the stream.
|
||||
* @param bytes The bytes to write to the stream.
|
||||
*/
|
||||
public void write(byte[] bytes) throws IOException {
|
||||
stream.write(bytes);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to the stream.
|
||||
* @param bytes The bytes to write to the stream.
|
||||
* @param offset The offset of the first byte to write.
|
||||
* @param length the number of bytes to write.
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws IOException {
|
||||
stream.write(bytes, offset, length);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the unsigned byte to the stream.
|
||||
* @param b The unsigned byte to write to the stream.
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
stream.write(b);
|
||||
}//write()//
|
||||
}//ObjectOutputStream//
|
||||
213
Common/src/com/common/io/ObjectStream.java
Normal file
213
Common/src/com/common/io/ObjectStream.java
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.text.*;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.util.IHashMap;
|
||||
import com.common.util.LiteHashMap;
|
||||
|
||||
/**
|
||||
* A container for settings and methods relating to object streaming.
|
||||
*/
|
||||
public class ObjectStream {
|
||||
/**
|
||||
* A collection of handlers providing customized serialization handlers indexed by class name or the index of the class in the collection of class names.
|
||||
* @see com.common.io.AbstractObjectInputStream.setCustomSerializationHandler(Class, ISerializationHandler)
|
||||
* @see com.common.io.ISerializationHandler
|
||||
*/
|
||||
public static final IHashMap serializationHandlersMap = new LiteHashMap(20, new Object[][] {
|
||||
{BigDecimal.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
byte[] bytes = ((BigDecimal) value).unscaledValue().toByteArray();
|
||||
|
||||
out.writeInt(bytes.length);
|
||||
out.write(bytes);
|
||||
out.writeInt(((BigDecimal) value).scale());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
byte[] bytes = new byte[in.readInt()];
|
||||
|
||||
in.read(bytes);
|
||||
|
||||
return new BigDecimal(new BigInteger(bytes), in.readInt());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{BigInteger.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
byte[] bytes = ((BigInteger) value).toByteArray();
|
||||
|
||||
out.writeInt(bytes.length);
|
||||
out.write(bytes);
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
byte[] bytes = new byte[in.readInt()];
|
||||
|
||||
in.read(bytes);
|
||||
|
||||
return new BigInteger(bytes);
|
||||
}//deserialize()//
|
||||
}},
|
||||
{java.io.File.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
out.writeObject(((java.io.File) value).getPath());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
Object result = null;
|
||||
|
||||
try {
|
||||
result = new java.io.File((String) in.readObject());
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
return result;
|
||||
}//deserialize()//
|
||||
}},
|
||||
{Locale.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
Locale locale = (Locale) value;
|
||||
|
||||
out.writeUTF8(locale.getLanguage());
|
||||
out.writeUTF8(locale.getCountry());
|
||||
out.writeUTF8(locale.getVariant());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
String language = in.readUTF8();
|
||||
String country = in.readUTF8();
|
||||
String varient = in.readUTF8();
|
||||
|
||||
return new Locale(language, country, varient);
|
||||
}//deserialize()//
|
||||
}},
|
||||
{MessageFormat.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
MessageFormat format = (MessageFormat) value;
|
||||
Format[] formats = format.getFormats();
|
||||
|
||||
out.writeInt(formats == null ? 0 : formats.length);
|
||||
|
||||
for(int index = 0; index < formats.length; index++) {
|
||||
out.writeObject(formats[index]);
|
||||
}//for//
|
||||
|
||||
out.writeObject(format.getLocale());
|
||||
out.writeUTF8(format.toPattern());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
MessageFormat format;
|
||||
int formatCount = in.readInt();
|
||||
Format[] formats = new Format[formatCount];
|
||||
Locale locale;
|
||||
|
||||
for(int index = 0; index < formats.length; index++) {
|
||||
formats[index] = (Format) in.readObject();
|
||||
}//for//
|
||||
|
||||
locale = (Locale) in.readObject();
|
||||
|
||||
if(locale == null) {
|
||||
format = new MessageFormat(in.readUTF8());
|
||||
}//if//
|
||||
else {
|
||||
format = new MessageFormat(in.readUTF8(), locale);
|
||||
}//else//
|
||||
|
||||
if(formats != null) {
|
||||
format.setFormats(formats);
|
||||
}//if//
|
||||
|
||||
return format;
|
||||
}//deserialize()//
|
||||
}},
|
||||
{DecimalFormat.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
DecimalFormat format = (DecimalFormat) value;
|
||||
|
||||
out.writeUTF8(format.toPattern());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
return new DecimalFormat(in.readUTF8());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{ChoiceFormat.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
ChoiceFormat format = (ChoiceFormat) value;
|
||||
|
||||
out.writeUTF8(format.toPattern());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
return new ChoiceFormat(in.readUTF8());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{SimpleDateFormat.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
SimpleDateFormat format = (SimpleDateFormat) value;
|
||||
|
||||
out.writeUTF8(format.toPattern());
|
||||
out.writeUTF8(format.getTimeZone().getID());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
SimpleDateFormat result = new SimpleDateFormat(in.readUTF8());
|
||||
|
||||
result.setTimeZone(TimeZone.getTimeZone(in.readUTF8()));
|
||||
return result;
|
||||
}//deserialize()//
|
||||
}},
|
||||
{java.util.Date.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
out.writeLong(((java.util.Date) value).getTime());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
return new java.util.Date(in.readLong());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{java.sql.Date.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
out.writeLong(((java.sql.Date) value).getTime());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
return new java.sql.Date(in.readLong());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{java.sql.Time.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
out.writeLong(((java.sql.Time) value).getTime());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
return new java.sql.Time(in.readLong());
|
||||
}//deserialize()//
|
||||
}},
|
||||
{java.sql.Timestamp.class, new ISerializationHandler() {
|
||||
public void serialize(Object value, IObjectOutputStream out) throws IOException {
|
||||
out.writeLong(((java.sql.Timestamp) value).getTime());
|
||||
out.writeInt(((java.sql.Timestamp) value).getNanos());
|
||||
}//serialize()//
|
||||
public Object deserialize(IObjectInputStream in) throws IOException {
|
||||
java.sql.Timestamp result = new java.sql.Timestamp(in.readLong());
|
||||
|
||||
result.setNanos(in.readInt());
|
||||
|
||||
return result;
|
||||
}//deserialize()//
|
||||
}}
|
||||
});
|
||||
/**
|
||||
* ObjectStream constructor.
|
||||
*/
|
||||
private ObjectStream() {
|
||||
super();
|
||||
}//ObjectStream()//
|
||||
}//ObjectStream//
|
||||
34
Common/src/com/common/io/SignatureInputStream.java
Normal file
34
Common/src/com/common/io/SignatureInputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows a signature stream to be plugged into an input stream so that read bytes are decrypted using the public key (verified).
|
||||
*/
|
||||
public class SignatureInputStream extends CryptoInputStream implements IInputStream {
|
||||
private ISignatureAlgorithm algorithm = null;
|
||||
/**
|
||||
* SignatureInputStream constructor.
|
||||
*/
|
||||
public SignatureInputStream(InputStream stream, ISignatureAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalVerificationBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalSignatureBlockSize()];
|
||||
}//SignatureInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#decrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.verify(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//decrypt()//
|
||||
}//SignatureInputStream//
|
||||
34
Common/src/com/common/io/SignatureOutputStream.java
Normal file
34
Common/src/com/common/io/SignatureOutputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows a signature stream to be plugged into an output stream so that written bytes are encrypted using the private key (signed).
|
||||
*/
|
||||
public class SignatureOutputStream extends CryptoOutputStream implements IOutputStream {
|
||||
private ISignatureAlgorithm algorithm = null;
|
||||
/**
|
||||
* SignatureOutputStream constructor.
|
||||
*/
|
||||
public SignatureOutputStream(OutputStream stream, ISignatureAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalVerificationBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalSignatureBlockSize()]; //The smaller buffer.//
|
||||
}//SignatureOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#encrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.sign(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//encrypt()//
|
||||
}//SignatureOutputStream//
|
||||
146
Common/src/com/common/io/StandardInputStream.java
Normal file
146
Common/src/com/common/io/StandardInputStream.java
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class StandardInputStream extends AbstractStandardInputStream {
|
||||
private InputStream inputStream = null;
|
||||
/**
|
||||
* StandardInputStream constructor.
|
||||
*/
|
||||
public StandardInputStream(InputStream inputStream) {
|
||||
super();
|
||||
|
||||
if(inputStream == null) {
|
||||
throw new NullPointerException("Must provide a non-null input stream when constructing a StandardInputStream instance.");
|
||||
}//if//
|
||||
|
||||
this.inputStream = inputStream;
|
||||
}//StandardInputStream()//
|
||||
/**
|
||||
* Gets the number of available bytes in this input stream.
|
||||
* @return The count of bytes that may be immediatly read from the stream.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return inputStream.available();
|
||||
}//available()//
|
||||
/**
|
||||
* @see IObjectInputStream.canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return (inputStream instanceof IInputStream) && (((IInputStream) inputStream).canDecrypt());
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}//close()//
|
||||
/**
|
||||
* @see IObjectInputStream.decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws IOException {
|
||||
if(inputStream instanceof IInputStream) {
|
||||
if(((IInputStream) inputStream).canDecrypt()) {
|
||||
((IInputStream) inputStream).decrypt(decrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//decrypt()//
|
||||
/**
|
||||
* Gets the encapsulated input stream.
|
||||
* @return Gets the input stream that this object wrappers.
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}//getInputStream()//
|
||||
/**
|
||||
* @see IObjectInputStream.isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return (inputStream instanceof IInputStream) && (((IInputStream) inputStream).isDecrypting());
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Marks the stream so that the reader can reset to the current position.
|
||||
* @param readLimit The number of bytes that may be read before the mark becomes invalid.
|
||||
*/
|
||||
public void mark(int readLimit) {
|
||||
inputStream.mark(readLimit);
|
||||
}//mark()//
|
||||
/**
|
||||
* Determines whether the stream supports using the mark method.
|
||||
* @return Whether the mark method is supported.
|
||||
*/
|
||||
public boolean markSupported() {
|
||||
return inputStream.markSupported();
|
||||
}//markSupported()//
|
||||
/**
|
||||
* Reads an unsigned byte from the stream.
|
||||
* @return The unsigned byte read from the stream.
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}//read()//
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
return inputStream.read(buffer);
|
||||
}//read()//
|
||||
/**
|
||||
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
|
||||
* @param buffer The buffer where the read bytes will be placed.
|
||||
* @param offset The offset where the first read byte should be placed in the buffer.
|
||||
* @param length The number of bytes that should be read into the buffer.
|
||||
* @return The number of bytes read into the buffer.
|
||||
*/
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
return inputStream.read(buffer, offset, length);
|
||||
}//read()//
|
||||
/**
|
||||
* @see IInputStream.read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
int retVal;
|
||||
|
||||
if(inputStream instanceof IInputStream) {
|
||||
retVal = ((IInputStream) inputStream).read(out,length);
|
||||
}//if//
|
||||
else {
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
retVal = inputStream.read(bytes, 0, bytes.length);
|
||||
out.write(bytes, 0, retVal);
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//read()//
|
||||
/**
|
||||
* Resets the stream by telling the encapsulated stream to reset.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
inputStream.reset();
|
||||
}//reset()//
|
||||
/**
|
||||
* Skips the next <code>count</code> bytes on the stream.
|
||||
* @param count The number of bytes to skip.
|
||||
* @return The number of bytes that were skipped.
|
||||
*/
|
||||
public long skip(long count) throws IOException {
|
||||
return inputStream.skip(count);
|
||||
}//skip()//
|
||||
}//StandardInputStream//
|
||||
108
Common/src/com/common/io/StandardOutputStream.java
Normal file
108
Common/src/com/common/io/StandardOutputStream.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class StandardOutputStream extends AbstractStandardOutputStream {
|
||||
private OutputStream outputStream = null;
|
||||
/**
|
||||
* StandardOutputStream constructor.
|
||||
* @param outputStream The stream to encapsulate.
|
||||
*/
|
||||
public StandardOutputStream(OutputStream outputStream) {
|
||||
super();
|
||||
|
||||
if(outputStream == null) {
|
||||
throw new NullPointerException("Must provide a non-null output stream when constructing a StandardOutputStream instance.");
|
||||
}//if//
|
||||
|
||||
this.outputStream = outputStream;
|
||||
}//StandardOutputStream()//
|
||||
/**
|
||||
* StandardOutputStream constructor.
|
||||
* @param outputStream The stream to encapsulate.
|
||||
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
|
||||
*/
|
||||
public StandardOutputStream(OutputStream outputStream, int defaultNumberStyle) {
|
||||
super(defaultNumberStyle);
|
||||
|
||||
if(outputStream == null) {
|
||||
throw new NullPointerException("Must provide a non-null output stream when constructing a StandardOutputStream instance.");
|
||||
}//if//
|
||||
|
||||
this.outputStream = outputStream;
|
||||
}//StandardOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return (outputStream instanceof IOutputStream) && (((IOutputStream) outputStream).canEncrypt());
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
outputStream.close();
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
if(outputStream instanceof IOutputStream) {
|
||||
if(((IOutputStream) outputStream).canEncrypt()) {
|
||||
flush();
|
||||
((IOutputStream) outputStream).encrypt(encrypt);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
||||
}//else//
|
||||
}//encrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return (outputStream instanceof IOutputStream) && (((IOutputStream) outputStream).isEncrypting());
|
||||
}//isEncrypting()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
outputStream.flush();
|
||||
}//flush()//
|
||||
/**
|
||||
* Gets the encapsulated output stream.
|
||||
* @return Gets the output stream that this object wrappers.
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}//getOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte[] bytes) throws IOException {
|
||||
outputStream.write(bytes);
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws IOException {
|
||||
outputStream.write(bytes, offset, length);
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.AbstractStandardOutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
outputStream.write(b);
|
||||
}//write()//
|
||||
}//StandardOutputStream//
|
||||
3191
Common/src/com/common/io/StreamSupport.java
Normal file
3191
Common/src/com/common/io/StreamSupport.java
Normal file
File diff suppressed because it is too large
Load Diff
37
Common/src/com/common/io/StringBufferPrintWriter.java
Normal file
37
Common/src/com/common/io/StringBufferPrintWriter.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2006 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/*
|
||||
* A print writer that simply wrappers a string buffer and whose string can be retreived by calling toString().
|
||||
* This is useful for retrieving a stack trace using <code>exception.printStackTrace(PrintWriter)</code>.
|
||||
*/
|
||||
public class StringBufferPrintWriter extends PrintWriter {
|
||||
/**
|
||||
* StringBufferPrintWriter constructor.
|
||||
* @param file
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public StringBufferPrintWriter(StringBuffer buffer) {
|
||||
super(new StringBufferWriter(buffer));
|
||||
}//StringBufferPrintWriter()//
|
||||
/**
|
||||
* StringBufferPrintWriter constructor.
|
||||
*/
|
||||
public StringBufferPrintWriter() {
|
||||
super(new StringBufferWriter(new StringBuffer(1000)));
|
||||
}//StringBufferPrintWriter()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return ((StringBufferWriter) out).toString();
|
||||
}//toString()//
|
||||
}//StringBufferPrintWriter//
|
||||
63
Common/src/com/common/io/StringBufferWriter.java
Normal file
63
Common/src/com/common/io/StringBufferWriter.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2006 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/*
|
||||
* A writer that simply wrappers a string buffer and whose string can be retreived by calling toString().
|
||||
*/
|
||||
public class StringBufferWriter extends Writer {
|
||||
private StringBuffer buffer = null;
|
||||
private boolean isClosed = false;
|
||||
/**
|
||||
* StringBufferWriter constructor.
|
||||
*/
|
||||
public StringBufferWriter() {
|
||||
super();
|
||||
this.buffer = new StringBuffer(1000);
|
||||
}//StringBufferWriter()//
|
||||
/**
|
||||
* StringBufferWriter constructor.
|
||||
* @param buffer The buffer to be appended to.
|
||||
*/
|
||||
public StringBufferWriter(StringBuffer buffer) {
|
||||
super();
|
||||
this.buffer = buffer;
|
||||
}//StringBufferWriter()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Writer#write(char[], int, int)
|
||||
*/
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
if(!isClosed) {
|
||||
buffer.append(cbuf, off, len);
|
||||
}//if//
|
||||
else {
|
||||
throw new IOException("Closed writer cannot be written to.");
|
||||
}//else//
|
||||
}//write()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Writer#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
//Does nothing.//
|
||||
}//flush()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.Writer#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
isClosed = true;
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return buffer.toString();
|
||||
}//toString()//
|
||||
}//StringBufferWriter//
|
||||
34
Common/src/com/common/io/SymmetricInputStream.java
Normal file
34
Common/src/com/common/io/SymmetricInputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an symmetricly encrypted stream to be plugged into an input stream so that read bytes are decrypted using the private key.
|
||||
*/
|
||||
public class SymmetricInputStream extends CryptoInputStream implements IInputStream {
|
||||
private ISymmetricAlgorithm algorithm = null;
|
||||
/**
|
||||
* SymmetricInputStream constructor.
|
||||
*/
|
||||
public SymmetricInputStream(InputStream stream, ISymmetricAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
|
||||
}//SymmetricInputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#decrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.decrypt(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//decrypt()//
|
||||
}//SymmetricInputStream//
|
||||
34
Common/src/com/common/io/SymmetricOutputStream.java
Normal file
34
Common/src/com/common/io/SymmetricOutputStream.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.common.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import com.common.security.*;
|
||||
|
||||
/*
|
||||
* This class allows an asymmetric stream to be plugged into an output stream so that written bytes are encrypted using the public key.
|
||||
*/
|
||||
public class SymmetricOutputStream extends CryptoOutputStream implements IOutputStream {
|
||||
private ISymmetricAlgorithm algorithm = null;
|
||||
/**
|
||||
* AsymmetricOutputStream constructor.
|
||||
*/
|
||||
public SymmetricOutputStream(OutputStream stream, ISymmetricAlgorithm algorithm) {
|
||||
super(stream, algorithm);
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
|
||||
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
|
||||
}//AsymmetricOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.CryptoOutputStream#encrypt(byte[], int, int, byte[], int)
|
||||
*/
|
||||
protected int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
|
||||
return algorithm.encrypt(data, dataOffset, dataLength, output, outputOffset);
|
||||
}//encrypt()//
|
||||
}//SymmetricOutputStream//
|
||||
Reference in New Issue
Block a user