1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package com
.sun
.star
.lib
.uno
.protocols
.urp
;
21 import java
.io
.ByteArrayOutputStream
;
22 import java
.io
.DataOutput
;
23 import java
.io
.DataOutputStream
;
24 import java
.io
.IOException
;
25 import java
.lang
.reflect
.Array
;
26 import java
.lang
.reflect
.InvocationTargetException
;
28 import com
.sun
.star
.lib
.uno
.environments
.remote
.ThreadId
;
29 import com
.sun
.star
.lib
.uno
.typedesc
.FieldDescription
;
30 import com
.sun
.star
.lib
.uno
.typedesc
.TypeDescription
;
31 import com
.sun
.star
.uno
.Any
;
32 import com
.sun
.star
.uno
.Enum
;
33 import com
.sun
.star
.uno
.IBridge
;
34 import com
.sun
.star
.uno
.Type
;
35 import com
.sun
.star
.uno
.TypeClass
;
36 import com
.sun
.star
.uno
.XInterface
;
39 public Marshal(IBridge bridge
, short cacheSize
) {
41 objectIdCache
= new Cache(cacheSize
);
42 threadIdCache
= new Cache(cacheSize
);
43 typeCache
= new Cache(cacheSize
);
46 public void write8Bit(int value
) {
48 output
.writeByte(value
);
49 } catch (IOException e
) {
50 throw new RuntimeException(e
);
54 public void write16Bit(int value
) {
56 output
.writeShort(value
);
57 } catch (IOException e
) {
58 throw new RuntimeException(e
);
62 public void writeObjectId(String objectId
) {
64 if (objectId
== null) {
65 writeStringValue(null);
68 boolean[] found
= new boolean[1];
69 int index
= objectIdCache
.add(found
, objectId
);
70 writeStringValue(found
[0] ?
null : objectId
);
73 } catch (IOException e
) {
74 throw new RuntimeException(e
);
78 public void writeInterface(XInterface object
, Type type
) {
79 writeObjectId((String
) bridge
.mapInterfaceTo(object
, type
));
82 public void writeThreadId(ThreadId threadId
) {
84 byte[] data
= threadId
.getBytes();
85 boolean[] found
= new boolean[1];
86 int index
= threadIdCache
.add(found
, data
);
88 writeCompressedNumber(0);
90 writeCompressedNumber(data
.length
);
94 } catch (IOException e
) {
95 throw new RuntimeException(e
);
99 public void writeType(TypeDescription type
) {
101 TypeClass typeClass
= type
.getTypeClass();
102 if (TypeDescription
.isTypeClassSimple(typeClass
)) {
103 write8Bit(typeClass
.getValue());
105 boolean[] found
= new boolean[1];
106 int index
= typeCache
.add(found
, type
.getTypeName());
107 write8Bit(typeClass
.getValue() | (found
[0] ?
0 : 0x80));
110 writeStringValue(type
.getTypeName());
113 } catch (IOException e
) {
114 throw new RuntimeException(e
);
118 public void writeValue(TypeDescription type
, Object value
) {
120 switch(type
.getTypeClass().getValue()) {
121 case TypeClass
.VOID_value
:
124 case TypeClass
.BOOLEAN_value
:
125 writeBooleanValue((Boolean
) value
);
128 case TypeClass
.BYTE_value
:
129 writeByteValue((Byte
) value
);
132 case TypeClass
.SHORT_value
:
133 case TypeClass
.UNSIGNED_SHORT_value
:
134 writeShortValue((Short
) value
);
137 case TypeClass
.LONG_value
:
138 case TypeClass
.UNSIGNED_LONG_value
:
139 writeLongValue((Integer
) value
);
142 case TypeClass
.HYPER_value
:
143 case TypeClass
.UNSIGNED_HYPER_value
:
144 writeHyperValue((Long
) value
);
147 case TypeClass
.FLOAT_value
:
148 writeFloatValue((Float
) value
);
151 case TypeClass
.DOUBLE_value
:
152 writeDoubleValue((Double
) value
);
155 case TypeClass
.CHAR_value
:
156 writeCharValue((Character
) value
);
159 case TypeClass
.STRING_value
:
160 writeStringValue((String
) value
);
163 case TypeClass
.TYPE_value
:
164 writeTypeValue((Type
) value
);
167 case TypeClass
.ANY_value
:
168 writeAnyValue(value
);
171 case TypeClass
.SEQUENCE_value
:
172 writeSequenceValue(type
, value
);
175 case TypeClass
.ENUM_value
:
176 writeEnumValue(type
, (Enum
) value
);
179 case TypeClass
.STRUCT_value
:
180 writeStructValue(type
, value
);
183 case TypeClass
.EXCEPTION_value
:
184 writeExceptionValue(type
, (Exception
) value
);
187 case TypeClass
.INTERFACE_value
:
188 writeInterfaceValue(type
, (XInterface
) value
);
192 throw new IllegalArgumentException("Bad type descriptor " + type
);
194 } catch (ClassNotFoundException e
) {
195 throw new RuntimeException(e
);
196 } catch (IllegalAccessException e
) {
197 throw new RuntimeException(e
);
198 } catch (IOException e
) {
199 throw new RuntimeException(e
);
200 } catch (InvocationTargetException e
) {
201 throw new RuntimeException(e
);
202 } catch (NoSuchMethodException e
) {
203 throw new RuntimeException(e
);
207 public byte[] reset() {
208 byte[] data
= buffer
.toByteArray();
213 private void writeBooleanValue(Boolean value
) throws IOException
{
214 output
.writeBoolean(value
!= null && value
.booleanValue());
217 private void writeByteValue(Byte value
) {
218 write8Bit(value
== null ?
0 : value
.byteValue());
221 private void writeShortValue(Short value
) {
222 write16Bit(value
== null ?
0 : value
.shortValue());
225 private void writeLongValue(Integer value
) throws IOException
{
226 write32Bit(value
== null ?
0 : value
.intValue());
229 private void writeHyperValue(Long value
) throws IOException
{
230 output
.writeLong(value
== null ?
0 : value
.longValue());
233 private void writeFloatValue(Float value
) throws IOException
{
234 output
.writeFloat(value
== null ?
0 : value
.floatValue());
237 private void writeDoubleValue(Double value
) throws IOException
{
238 output
.writeDouble(value
== null ?
0 : value
.doubleValue());
241 private void writeCharValue(Character value
) throws IOException
{
242 output
.writeChar(value
== null ?
0 : value
.charValue());
245 private void writeStringValue(String value
) throws IOException
{
247 writeCompressedNumber(0);
249 byte[] data
= value
.getBytes("UTF8");
250 writeCompressedNumber(data
.length
);
255 private void writeTypeValue(Type value
) throws ClassNotFoundException
{
257 TypeDescription
.getTypeDescription(
258 value
== null ? Type
.VOID
: value
));
261 private void writeAnyValue(Object value
) throws ClassNotFoundException
{
262 TypeDescription type
;
263 if (value
== null || value
instanceof XInterface
) {
264 type
= TypeDescription
.getTypeDescription(XInterface
.class);
265 } else if (value
instanceof Any
) {
266 Any any
= (Any
) value
;
267 type
= TypeDescription
.getTypeDescription(any
.getType());
268 value
= any
.getObject();
269 } else if (value
.getClass() == Object
.class) {
270 // Avoid StackOverflowError:
271 throw new IllegalArgumentException(
272 "Object instance does not represent UNO value");
274 type
= TypeDescription
.getTypeDescription(value
.getClass());
277 writeValue(type
, value
);
280 private void writeSequenceValue(TypeDescription type
, Object value
) throws IOException
{
282 writeCompressedNumber(0);
284 TypeDescription ctype
= type
.getComponentType();
285 if (ctype
.getTypeClass() == TypeClass
.BYTE
) {
286 byte[] data
= (byte[]) value
;
287 writeCompressedNumber(data
.length
);
290 int len
= Array
.getLength(value
);
291 writeCompressedNumber(len
);
292 for (int i
= 0; i
< len
; ++i
) {
293 writeValue(ctype
, Array
.get(value
, i
));
299 private void writeEnumValue(TypeDescription type
, Enum value
) throws IllegalAccessException
, IOException
, InvocationTargetException
, NoSuchMethodException
{
303 (type
.getZClass().getMethod("getDefault", (Class
[]) null).
304 invoke(null, (Object
[]) null))).
307 n
= value
.getValue();
312 private void writeStructValue(TypeDescription type
, Object value
) throws IllegalAccessException
{
313 FieldDescription
[] fields
= type
.getFieldDescriptions();
314 for (int i
= 0; i
< fields
.length
; ++i
) {
316 fields
[i
].getTypeDescription(),
317 value
== null ?
null : fields
[i
].getField().get(value
));
321 private void writeExceptionValue(TypeDescription type
, Exception value
) throws IllegalAccessException
, IOException
{
322 writeStringValue(value
== null ?
null : value
.getMessage());
323 writeStructValue(type
, value
);
326 private void writeInterfaceValue(TypeDescription type
, XInterface value
) {
327 writeInterface(value
, new Type(type
));
330 private void write32Bit(int value
) throws IOException
{
331 output
.writeInt(value
);
334 private void writeCompressedNumber(int number
) throws IOException
{
335 if (number
>= 0 && number
< 0xFF) {
343 private void writeBytes(byte[] data
) throws IOException
{
347 private final ByteArrayOutputStream buffer
= new ByteArrayOutputStream();
348 private final DataOutput output
= new DataOutputStream(buffer
);
349 private final IBridge bridge
;
350 private final Cache objectIdCache
;
351 private final Cache threadIdCache
;
352 private final Cache typeCache
;
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */