2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 package com
.sun
.star
.lib
.uno
.protocols
.urp
;
20 import com
.sun
.star
.lib
.uno
.environments
.remote
.ThreadId
;
21 import com
.sun
.star
.lib
.uno
.typedesc
.TypeDescription
;
22 import com
.sun
.star
.uno
.Any
;
23 import com
.sun
.star
.uno
.Enum
;
24 import com
.sun
.star
.uno
.IBridge
;
25 import com
.sun
.star
.uno
.IFieldDescription
;
26 import com
.sun
.star
.uno
.Type
;
27 import com
.sun
.star
.uno
.TypeClass
;
28 import com
.sun
.star
.uno
.XInterface
;
30 import java
.io
.ByteArrayOutputStream
;
31 import java
.io
.DataOutput
;
32 import java
.io
.DataOutputStream
;
33 import java
.io
.IOException
;
34 import java
.lang
.reflect
.Array
;
35 import java
.lang
.reflect
.InvocationTargetException
;
38 public Marshal(IBridge bridge
, short cacheSize
) {
40 objectIdCache
= new Cache(cacheSize
);
41 threadIdCache
= new Cache(cacheSize
);
42 typeCache
= new Cache(cacheSize
);
45 public void write8Bit(int value
) {
47 output
.writeByte(value
);
48 } catch (IOException e
) {
49 throw new RuntimeException(e
);
53 public void write16Bit(int value
) {
55 output
.writeShort(value
);
56 } catch (IOException e
) {
57 throw new RuntimeException(e
);
61 public void writeObjectId(String objectId
) {
63 if (objectId
== null) {
64 writeStringValue(null);
67 boolean[] found
= new boolean[1];
68 int index
= objectIdCache
.add(found
, objectId
);
69 writeStringValue(found
[0] ?
null : objectId
);
72 } catch (IOException e
) {
73 throw new RuntimeException(e
);
77 public void writeInterface(XInterface object
, Type type
) {
78 writeObjectId((String
) bridge
.mapInterfaceTo(object
, type
));
81 public void writeThreadId(ThreadId threadId
) {
83 byte[] data
= threadId
.getBytes();
84 boolean[] found
= new boolean[1];
85 int index
= threadIdCache
.add(found
, data
);
87 writeCompressedNumber(0);
89 writeCompressedNumber(data
.length
);
93 } catch (IOException e
) {
94 throw new RuntimeException(e
);
98 public void writeType(TypeDescription type
) {
100 TypeClass typeClass
= type
.getTypeClass();
101 if (TypeDescription
.isTypeClassSimple(typeClass
)) {
102 write8Bit(typeClass
.getValue());
104 boolean[] found
= new boolean[1];
105 int index
= typeCache
.add(found
, type
.getTypeName());
106 write8Bit(typeClass
.getValue() | (found
[0] ?
0 : 0x80));
109 writeStringValue(type
.getTypeName());
112 } catch (IOException e
) {
113 throw new RuntimeException(e
);
117 public void writeValue(TypeDescription type
, Object value
) {
119 switch(type
.getTypeClass().getValue()) {
120 case TypeClass
.VOID_value
:
123 case TypeClass
.BOOLEAN_value
:
124 writeBooleanValue((Boolean
) value
);
127 case TypeClass
.BYTE_value
:
128 writeByteValue((Byte
) value
);
131 case TypeClass
.SHORT_value
:
132 case TypeClass
.UNSIGNED_SHORT_value
:
133 writeShortValue((Short
) value
);
136 case TypeClass
.LONG_value
:
137 case TypeClass
.UNSIGNED_LONG_value
:
138 writeLongValue((Integer
) value
);
141 case TypeClass
.HYPER_value
:
142 case TypeClass
.UNSIGNED_HYPER_value
:
143 writeHyperValue((Long
) value
);
146 case TypeClass
.FLOAT_value
:
147 writeFloatValue((Float
) value
);
150 case TypeClass
.DOUBLE_value
:
151 writeDoubleValue((Double
) value
);
154 case TypeClass
.CHAR_value
:
155 writeCharValue((Character
) value
);
158 case TypeClass
.STRING_value
:
159 writeStringValue((String
) value
);
162 case TypeClass
.TYPE_value
:
163 writeTypeValue((Type
) value
);
166 case TypeClass
.ANY_value
:
167 writeAnyValue(value
);
170 case TypeClass
.SEQUENCE_value
:
171 writeSequenceValue(type
, value
);
174 case TypeClass
.ENUM_value
:
175 writeEnumValue(type
, (Enum
) value
);
178 case TypeClass
.STRUCT_value
:
179 writeStructValue(type
, value
);
182 case TypeClass
.EXCEPTION_value
:
183 writeExceptionValue(type
, (Exception
) value
);
186 case TypeClass
.INTERFACE_value
:
187 writeInterfaceValue(type
, (XInterface
) value
);
191 throw new IllegalArgumentException("Bad type descriptor " + type
);
193 } catch (ClassNotFoundException e
) {
194 throw new RuntimeException(e
);
195 } catch (IllegalAccessException e
) {
196 throw new RuntimeException(e
);
197 } catch (IOException e
) {
198 throw new RuntimeException(e
);
199 } catch (InvocationTargetException e
) {
200 throw new RuntimeException(e
);
201 } catch (NoSuchMethodException e
) {
202 throw new RuntimeException(e
);
206 public byte[] reset() {
207 byte[] data
= buffer
.toByteArray();
212 private void writeBooleanValue(Boolean value
) throws IOException
{
213 output
.writeBoolean(value
!= null && value
.booleanValue());
216 private void writeByteValue(Byte value
) {
217 write8Bit(value
== null ?
0 : value
.byteValue());
220 private void writeShortValue(Short value
) {
221 write16Bit(value
== null ?
0 : value
.shortValue());
224 private void writeLongValue(Integer value
) throws IOException
{
225 write32Bit(value
== null ?
0 : value
.intValue());
228 private void writeHyperValue(Long value
) throws IOException
{
229 output
.writeLong(value
== null ?
0 : value
.longValue());
232 private void writeFloatValue(Float value
) throws IOException
{
233 output
.writeFloat(value
== null ?
0 : value
.floatValue());
236 private void writeDoubleValue(Double value
) throws IOException
{
237 output
.writeDouble(value
== null ?
0 : value
.doubleValue());
240 private void writeCharValue(Character value
) throws IOException
{
241 output
.writeChar(value
== null ?
0 : value
.charValue());
244 private void writeStringValue(String value
) throws IOException
{
246 writeCompressedNumber(0);
248 byte[] data
= value
.getBytes("UTF8");
249 writeCompressedNumber(data
.length
);
254 private void writeTypeValue(Type value
) throws ClassNotFoundException
{
256 TypeDescription
.getTypeDescription(
257 value
== null ? Type
.VOID
: value
));
260 private void writeAnyValue(Object value
) throws ClassNotFoundException
{
261 TypeDescription type
;
262 if (value
== null || value
instanceof XInterface
) {
263 type
= TypeDescription
.getTypeDescription(XInterface
.class);
264 } else if (value
instanceof Any
) {
265 Any any
= (Any
) value
;
266 type
= TypeDescription
.getTypeDescription(any
.getType());
267 value
= any
.getObject();
268 } else if (value
.getClass() == Object
.class) {
269 // Avoid StackOverflowError:
270 throw new IllegalArgumentException(
271 "Object instance does not represent UNO value");
273 type
= TypeDescription
.getTypeDescription(value
.getClass());
276 writeValue(type
, value
);
279 private void writeSequenceValue(TypeDescription type
, Object value
) throws IOException
{
281 writeCompressedNumber(0);
283 TypeDescription ctype
= (TypeDescription
) type
.getComponentType();
284 if (ctype
.getTypeClass() == TypeClass
.BYTE
) {
285 byte[] data
= (byte[]) value
;
286 writeCompressedNumber(data
.length
);
289 int len
= Array
.getLength(value
);
290 writeCompressedNumber(len
);
291 for (int i
= 0; i
< len
; ++i
) {
292 writeValue(ctype
, Array
.get(value
, i
));
298 private void writeEnumValue(TypeDescription type
, Enum value
) throws IllegalAccessException
, IOException
, InvocationTargetException
, NoSuchMethodException
{
302 (type
.getZClass().getMethod("getDefault", (Class
[]) null).
303 invoke(null, (Object
[]) null))).
306 n
= value
.getValue();
311 private void writeStructValue(TypeDescription type
, Object value
) throws IllegalAccessException
{
312 IFieldDescription
[] fields
= type
.getFieldDescriptions();
313 for (int i
= 0; i
< fields
.length
; ++i
) {
315 (TypeDescription
) fields
[i
].getTypeDescription(),
316 value
== null ?
null : fields
[i
].getField().get(value
));
320 private void writeExceptionValue(TypeDescription type
, Exception value
) throws IllegalAccessException
, IOException
{
321 writeStringValue(value
== null ?
null : value
.getMessage());
322 writeStructValue(type
, value
);
325 private void writeInterfaceValue(TypeDescription type
, XInterface value
) {
326 writeInterface(value
, new Type(type
));
329 private void write32Bit(int value
) throws IOException
{
330 output
.writeInt(value
);
333 private void writeCompressedNumber(int number
) throws IOException
{
334 if (number
>= 0 && number
< 0xFF) {
342 private void writeBytes(byte[] data
) throws IOException
{
346 private final ByteArrayOutputStream buffer
= new ByteArrayOutputStream();
347 private final DataOutput output
= new DataOutputStream(buffer
);
348 private final IBridge bridge
;
349 private final Cache objectIdCache
;
350 private final Cache threadIdCache
;
351 private final Cache typeCache
;