summaryrefslogtreecommitdiffstats
path: root/ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java
diff options
context:
space:
mode:
Diffstat (limited to 'ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java')
-rw-r--r--ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java355
1 files changed, 355 insertions, 0 deletions
diff --git a/ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java b/ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java
new file mode 100644
index 000000000..106a8736c
--- /dev/null
+++ b/ridljar/com/sun/star/lib/uno/protocols/urp/Marshal.java
@@ -0,0 +1,355 @@
+/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you 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 .
+ */
+package com.sun.star.lib.uno.protocols.urp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+
+import com.sun.star.lib.uno.environments.remote.ThreadId;
+import com.sun.star.lib.uno.typedesc.FieldDescription;
+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.Type;
+import com.sun.star.uno.TypeClass;
+import com.sun.star.uno.XInterface;
+
+final class Marshal {
+ public Marshal(IBridge bridge, short cacheSize) {
+ this.bridge = bridge;
+ objectIdCache = new Cache(cacheSize);
+ threadIdCache = new Cache(cacheSize);
+ typeCache = new Cache(cacheSize);
+ }
+
+ public void write8Bit(int value) {
+ try {
+ output.writeByte(value);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void write16Bit(int value) {
+ try {
+ output.writeShort(value);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void writeObjectId(String objectId) {
+ try {
+ if (objectId == null) {
+ writeStringValue(null);
+ write16Bit(0xFFFF);
+ } else {
+ boolean[] found = new boolean[1];
+ int index = objectIdCache.add(found, objectId);
+ writeStringValue(found[0] ? null : objectId);
+ write16Bit(index);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void writeInterface(XInterface object, Type type) {
+ writeObjectId((String) bridge.mapInterfaceTo(object, type));
+ }
+
+ public void writeThreadId(ThreadId threadId) {
+ try {
+ byte[] data = threadId.getBytes();
+ boolean[] found = new boolean[1];
+ int index = threadIdCache.add(found, data);
+ if (found[0]) {
+ writeCompressedNumber(0);
+ } else {
+ writeCompressedNumber(data.length);
+ writeBytes(data);
+ }
+ write16Bit(index);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void writeType(TypeDescription type) {
+ try {
+ TypeClass typeClass = type.getTypeClass();
+ if (TypeDescription.isTypeClassSimple(typeClass)) {
+ write8Bit(typeClass.getValue());
+ } else {
+ boolean[] found = new boolean[1];
+ int index = typeCache.add(found, type.getTypeName());
+ write8Bit(typeClass.getValue() | (found[0] ? 0 : 0x80));
+ write16Bit(index);
+ if (!found[0]) {
+ writeStringValue(type.getTypeName());
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void writeValue(TypeDescription type, Object value) {
+ try {
+ switch(type.getTypeClass().getValue()) {
+ case TypeClass.VOID_value:
+ break;
+
+ case TypeClass.BOOLEAN_value:
+ writeBooleanValue((Boolean) value);
+ break;
+
+ case TypeClass.BYTE_value:
+ writeByteValue((Byte) value);
+ break;
+
+ case TypeClass.SHORT_value:
+ case TypeClass.UNSIGNED_SHORT_value:
+ writeShortValue((Short) value);
+ break;
+
+ case TypeClass.LONG_value:
+ case TypeClass.UNSIGNED_LONG_value:
+ writeLongValue((Integer) value);
+ break;
+
+ case TypeClass.HYPER_value:
+ case TypeClass.UNSIGNED_HYPER_value:
+ writeHyperValue((Long) value);
+ break;
+
+ case TypeClass.FLOAT_value:
+ writeFloatValue((Float) value);
+ break;
+
+ case TypeClass.DOUBLE_value:
+ writeDoubleValue((Double) value);
+ break;
+
+ case TypeClass.CHAR_value:
+ writeCharValue((Character) value);
+ break;
+
+ case TypeClass.STRING_value:
+ writeStringValue((String) value);
+ break;
+
+ case TypeClass.TYPE_value:
+ writeTypeValue((Type) value);
+ break;
+
+ case TypeClass.ANY_value:
+ writeAnyValue(value);
+ break;
+
+ case TypeClass.SEQUENCE_value:
+ writeSequenceValue(type, value);
+ break;
+
+ case TypeClass.ENUM_value:
+ writeEnumValue(type, (Enum) value);
+ break;
+
+ case TypeClass.STRUCT_value:
+ writeStructValue(type, value);
+ break;
+
+ case TypeClass.EXCEPTION_value:
+ writeExceptionValue(type, (Exception) value);
+ break;
+
+ case TypeClass.INTERFACE_value:
+ writeInterfaceValue(type, (XInterface) value);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Bad type descriptor " + type);
+ }
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public byte[] reset() {
+ byte[] data = buffer.toByteArray();
+ buffer.reset();
+ return data;
+ }
+
+ private void writeBooleanValue(Boolean value) throws IOException {
+ output.writeBoolean(value != null && value.booleanValue());
+ }
+
+ private void writeByteValue(Byte value) {
+ write8Bit(value == null ? 0 : value.byteValue());
+ }
+
+ private void writeShortValue(Short value) {
+ write16Bit(value == null ? 0 : value.shortValue());
+ }
+
+ private void writeLongValue(Integer value) throws IOException {
+ write32Bit(value == null ? 0 : value.intValue());
+ }
+
+ private void writeHyperValue(Long value) throws IOException {
+ output.writeLong(value == null ? 0 : value.longValue());
+ }
+
+ private void writeFloatValue(Float value) throws IOException {
+ output.writeFloat(value == null ? 0 : value.floatValue());
+ }
+
+ private void writeDoubleValue(Double value) throws IOException {
+ output.writeDouble(value == null ? 0 : value.doubleValue());
+ }
+
+ private void writeCharValue(Character value) throws IOException {
+ output.writeChar(value == null ? 0 : value.charValue());
+ }
+
+ private void writeStringValue(String value) throws IOException {
+ if (value == null) {
+ writeCompressedNumber(0);
+ } else {
+ byte[] data = value.getBytes("UTF8");
+ writeCompressedNumber(data.length);
+ writeBytes(data);
+ }
+ }
+
+ private void writeTypeValue(Type value) throws ClassNotFoundException {
+ writeType(
+ TypeDescription.getTypeDescription(
+ value == null ? Type.VOID : value));
+ }
+
+ private void writeAnyValue(Object value) throws ClassNotFoundException {
+ TypeDescription type;
+ if (value == null || value instanceof XInterface) {
+ type = TypeDescription.getTypeDescription(XInterface.class);
+ } else if (value instanceof Any) {
+ Any any = (Any) value;
+ type = TypeDescription.getTypeDescription(any.getType());
+ value = any.getObject();
+ } else if (value.getClass() == Object.class) {
+ // Avoid StackOverflowError:
+ throw new IllegalArgumentException(
+ "Object instance does not represent UNO value");
+ } else {
+ type = TypeDescription.getTypeDescription(value.getClass());
+ }
+ writeType(type);
+ writeValue(type, value);
+ }
+
+ private void writeSequenceValue(TypeDescription type, Object value) throws IOException {
+ if (value == null) {
+ writeCompressedNumber(0);
+ } else {
+ TypeDescription ctype = type.getComponentType();
+ if (ctype.getTypeClass() == TypeClass.BYTE) {
+ byte[] data = (byte[]) value;
+ writeCompressedNumber(data.length);
+ writeBytes(data);
+ } else {
+ int len = Array.getLength(value);
+ writeCompressedNumber(len);
+ for (int i = 0; i < len; ++i) {
+ writeValue(ctype, Array.get(value, i));
+ }
+ }
+ }
+ }
+
+ private void writeEnumValue(TypeDescription type, Enum value) throws IllegalAccessException, IOException, InvocationTargetException, NoSuchMethodException {
+ int n;
+ if (value == null) {
+ n = ((Enum)
+ (type.getZClass().getMethod("getDefault", (Class[]) null).
+ invoke(null, (Object[]) null))).
+ getValue();
+ } else {
+ n = value.getValue();
+ }
+ write32Bit(n);
+ }
+
+ private void writeStructValue(TypeDescription type, Object value) throws IllegalAccessException {
+ FieldDescription[] fields = type.getFieldDescriptions();
+ for (int i = 0; i < fields.length; ++i) {
+ writeValue(
+ fields[i].getTypeDescription(),
+ value == null ? null : fields[i].getField().get(value));
+ }
+ }
+
+ private void writeExceptionValue(TypeDescription type, Exception value) throws IllegalAccessException, IOException {
+ writeStringValue(value == null ? null : value.getMessage());
+ writeStructValue(type, value);
+ }
+
+ private void writeInterfaceValue(TypeDescription type, XInterface value) {
+ writeInterface(value, new Type(type));
+ }
+
+ private void write32Bit(int value) throws IOException {
+ output.writeInt(value);
+ }
+
+ private void writeCompressedNumber(int number) throws IOException {
+ if (number >= 0 && number < 0xFF) {
+ write8Bit(number);
+ } else {
+ write8Bit(0xFF);
+ write32Bit(number);
+ }
+ }
+
+ private void writeBytes(byte[] data) throws IOException {
+ output.write(data);
+ }
+
+ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ private final DataOutput output = new DataOutputStream(buffer);
+ private final IBridge bridge;
+ private final Cache objectIdCache;
+ private final Cache threadIdCache;
+ private final Cache typeCache;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */