/**
*
* Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geronimo.interop.rmi.iiop;
import org.apache.geronimo.interop.*;
import org.apache.geronimo.interop.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
public class ObjectOutputStream extends java.io.ObjectOutputStream
{
public static ObjectOutputStream getInstance()
{
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream();
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
oos = null;
}
return oos;
}
public static ObjectOutputStream getInstance(CdrOutputStream cdrOutput)
{
ObjectOutputStream output = getInstance();
output.init(cdrOutput);
return output;
}
public static ObjectOutputStream getPooledInstance()
{
ObjectOutputStream output = null;
if (output == null)
{
output = getInstance();
}
return output;
}
// -----------------------------------------------------------------------
// private data
// -----------------------------------------------------------------------
protected static class StreamState
{
ValueType type;
Object value;
int offset;
org.apache.geronimo.interop.rmi.iiop.ObjectOutputStream.PutField putField;
StreamState(ValueType type, Object value, int offset)
{
this.type = type;
this.value = value;
this.offset = offset;
}
}
// -----------------------------------------------------------------------
// public data
// -----------------------------------------------------------------------
public CdrOutputStream _cdrOutput;
public boolean _hasException;
public Object[] thisAsObjectArray;
// -----------------------------------------------------------------------
// private data
// -----------------------------------------------------------------------
private static ValueType OBJECT_VALUE_TYPE = ValueType.getInstance(java.lang.Object.class);
private static boolean OBJECT_VALUE_TYPE_INIT = false;
private ArrayList _stack = null;
private SimpleIdentityHashMap _indirection;
private int _blockSizeIndex = -1;
private int _endLevel;
private int _endTagIndex;
private boolean _inBlock = false;
private boolean _isChunked = false;
private int _booleanIndex = -1;
// -----------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------
public ObjectOutputStream() throws IOException
{
super();
}
public void $reset()
{
_cdrOutput.reset();
if (_indirection != null)
{
_indirection.clear();
}
if (_stack != null)
{
_stack.clear();
}
_blockSizeIndex = -1;
_endLevel = 0;
_endTagIndex = 0;
_inBlock = false;
_isChunked = false;
_booleanIndex = -1;
}
public void recycle()
{
$reset();
}
// -----------------------------------------------------------------------
// public methods from java.io.ObjectOutputStream
// -----------------------------------------------------------------------
public void writeBoolean(boolean value)
{
_cdrOutput.write_boolean(value);
}
public void writeChar(char value)
{
_cdrOutput.write_wchar(value);
}
public void writeByte(byte value)
{
_cdrOutput.write_octet(value);
}
public void writeShort(short value)
{
_cdrOutput.write_short(value);
}
public void writeInt(int value)
{
_cdrOutput.write_long(value);
}
public void writeLong(long value)
{
_cdrOutput.write_longlong(value);
}
public void writeFloat(float value)
{
_cdrOutput.write_float(value);
}
public void writeDouble(double value)
{
_cdrOutput.write_double(value);
}
public void writeObjectOverride(Object value)
{
writeObject(OBJECT_VALUE_TYPE, value, true);
}
public void defaultWriteObject() throws IOException
{
StreamState state = top();
// TODO: check this
int saveOffset = _cdrOutput._offset;
_cdrOutput._offset = _booleanIndex;
_cdrOutput.write_boolean(true);
_cdrOutput._offset = saveOffset;
writeDeclaredFields(state.type, state.value);
}
// -----------------------------------------------------------------------
// public methods used by generated and package-internal code
// -----------------------------------------------------------------------
public boolean hasException()
{
return _hasException;
}
public void writeException(ValueType type, Exception value)
{
String className = type._class.getName();
String exType = StringUtil.removeSuffix(className, "Exception") + "Ex";
String repositoryID = "IDL:" + exType.replace('.', '/') + ":1.0";
_cdrOutput.write_string(repositoryID);
writeObject(type, value);
_hasException = true;
}
public void writeObject(ValueType type, Object value)
{
writeObject(type, value, false);
}
// -----------------------------------------------------------------------
// protected methods
// -----------------------------------------------------------------------
protected void init(CdrOutputStream cdrOutput)
{
_cdrOutput = cdrOutput;
thisAsObjectArray = new Object[] { this };
}
protected void putIndirection(Object value, Integer ref)
{
if (_indirection == null)
{
_indirection = new SimpleIdentityHashMap(8);
}
_indirection.put(value, ref);
}
protected void writeObject(ValueType declaredType, Object value, boolean calledFromCustomSerialization)
{
ValueType actualType = declaredType;
while (value != null)
{
Class vc = value.getClass();
if (vc != declaredType._class)
{
actualType = ValueType.getInstance(vc);
}
if (actualType.hasWriteReplace)
{
value = actualType.writeReplace(value);
}
else
{
break;
}
}
boolean saveIsChunked = _isChunked;
if (_inBlock)
{
if (actualType != null)
{
if (!declaredType.isAny || calledFromCustomSerialization)
{
endBlock();
}
}
}
if (value == null)
{
if (calledFromCustomSerialization)
{
_cdrOutput.write_boolean(actualType.isObjectRef);
if(actualType.isObjectRef)
{
writeObjectRef(value);
endBlock();
}
else
{
_cdrOutput.write_long(ValueType.NULL_VALUE_TAG);
}
return;
}
if (declaredType.isAny)
{
_cdrOutput.write_TypeCode(ValueType.TC_ABSTRACT_BASE);
_cdrOutput.write_boolean(false);
}
if (declaredType.isObjectRef)
{
writeObjectRef(value);
}
else
{
if (declaredType.isAbstractInterface)
{
_cdrOutput.write_boolean(false);
}
_cdrOutput.write_long(ValueType.NULL_VALUE_TAG);
}
return;
}
if (declaredType.isAny && ! calledFromCustomSerialization)
{
org.omg.CORBA.TypeCode tc = actualType.tc;
_cdrOutput.write_TypeCode(tc);
if (!actualType.isAny)
{
endBlock();
}
}
else if (declaredType.isAbstractInterface || calledFromCustomSerialization)
{
_cdrOutput.write_boolean(actualType.isObjectRef);
if (actualType.isObjectRef)
{
writeObjectRef(value);
return;
}
}
if (actualType.isObjectRef)
{
writeObjectRef(value);
return;
}
Integer ref = _indirection == null ? null : (Integer)_indirection.get(value);
if (ref != null)
{
_cdrOutput.write_long(ValueType.INDIRECTION_TAG);
_cdrOutput.write_long(ref.intValue() - _cdrOutput._offset);
return;
}
else
{
_cdrOutput.write_align(4, 4); // write any necessary padding
ref = IntegerCache.get(_cdrOutput._offset);
putIndirection(value, ref);
}
if (saveIsChunked || actualType.requiresCustomSerialization)
{
_cdrOutput.write_long(ValueType.TRUNCATABLE_SINGLE_TYPE_VALUE_TAG);
_isChunked = true;
}
else
{
_cdrOutput.write_long(ValueType.SINGLE_TYPE_VALUE_TAG);
_isChunked = false;
}
writeMetaString(actualType.id);
startBlock();
switch (actualType.readWriteCase)
{
case ValueType.CASE_ARRAY:
writeArray(actualType, value);
break;
case ValueType.CASE_CLASS:
writeClassDesc((java.lang.Class)value);
break;
case ValueType.CASE_IDL_ENTITY:
actualType.helper.write(this, value);
break;
// case ValueType.IDL_OBJECT: // already handled above
case ValueType.CASE_STRING:
_cdrOutput.write_wstring((String)value);
break;
default:
writeObjectState(actualType, value);
}
endBlock();
writeEndTag(declaredType, actualType, calledFromCustomSerialization);
_isChunked = saveIsChunked;
}
protected void writeMetaString(String ms)
{
Integer ref = (Integer)_indirection.get(ms);
if (ref != null)
{
_cdrOutput.write_long(ValueType.INDIRECTION_TAG);
_cdrOutput.write_long(ref.intValue() - _cdrOutput._offset);
}
else
{
ref = IntegerCache.get(_cdrOutput._offset);
_cdrOutput.write_string(ms);
putIndirection(ms, ref);
}
}
protected void writeObjectState(ValueType type, Object value)
{
if (type.isExternalizable)
{
_cdrOutput.write_octet((byte)1);
type.writeExternal(value, this);
return;
}
if (type.hasParentState)
{
writeObjectState(type.parent, value);
}
if (type.hasWriteObject)
{
push(new StreamState(type, value, _cdrOutput._offset));
if (type.skipCustomFlags)
{
_booleanIndex = _cdrOutput._offset;
}
else
{
_cdrOutput.write_octet((byte)1);
_cdrOutput.write_boolean(false);
_booleanIndex = _cdrOutput._offset - 1;
}
type.writeObject(value, this);
pop();
}
else
{
writeDeclaredFields(type, value);
}
}
protected void writeDeclaredFields(ValueType type, Object value)
{
int n = type.fields.length;
for (int f = 0; f < n; f++)
{
ValueTypeField field = type.fields[f];
int primitive = field.primitive;
if (primitive != 0)
{
writePrimitive(primitive, field, value);
}
else
{
writeObject(field.type, field.get(value), false);
}
}
}
protected void writeClassDesc(Class theClass)
{
writeObject(ValueType.STRING_VALUE_TYPE, null); // codebase URL
writeObject(ValueType.STRING_VALUE_TYPE, ValueType.getInstance(theClass).id);
}
protected void writeArray(ValueType arrayType, Object value)
{
int primitive = arrayType.primitiveArray;
if (primitive != 0)
{
arrayType.helper.write(this, value);
}
else
{
Object[] array = (Object[])value;
int n = array.length;
_cdrOutput.write_ulong(n);
for (int i = 0; i < n; i++)
{
writeObject(arrayType.element, array[i], false);
}
}
}
protected void writePrimitive(int primitive, ValueTypeField field, Object value)
{
switch (primitive)
{
case PrimitiveType.BOOLEAN:
_cdrOutput.write_boolean(field.getBoolean(value));
break;
case PrimitiveType.BYTE:
_cdrOutput.write_octet(field.getByte(value));
break;
case PrimitiveType.CHAR:
_cdrOutput.write_wchar(field.getChar(value));
break;
case PrimitiveType.DOUBLE:
_cdrOutput.write_double(field.getDouble(value));
break;
case PrimitiveType.FLOAT:
_cdrOutput.write_float(field.getFloat(value));
break;
case PrimitiveType.INT:
_cdrOutput.write_long(field.getInt(value));
break;
case PrimitiveType.LONG:
_cdrOutput.write_longlong(field.getLong(value));
break;
case PrimitiveType.SHORT:
_cdrOutput.write_short(field.getShort(value));
break;
default:
throw new IllegalStateException();
}
}
public void startBlock()
{
if (! _isChunked)
{
return;
}
_endLevel--;
_cdrOutput.write_long(0);
_inBlock = true;
_blockSizeIndex = _cdrOutput._offset - 4;
}
public void endBlock()
{
if (! _inBlock)
{
return;
}
_inBlock = false;
int oldSize = _cdrOutput._offset;
_cdrOutput._offset = _blockSizeIndex;
_cdrOutput.write_long(oldSize - _blockSizeIndex - 4);
_cdrOutput._offset = oldSize;
_blockSizeIndex = -1;
}
protected void writeEndTag()
{
if (_isChunked)
{
if (_endTagIndex == _cdrOutput._offset - 8)
{
_cdrOutput._offset -= 8;
}
_cdrOutput.write_long(_endLevel);
_endTagIndex = _cdrOutput._offset - 4;
if (_endLevel != -1)
{
_cdrOutput.write_long(1);
}
else // _endLevel == -1
{
_cdrOutput._offset -=4;
_cdrOutput.write_long(-1);
_isChunked = false;
}
_endLevel++;
}
}
protected void writeEndTag(ValueType declaredType, ValueType actualType,
boolean calledFromCustomSerialization)
{
if (_isChunked)
{
if (_endTagIndex == _cdrOutput._offset - 8)
{
_cdrOutput._offset -= 8;
}
_cdrOutput.write_long(_endLevel);
_endTagIndex = _cdrOutput._offset - 4;
if (_endLevel != -1)
{
if(declaredType.isAny && !actualType.isAny && !calledFromCustomSerialization)
{
startBlock();
_endLevel++;
}
else
{
_cdrOutput.write_long(1);
}
}
else // _endLevel == -1
{
_cdrOutput._offset -=4;
_cdrOutput.write_long(-1);
_isChunked = false;
}
_endLevel++;
}
}
private void writeObjectRef(java.lang.Object value)
{
if(value instanceof org.apache.geronimo.interop.rmi.iiop.ObjectRef || value == null)
{
_cdrOutput.write_Object((org.omg.CORBA.Object)value);
}
else if (value instanceof RemoteInterface)
{
ObjectRef objectRef = ((RemoteInterface)value).getObjectRef();
value = objectRef;
_cdrOutput.write_Object((org.omg.CORBA.Object)value);
}
else
{
writeForeignObjectRef(value);
}
}
private void writeForeignObjectRef(java.lang.Object value)
{
if (value instanceof java.rmi.Remote)
{
try
{
value = (org.omg.CORBA.Object)javax.rmi.PortableRemoteObject.toStub((java.rmi.Remote)value);
}
catch (java.rmi.NoSuchObjectException ex)
{
throw new org.omg.CORBA.MARSHAL(ExceptionUtil.causedBy(ex));
}
}
if (value instanceof org.omg.CORBA.Object)
{
try
{
org.omg.CORBA.Object object = (org.omg.CORBA.Object)value;
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[0], null);
orb.create_output_stream().write_Object(object);
String ior = orb.object_to_string(object);
org.apache.geronimo.interop.rmi.iiop.ObjectRef objectRef = org.apache.geronimo.interop.rmi.iiop.ObjectRef.$getObjectFromIOR(ior);
_cdrOutput.write_Object((org.omg.CORBA.Object)objectRef);
}
catch (Exception ex)
{
throw new org.omg.CORBA.MARSHAL(ExceptionUtil.causedBy(ex));
}
}
else
{
throw new org.omg.CORBA.MARSHAL("writeObjectRef: " + value.getClass().getName());
}
}
public java.io.ObjectOutputStream.PutField putFields() throws IOException
{
StreamState state = top();
Class currentClass = state.type.getTheClass();
if(currentClass == null)
{
throw new IOException("putFields: class from ValueType is null");
}
java.io.ObjectStreamClass osc = ObjectStreamClass.lookup(currentClass);
if(osc == null)
{
throw new IOException("putFields: ObjectSteamClass is null");
}
org.apache.geronimo.interop.rmi.iiop.PutField pf = new org.apache.geronimo.interop.rmi.iiop.PutField(osc);
state.putField = pf;
return pf;
}
public void writeFields() throws IOException
{
StreamState state = top();
if(state.putField == null)
{
throw new IOException("writeFields: PutField object is null");
}
org.apache.geronimo.interop.rmi.iiop.PutField pf = (org.apache.geronimo.interop.rmi.iiop.PutField)state.putField;
pf.writeFields(this);
}
protected void push(StreamState state)
{
if (_stack == null)
{
_stack = new ArrayList();
}
_stack.add(state);
}
protected void pop()
{
int n = _stack.size();
if (n == 0)
{
throw new SystemException("pop: state stack empty");
}
_stack.remove(n - 1);
}
private StreamState top()
{
int n = _stack.size();
if (n == 0)
{
throw new SystemException("top: state stack empty");
}
return (StreamState)_stack.get(n - 1);
}
}