/*************************************************************************
*
* $RCSfile: Unmarshal.java,v $
*
* $Revision: 1.3 $
*
* last change: $Author: kr $ $Date: 2001/01/16 18:01:30 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (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.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
package com.sun.star.lib.uno.protocols.iiop;
import java.io.DataInputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Hashtable;
import com.sun.star.corba.CorbaString8;
import com.sun.star.corba.CorbaUnion;
import com.sun.star.corba.ObjectKey;
import com.sun.star.corba.TCKind;
import com.sun.star.uno.Any;
import com.sun.star.uno.Ascii;
import com.sun.star.uno.AsciiString;
import com.sun.star.uno.Enum;
import com.sun.star.uno.IBridge;
import com.sun.star.uno.Type;
import com.sun.star.uno.TypeClass;
import com.sun.star.uno.Union;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XInterface;
import com.sun.star.corba.iiop.ProfileBody_1_1;
import com.sun.star.corba.iop.IOR;
import com.sun.star.corba.giop.ReplyHeader_1_2;
import com.sun.star.lib.uno.environments.remote.IUnmarshal;
import com.sun.star.lib.uno.environments.remote.Protocol;
import com.sun.star.lib.uno.environments.remote.ThreadID;
import com.sun.star.lib.uno.typedesc.TypeDescription;
import com.sun.star.lib.uno.typeinfo.MemberTypeInfo;
final class Unmarshal extends CDRInputStream implements IUnmarshal {
public static boolean DEBUG = false;
static final TypeDescription __asciiTypeDescription = TypeDescription.getTypeDescription(Ascii.class);
static final TypeDescription __asciiStringTypeDescription = TypeDescription.getTypeDescription(AsciiString.class);
static final TypeDescription __IORTypeDescription = TypeDescription.getTypeDescription(IOR.class);
static final TypeDescription __ProfileBody_1_1TypeDescription = TypeDescription.getTypeDescription(ProfileBody_1_1.class);
static final TypeDescription __ObjectKeyTypeDescription = TypeDescription.getTypeDescription(ObjectKey.class);
static final TypeDescription __xInterfaceTypeDescription = TypeDescription.getTypeDescription(XInterface.class);
static class I2U {
TypeClass _typeClass;
TypeDescription _typeDescription;
I2U(TypeClass typeClass, TypeDescription typeDescription) {
_typeClass = typeClass;
_typeDescription = typeDescription;
}
}
// new I2U(TypeClass.UNSIGNED_SHORT.getValue(), Short.TYPE, Short.class, null,), //ushort -> ushort, 4 -> 5
// new I2U(TypeClass.UNSIGNED_LONG.getValue(), Integer.TYPE, Integer.class), //ulong -> ulong, 5 -> 7
// new I2U(TypeClass.UNSIGNED_HYPER.getValue(), Long.TYPE, Long.class), //ulonglong -> uhyper, 24 -> 9
final static I2U IIOP2UNOTypeClass[] = new I2U[]{
new I2U(TypeClass.VOID, TypeDescription.__void_TypeDescription), //null -> void, 0 ->0
new I2U(TypeClass.VOID, TypeDescription.__void_TypeDescription), //void -> void, 1 -> 0
new I2U(TypeClass.SHORT, TypeDescription.__short_TypeDescription), //short -> short, 2 -> 4
new I2U(TypeClass.LONG, TypeDescription.__long_TypeDescription), //long -> long, 3 -> 6
new I2U(TypeClass.UNSIGNED_SHORT, null), // ushort, 4 -> 5, not supported
new I2U(TypeClass.UNSIGNED_LONG, null), //ulong -> ulong, 5 -> 7, not supported
new I2U(TypeClass.FLOAT, TypeDescription.__float_TypeDescription), //float -> float, 6 -> 10
new I2U(TypeClass.DOUBLE, TypeDescription.__double_TypeDescription), //double -> double, 7 -> 11
new I2U(TypeClass.BOOLEAN, TypeDescription.__boolean_TypeDescription), //bool -> bool, 8 -> 2
new I2U(TypeClass.UNKNOWN, __asciiTypeDescription), //ascii -> ???, 9 -> 27
new I2U(TypeClass.BYTE, TypeDescription.__byte_TypeDescription), //octet -> byte, 10 -> 3
new I2U(TypeClass.ANY, TypeDescription.__any_TypeDescription), //any -> any, 11 -> 14
new I2U(TypeClass.TYPE, TypeDescription.__type_TypeDescription), //TypeCode -> type, 12 -> 13
new I2U(TypeClass.UNKNOWN, null), //Principal -> ???, 13 -> 27
new I2U(TypeClass.INTERFACE, null), //objref -> interface, 14 -> 22
new I2U(TypeClass.STRUCT, null), //struct -> struct, 15 -> 17
new I2U(TypeClass.UNION, null), //union -> union, 16 -> 18
new I2U(TypeClass.ENUM, null), //enum -> enum, 17 -> 15
new I2U(TypeClass.UNKNOWN, __asciiStringTypeDescription), //asciistring -> ???, 18 -> 27
new I2U(TypeClass.SEQUENCE, null), //sequence -> sequence, 19 -> 20
new I2U(TypeClass.ARRAY, null), //array -> array, 20 -> 21
new I2U(TypeClass.TYPEDEF, null), //alias -> typedef, 21 -> 16
new I2U(TypeClass.EXCEPTION, null), //exception -> exception, 22 -> 19
new I2U(TypeClass.HYPER, TypeDescription.__hyper_TypeDescription), //longlong -> hyper, 23 -> 8
new I2U(TypeClass.UNSIGNED_HYPER, null), //ulonglong -> uhyper, 24 -> 9, not supported
new I2U(TypeClass.UNKNOWN, null), //longdouble -> ???, 25 -> 27
new I2U(TypeClass.CHAR, TypeDescription.__char_TypeDescription), //unicode -> unicode, 26 -> 1
new I2U(TypeClass.STRING, TypeDescription.__string_TypeDescription), //unicodestring-> unicodestring, 27 -> 12
new I2U(TypeClass.UNKNOWN, null), //fixed -> ???, 28 -> 27
new I2U(TypeClass.UNKNOWN, null), //value -> ???, 29 -> 27
new I2U(TypeClass.UNKNOWN, null), //value_box -> ???, 30 -> 27
new I2U(TypeClass.UNKNOWN, null), //native -> ???, 31 -> 27
new I2U(TypeClass.UNKNOWN, null) //abstract_interface -> ???, 32 -> 27
};
// The last type kind read with the read_typeclass method. Only usefull for spead up.
private int LastIIOPTypeKind;
private void todo() throws Exception {
throw new Exception(getClass().getName() + " - todo: not implemented");
}
protected IBridge _bridge;
Unmarshal(byte [] Buffer, int size, boolean littleEndian, IBridge bridge) {
super(Buffer, size, littleEndian);
_bridge = bridge;
}
/** Return the proper type kind of a class
*/
static int classToIIOPTypeKind(TypeDescription typeDescription){
int nLen = IIOP2UNOTypeClass.length;
int result = TCKind.tk_struct_value;
//strat with 0, so no unsigned types occure
int i;
for(i = 0; i != nLen; ++i)
if( typeDescription.equals(IIOP2UNOTypeClass[i]._typeDescription) ) {
result = i;
break;
}
if(i >= nLen) {
// workaround for: isAssignableFrom bug with jdk blackdown 118 under linux
// __getDeclaredFields(type);
/*if(JavaClass == com.sun.star.corba.CorbaString8.class) //////////////////////////////////////////////////
result = TCKind.tk_string.getValue();
else */
if(typeDescription.getTypeClass() == TypeClass.SEQUENCE)
result = TCKind.tk_sequence.getValue();
else if(typeDescription.getTypeClass() == TypeClass.EXCEPTION)
result = TCKind.tk_except.getValue();
else if(typeDescription.getTypeClass() == TypeClass.ENUM)
result = TCKind.tk_enum.getValue();
else if(typeDescription.getTypeClass() == TypeClass.UNION)
result = TCKind.tk_union.getValue();
// this is (like write_union) only temporaer
else if(com.sun.star.corba.CorbaUnion.class.isAssignableFrom(typeDescription.getZClass()))
result = TCKind.tk_union.getValue();
// any ?
else if(Object.class == typeDescription.getZClass()
|| Number.class.isAssignableFrom(typeDescription.getZClass())
|| Character.class == typeDescription.getZClass()
|| Boolean.class == typeDescription.getZClass()) {
result = TCKind.tk_any.getValue();
}
else if(typeDescription.getTypeClass() == TypeClass.INTERFACE)
result = TCKind.tk_objref.getValue();
}
// if(DEBUG) System.err.println("##### Unmarshal.classToIIOPTypeKind:" + type + " " + result);
return result;
}
private TypeDescription readTypeDescription() throws Exception {
TypeDescription result = null;
//Class return = null;
String TypeName = null;
int kind = read_long();
int nCount = 0;
int nBound = 0;
switch(kind) {
case TCKind.tk_Principal_value: todo(); break;
case TCKind.tk_objref_value:
TypeName = read_asciistring();
read_asciistring(); // dummy
break;
case TCKind.tk_struct_value:
TypeName = read_asciistring();
read_asciistring();// dummy
nCount = read_long();
for(int i = 0; i < nCount; ++ i) {
read_asciistring(); // member name
readTypeDescription();
}
break;
case TCKind.tk_union_value:
TypeName = read_asciistring();
read_asciistring(); // dummy
TypeDescription descreminator = readTypeDescription();// Descriminator type code
int nDefault = read_long(); // index of default
nCount = read_long();// count of members
for(int i = 0; i < nCount; ++ i) {// add members of the unions
// value of descriminator
todo();
// member name
read_asciistring();
//typecode of the member
readTypeDescription();
}
break;
case TCKind.tk_enum_value:
TypeName = read_asciistring();
read_asciistring(); // dummy
nCount = read_long();// all enum names
for(int i = 0; i < nCount; ++ i)
read_asciistring(); // member name
break;
case TCKind.tk_string_value:
// read the bounds of an string
nBound = read_long();
break;
case TCKind.tk_sequence_value:
TypeDescription elementType = readTypeDescription();
TypeName = "[]" + elementType.getTypeName();
nBound = read_long();
if(nBound != 0)
todo();
result = TypeDescription.getTypeDescription(TypeName);
break;
case TCKind.tk_except_value:
TypeName = read_asciistring();
// dummy
read_asciistring();
nCount = read_long();
for(int i = 0;i < nCount; ++ i){
read_asciistring(); // member name
readTypeDescription();
}
break;
case TCKind.tk_wstring_value:
// read the bounds of an string
nBound = read_long();
break;
}
LastIIOPTypeKind = kind;
if(IIOP2UNOTypeClass[kind]._typeDescription != null)
result = IIOP2UNOTypeClass[kind]._typeDescription;
else
result = TypeDescription.getTypeDescription(TypeName);
// result = TypeDescription.getType(IIOP2UNOTypeClass[kind]._typeClass, TypeName);
if(DEBUG); System.err.println("##### " + getClass().getName() + " - read_type - kind:" + result + " " + kind);
return result;
}
Boolean readBoolean() throws Exception {
Boolean result = new Boolean(read_boolean());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readBoolean:" + result);
return result;
}
Byte readByte() throws Exception {
Byte result = new Byte(read_octet());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readByte:" + result);
return result;
}
Character readCharacter() throws Exception {
Character result = new Character(read_ascii());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readChar:" + result);
return result;
}
Short readShort() throws Exception {
Short result = new Short(read_short());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readShort:" + result);
return result;
}
Integer readInteger() throws Exception {
Integer result = new Integer(read_long());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readInteger:" + result);
return result;
}
Double readDouble() throws Exception {
Double result = new Double(read_double());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readDouble:" + result);
return result;
}
Float readFloat() throws Exception {
Float result = new Float(read_float());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readFloat:" + result);
return result;
}
Long readLong() throws Exception {
Long result = new Long(read_longlong());
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readLong:" + result);
return result;
}
Throwable readThrowable() throws Exception {
String typeName = read_asciistring();
TypeDescription typeDescription = TypeDescription.getTypeDescription(typeName);
String message = read_unicodestring();
Constructor constructor = typeDescription.getZClass().getConstructor(new Class[]{String.class});
Throwable throwable = (Throwable)constructor.newInstance(new Object[]{message});
readStruct(typeDescription, throwable);
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readThrowable:" + throwable);
return throwable;
}
void readStruct(TypeDescription typeDescription, Object object) throws Exception {
Field fields[] = typeDescription.getFields();
for(int i = 0; i < fields.length; ++ i) {
if((fields[i].getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) { // neither static nor transient ?
MemberTypeInfo memberTypeInfo = typeDescription.getMemberTypeInfo(fields[i].getName());
// default the member type to the declared type
Class zInterface = fields[i].getType();
if(memberTypeInfo != null) {
if(memberTypeInfo.isAny()) // is the member an any?
if(zInterface.isArray())
zInterface = Class.forName("[Lcom.sun.star.uno.Any;");
else
zInterface = Any.class;
else if(memberTypeInfo.isInterface()) { // is the member an interface ?
Class xInterface = zInterface;
if(!XInterface.class.isAssignableFrom(fields[i].getType())) // is the member type not derived of XInterface ?
xInterface = XInterface.class; // ensure that we get at least an XInterface
if(zInterface.isArray())
zInterface = Class.forName("[L" + xInterface.getName() + ";");
else
zInterface = xInterface;
}
}
fields[i].set(object, readObject(TypeDescription.getTypeDescription(zInterface)));
}
}
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readStruct:" + object);
}
Object readStruct(TypeDescription typeDescription) throws Exception {
Object object = null;
if(typeDescription.getZClass() == CorbaString8.class) { // special treatement for CorbaString8
String string = read_asciistring();
if(DEBUG) System.err.println("##### Unmarshal.read_struct - CorbaString8:" + string);
object = new CorbaString8(string);
}
else {
object = typeDescription.getZClass().newInstance();
readStruct(typeDescription, object);
}
return object;
}
public ThreadID readThreadID() throws Exception {
throw new com.sun.star.uno.RuntimeException("Unmarshal.readThreadID - not implemented!!!");
}
public Object readObject(TypeDescription typeDescription) throws Exception {
Object result = null;
switch(typeDescription.getTypeClass().getValue()) {
case TypeClass.ANY_value: result = readAny(); break; // read an any?
case TypeClass.SEQUENCE_value:
case TypeClass.ARRAY_value: result = readSequence(typeDescription); break; // read a sequence ?
case TypeClass.VOID_value: break; // nop // read nothing ?
case TypeClass.ENUM_value: result = readEnum(typeDescription); break; // read an enum ?
case TypeClass.UNION_value: result = readUnion(typeDescription); break; // read a union ?
case TypeClass.TYPE_value: result = new Type(readTypeDescription()); break; // read a type ?
case TypeClass.INTERFACE_value: result = read_objref(typeDescription); break; // read an interface ?
case TypeClass.BOOLEAN_value: result = readBoolean(); break; // is it a boolean
case TypeClass.CHAR_value: result = readCharacter(); break; // is it a character ?)
case TypeClass.BYTE_value: result = readByte(); break; // is it a byte ?
case TypeClass.SHORT_value: result = readShort(); break; // is it a short ?
case TypeClass.LONG_value: result = readInteger(); break; // is it an integer ?
case TypeClass.HYPER_value: result = readLong(); break; // is it a long ?
case TypeClass.FLOAT_value: result = readFloat(); break; // is it a float ?
case TypeClass.DOUBLE_value: result = readDouble(); break; // is it a double ?
case TypeClass.STRING_value: result = read_unicodestring(); break; // is it a String ?
case TypeClass.EXCEPTION_value: result = readThrowable(); break; // is it an exception?
case TypeClass.STRUCT_value:
if(typeDescription.getZClass() == ThreadID.class) // read a thread id ?
result = readThreadID();
else if(CorbaUnion.class.isAssignableFrom(typeDescription.getZClass()))
result = readCorbaUnion(typeDescription);
else // otherwise read a struct
result = readStruct(typeDescription);
break;
default:
throw new com.sun.star.uno.RuntimeException("unknown typeClass:" + typeDescription.getTypeClass());
}
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readObject:" + typeDescription + " " + result);
return result;
}
Object readAny() throws Exception {
TypeDescription typeDescription = readTypeDescription();
Object object = readObject(typeDescription);
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readAny:" + object);
return object;
}
Object readSequence(TypeDescription typeDescription) throws Exception {
Object result = null;
typeDescription = typeDescription.getComponentType();
if(typeDescription.getTypeClass().getValue() == TypeClass.BYTE_value) // read a byte sequence ?
result = read_octet_array();
else {
int size = read_long();
if(typeDescription.getTypeClass() == TypeClass.ANY) // take special care of any array (cause anys are mapped to objects)
result = Array.newInstance(Object.class, size);
else
result = Array.newInstance(typeDescription.getZClass(), size);
for(int i = 0; i < size; ++ i)
Array.set(result, i, readObject(typeDescription));
}
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readSequence:" + result);
return result;
}
Union readUnion(TypeDescription typeDescription) throws Exception {
throw new com.sun.star.uno.RuntimeException("Unmarshal.readUnion - not implemented!!!");
}
Enum readEnum(TypeDescription typeDescription) throws Exception {
Integer index = new Integer(read_long());
Method fromInt = typeDescription.getZClass().getMethod("fromInt", new Class[] {int.class});
Enum result = (Enum)fromInt.invoke(null, new Object[]{index});
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readEnum:" + result);
return result;
}
private XInterface read_objref(TypeDescription typeDescription) throws Exception {
XInterface xInterface = null;
IOR ior = (IOR)readObject(__IORTypeDescription);
// is it the empty ref?
if(ior.profiles.length != 0) {
String sType = ior.type_id.theString;
byte profileBody_bytes[] = ior.profiles[0].profile_data;
Unmarshal unmarshal = new Unmarshal(profileBody_bytes,
profileBody_bytes.length,
littleEndian,
_bridge);
ProfileBody_1_1 profileBody = (ProfileBody_1_1)unmarshal.readObject(__ProfileBody_1_1TypeDescription);
byte key_bytes[] = profileBody.object_key;
Unmarshal tmpUnmarshal = new Unmarshal(key_bytes, key_bytes.length, littleEndian, _bridge);
ObjectKey objectKey = (ObjectKey)tmpUnmarshal.readObject(__ObjectKeyTypeDescription);
xInterface = (XInterface)_bridge.mapInterfaceFrom(objectKey.sOid.theString, new Type(typeDescription));
if(DEBUG) System.err.println("#### Unmarshal.read_objref - oid:" + objectKey.sOid.theString + " stype:" + objectKey.sType.theString + " xInterface:" + xInterface);
}
else
if(DEBUG) System.err.println("#### Unmarshal.read_objref - oid: ior empty");
return xInterface;
}
private CorbaUnion readCorbaUnion(TypeDescription corbaUnion_TypeDescription) throws Exception {
CorbaUnion corbaUnion = (CorbaUnion)corbaUnion_TypeDescription.getZClass().newInstance();
short discriminator = read_short();
Field descriminatorField = corbaUnion_TypeDescription.getZClass().getDeclaredField("nDiscriminator");
descriminatorField.set(corbaUnion, new Short(discriminator));
Field fields[] = corbaUnion_TypeDescription.getFields();
fields[discriminator + 2].set(corbaUnion, readObject(TypeDescription.getTypeDescription(fields[discriminator + 2].getType())));
return corbaUnion;
}
}