summaryrefslogtreecommitdiff
path: root/jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java
diff options
context:
space:
mode:
Diffstat (limited to 'jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java')
-rw-r--r--jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java490
1 files changed, 490 insertions, 0 deletions
diff --git a/jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java b/jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java
new file mode 100644
index 000000000000..5a500ad3a0c1
--- /dev/null
+++ b/jurt/com/sun/star/lib/uno/protocols/urp/Unmarshal.java
@@ -0,0 +1,490 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.lib.uno.protocols.urp;
+
+import com.sun.star.lib.uno.environments.remote.ThreadId;
+import com.sun.star.lib.uno.typedesc.TypeDescription;
+import com.sun.star.uno.Any;
+import com.sun.star.uno.Enum;
+import com.sun.star.uno.IBridge;
+import com.sun.star.uno.IFieldDescription;
+import com.sun.star.uno.Type;
+import com.sun.star.uno.TypeClass;
+import com.sun.star.uno.XInterface;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+
+final class Unmarshal {
+ public Unmarshal(IBridge bridge, int cacheSize) {
+ this.bridge = bridge;
+ objectIdCache = new String[cacheSize];
+ threadIdCache = new ThreadId[cacheSize];
+ typeCache = new TypeDescription[cacheSize];
+ reset(new byte[0]);
+ }
+
+ public int read8Bit() {
+ try {
+ return input.readUnsignedByte();
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ public int read16Bit() {
+ try {
+ return input.readUnsignedShort();
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ public String readObjectId() {
+ String id = readStringValue();
+ int index = read16Bit();
+ if (index == 0xFFFF) {
+ if (id.length() == 0) {
+ id = null;
+ }
+ } else {
+ if (id.length() == 0) {
+ id = objectIdCache[index];
+ } else {
+ objectIdCache[index] = id;
+ }
+ }
+ return id;
+ }
+
+ public Object readInterface(Type type) {
+ String id = readObjectId();
+ return id == null ? null : bridge.mapInterfaceFrom(id, type);
+ }
+
+ public ThreadId readThreadId() {
+ int len = readCompressedNumber();
+ byte[] data = null;
+ ThreadId id = null;
+ if (len != 0) {
+ data = new byte[len];
+ readBytes(data);
+ id = new ThreadId(data);
+ }
+ int index = read16Bit();
+ if (index != 0xFFFF) {
+ if (len == 0) {
+ id = threadIdCache[index];
+ } else {
+ threadIdCache[index] = id;
+ }
+ }
+ return id;
+ }
+
+ public TypeDescription readType() {
+ int b = read8Bit();
+ TypeClass typeClass = TypeClass.fromInt(b & 0x7F);
+ if (TypeDescription.isTypeClassSimple(typeClass)) {
+ return TypeDescription.getTypeDescription(typeClass);
+ } else {
+ int index = read16Bit();
+ TypeDescription type = null;
+ if ((b & 0x80) != 0) {
+ try {
+ type = TypeDescription.getTypeDescription(
+ readStringValue());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ if (index != 0xFFFF) {
+ if ((b & 0x80) == 0) {
+ type = typeCache[index];
+ } else {
+ typeCache[index] = type;
+ }
+ }
+ return type;
+ }
+ }
+
+ public Object readValue(TypeDescription type) {
+ switch (type.getTypeClass().getValue()) {
+ case TypeClass.VOID_value:
+ return null;
+
+ case TypeClass.BOOLEAN_value:
+ return readBooleanValue();
+
+ case TypeClass.BYTE_value:
+ return readByteValue();
+
+ case TypeClass.SHORT_value:
+ case TypeClass.UNSIGNED_SHORT_value:
+ return readShortValue();
+
+ case TypeClass.LONG_value:
+ case TypeClass.UNSIGNED_LONG_value:
+ return readLongValue();
+
+ case TypeClass.HYPER_value:
+ case TypeClass.UNSIGNED_HYPER_value:
+ return readHyperValue();
+
+ case TypeClass.FLOAT_value:
+ return readFloatValue();
+
+ case TypeClass.DOUBLE_value:
+ return readDoubleValue();
+
+ case TypeClass.CHAR_value:
+ return readCharValue();
+
+ case TypeClass.STRING_value:
+ return readStringValue();
+
+ case TypeClass.TYPE_value:
+ return readTypeValue();
+
+ case TypeClass.ANY_value:
+ return readAnyValue();
+
+ case TypeClass.SEQUENCE_value:
+ return readSequenceValue(type);
+
+ case TypeClass.ENUM_value:
+ return readEnumValue(type);
+
+ case TypeClass.STRUCT_value:
+ return readStructValue(type);
+
+ case TypeClass.EXCEPTION_value:
+ return readExceptionValue(type);
+
+ case TypeClass.INTERFACE_value:
+ return readInterfaceValue(type);
+
+ default:
+ throw new IllegalArgumentException("Bad type descriptor " + type);
+ }
+ }
+
+ public boolean hasMore() {
+ try {
+ return input.available() > 0;
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ public void reset(byte[] data) {
+ input = new DataInputStream(new ByteArrayInputStream(data));
+ }
+
+ private Boolean readBooleanValue() {
+ try {
+ return input.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Byte readByteValue() {
+ try {
+ return new Byte(input.readByte());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Short readShortValue() {
+ try {
+ return new Short(input.readShort());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Integer readLongValue() {
+ try {
+ return new Integer(input.readInt());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Long readHyperValue() {
+ try {
+ return new Long(input.readLong());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Float readFloatValue() {
+ try {
+ return new Float(input.readFloat());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Double readDoubleValue() {
+ try {
+ return new Double(input.readDouble());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Character readCharValue() {
+ try {
+ return new Character(input.readChar());
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private String readStringValue() {
+ int len = readCompressedNumber();
+ byte[] data = new byte[len];
+ readBytes(data);
+ try {
+ return new String(data, "UTF8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Type readTypeValue() {
+ return new Type(readType());
+ }
+
+ private Object readAnyValue() {
+ TypeDescription type = readType();
+ switch (type.getTypeClass().getValue()) {
+ case TypeClass.VOID_value:
+ return Any.VOID;
+
+ case TypeClass.BOOLEAN_value:
+ return readBooleanValue();
+
+ case TypeClass.BYTE_value:
+ return readByteValue();
+
+ case TypeClass.SHORT_value:
+ return readShortValue();
+
+ case TypeClass.UNSIGNED_SHORT_value:
+ return new Any(Type.UNSIGNED_SHORT, readShortValue());
+
+ case TypeClass.LONG_value:
+ return readLongValue();
+
+ case TypeClass.UNSIGNED_LONG_value:
+ return new Any(Type.UNSIGNED_LONG, readLongValue());
+
+ case TypeClass.HYPER_value:
+ return readHyperValue();
+
+ case TypeClass.UNSIGNED_HYPER_value:
+ return new Any(Type.UNSIGNED_HYPER, readHyperValue());
+
+ case TypeClass.FLOAT_value:
+ return readFloatValue();
+
+ case TypeClass.DOUBLE_value:
+ return readDoubleValue();
+
+ case TypeClass.CHAR_value:
+ return readCharValue();
+
+ case TypeClass.STRING_value:
+ return readStringValue();
+
+ case TypeClass.TYPE_value:
+ return readTypeValue();
+
+ case TypeClass.SEQUENCE_value:
+ {
+ Object value = readSequenceValue(type);
+ TypeDescription ctype = (TypeDescription)
+ type.getComponentType();
+ while (ctype.getTypeClass() == TypeClass.SEQUENCE) {
+ ctype = (TypeDescription) ctype.getComponentType();
+ }
+ switch (ctype.getTypeClass().getValue()) {
+ case TypeClass.UNSIGNED_SHORT_value:
+ case TypeClass.UNSIGNED_LONG_value:
+ case TypeClass.UNSIGNED_HYPER_value:
+ return new Any(new Type(type), value);
+
+ case TypeClass.STRUCT_value:
+ if (ctype.hasTypeArguments()) {
+ return new Any(new Type(type), value);
+ }
+ default:
+ return value;
+ }
+ }
+
+ case TypeClass.ENUM_value:
+ return readEnumValue(type);
+
+ case TypeClass.STRUCT_value:
+ {
+ Object value = readStructValue(type);
+ return type.hasTypeArguments()
+ ? new Any(new Type(type), value) : value;
+ }
+
+ case TypeClass.EXCEPTION_value:
+ return readExceptionValue(type);
+
+ case TypeClass.INTERFACE_value:
+ {
+ Object value = readInterfaceValue(type);
+ return type.getZClass() == XInterface.class
+ ? value : new Any(new Type(type), value);
+ }
+
+ default:
+ throw new RuntimeException(
+ "Reading ANY with bad type " + type.getTypeClass());
+ }
+ }
+
+ private Object readSequenceValue(TypeDescription type) {
+ int len = readCompressedNumber();
+ TypeDescription ctype = (TypeDescription) type.getComponentType();
+ if (ctype.getTypeClass() == TypeClass.BYTE) {
+ byte[] data = new byte[len];
+ readBytes(data);
+ return data;
+ } else {
+ Object value = Array.newInstance(
+ ctype.getTypeClass() == TypeClass.ANY
+ ? Object.class : ctype.getZClass(), len);
+ for (int i = 0; i < len; ++i) {
+ Array.set(value, i, readValue(ctype));
+ }
+ return value;
+ }
+ }
+
+ private Enum readEnumValue(TypeDescription type) {
+ try {
+ return (Enum)
+ type.getZClass().getMethod(
+ "fromInt", new Class[] { int.class }).
+ invoke(null, new Object[] { readLongValue() });
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.toString());
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.toString());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private Object readStructValue(TypeDescription type) {
+ Object value;
+ try {
+ value = type.getZClass().newInstance();
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.toString());
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e.toString());
+ }
+ readFields(type, value);
+ return value;
+ }
+
+ private Exception readExceptionValue(TypeDescription type) {
+ Exception value;
+ try {
+ value = (Exception)
+ type.getZClass().getConstructor(new Class[] { String.class }).
+ newInstance(new Object[] { readStringValue() });
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.toString());
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e.toString());
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.toString());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e.toString());
+ }
+ readFields(type, value);
+ return value;
+ }
+
+ private Object readInterfaceValue(TypeDescription type) {
+ return readInterface(new Type(type));
+ }
+
+ private int readCompressedNumber() {
+ int number = read8Bit();
+ try {
+ return number < 0xFF ? number : input.readInt();
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private void readBytes(byte[] data) {
+ try {
+ input.readFully(data);
+ } catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private void readFields(TypeDescription type, Object value) {
+ IFieldDescription[] fields = type.getFieldDescriptions();
+ for (int i = 0; i < fields.length; ++i) {
+ try {
+ fields[i].getField().set(
+ value,
+ readValue(
+ (TypeDescription) fields[i].getTypeDescription()));
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+
+ private final IBridge bridge;
+ private final String[] objectIdCache;
+ private final ThreadId[] threadIdCache;
+ private final TypeDescription[] typeCache;
+ private DataInputStream input;
+}