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 java
.io
.ByteArrayInputStream
;
21 import java
.io
.DataInputStream
;
22 import java
.io
.IOException
;
23 import java
.io
.UnsupportedEncodingException
;
24 import java
.lang
.reflect
.Array
;
25 import java
.lang
.reflect
.InvocationTargetException
;
27 import com
.sun
.star
.lib
.uno
.environments
.remote
.ThreadId
;
28 import com
.sun
.star
.lib
.uno
.typedesc
.TypeDescription
;
29 import com
.sun
.star
.uno
.Any
;
30 import com
.sun
.star
.uno
.Enum
;
31 import com
.sun
.star
.uno
.IBridge
;
32 import com
.sun
.star
.uno
.IFieldDescription
;
33 import com
.sun
.star
.uno
.Type
;
34 import com
.sun
.star
.uno
.TypeClass
;
35 import com
.sun
.star
.uno
.XInterface
;
37 final class Unmarshal
{
38 public Unmarshal(IBridge bridge
, int cacheSize
) {
40 objectIdCache
= new String
[cacheSize
];
41 threadIdCache
= new ThreadId
[cacheSize
];
42 typeCache
= new TypeDescription
[cacheSize
];
46 public int read8Bit() {
48 return input
.readUnsignedByte();
49 } catch (IOException e
) {
50 throw new RuntimeException(e
);
54 public int read16Bit() {
56 return input
.readUnsignedShort();
57 } catch (IOException e
) {
58 throw new RuntimeException(e
);
62 public String
readObjectId() {
64 String id
= readStringValue();
65 int index
= read16Bit();
66 if (index
== 0xFFFF) {
67 if (id
.length() == 0) {
71 if (id
.length() == 0) {
72 id
= objectIdCache
[index
];
74 objectIdCache
[index
] = id
;
78 } catch (IOException e
) {
79 throw new RuntimeException(e
);
83 public Object
readInterface(Type type
) {
84 String id
= readObjectId();
85 return id
== null ?
null : bridge
.mapInterfaceFrom(id
, type
);
88 public ThreadId
readThreadId() {
90 int len
= readCompressedNumber();
96 id
= new ThreadId(data
);
98 int index
= read16Bit();
99 if (index
!= 0xFFFF) {
101 id
= threadIdCache
[index
];
103 threadIdCache
[index
] = id
;
107 } catch (IOException e
) {
108 throw new RuntimeException(e
);
112 public TypeDescription
readType() {
114 TypeClass typeClass
= TypeClass
.fromInt(b
& 0x7F);
115 if (TypeDescription
.isTypeClassSimple(typeClass
)) {
116 return TypeDescription
.getTypeDescription(typeClass
);
118 int index
= read16Bit();
119 TypeDescription type
= null;
120 if ((b
& 0x80) != 0) {
122 type
= TypeDescription
.getTypeDescription(
124 } catch (IOException e
) {
125 throw new RuntimeException(e
);
126 } catch (ClassNotFoundException e
) {
127 throw new RuntimeException(e
);
130 if (index
!= 0xFFFF) {
131 if ((b
& 0x80) == 0) {
132 type
= typeCache
[index
];
134 typeCache
[index
] = type
;
141 public Object
readValue(TypeDescription type
) {
143 switch (type
.getTypeClass().getValue()) {
144 case TypeClass
.VOID_value
:
147 case TypeClass
.BOOLEAN_value
:
148 return readBooleanValue();
150 case TypeClass
.BYTE_value
:
151 return readByteValue();
153 case TypeClass
.SHORT_value
:
154 case TypeClass
.UNSIGNED_SHORT_value
:
155 return readShortValue();
157 case TypeClass
.LONG_value
:
158 case TypeClass
.UNSIGNED_LONG_value
:
159 return readLongValue();
161 case TypeClass
.HYPER_value
:
162 case TypeClass
.UNSIGNED_HYPER_value
:
163 return readHyperValue();
165 case TypeClass
.FLOAT_value
:
166 return readFloatValue();
168 case TypeClass
.DOUBLE_value
:
169 return readDoubleValue();
171 case TypeClass
.CHAR_value
:
172 return readCharValue();
174 case TypeClass
.STRING_value
:
175 return readStringValue();
177 case TypeClass
.TYPE_value
:
178 return readTypeValue();
180 case TypeClass
.ANY_value
:
181 return readAnyValue();
183 case TypeClass
.SEQUENCE_value
:
184 return readSequenceValue(type
);
186 case TypeClass
.ENUM_value
:
187 return readEnumValue(type
);
189 case TypeClass
.STRUCT_value
:
190 return readStructValue(type
);
192 case TypeClass
.EXCEPTION_value
:
193 return readExceptionValue(type
);
195 case TypeClass
.INTERFACE_value
:
196 return readInterfaceValue(type
);
199 throw new IllegalArgumentException("Bad type descriptor " + type
);
201 } catch (IOException e
) {
202 throw new RuntimeException(e
);
206 public boolean hasMore() {
208 return input
.available() > 0;
209 } catch (IOException e
) {
210 throw new RuntimeException(e
);
214 public void reset(byte[] data
) {
215 input
= new DataInputStream(new ByteArrayInputStream(data
));
218 private Boolean
readBooleanValue() throws IOException
{
219 return input
.readBoolean() ? Boolean
.TRUE
: Boolean
.FALSE
;
222 private Byte
readByteValue() throws IOException
{
223 return Byte
.valueOf(input
.readByte());
226 private Short
readShortValue() throws IOException
{
227 return Short
.valueOf(input
.readShort());
230 private Integer
readLongValue() throws IOException
{
231 return Integer
.valueOf(input
.readInt());
234 private Long
readHyperValue() throws IOException
{
235 return Long
.valueOf(input
.readLong());
238 private Float
readFloatValue() throws IOException
{
239 return new Float(input
.readFloat());
242 private Double
readDoubleValue() throws IOException
{
243 return new Double(input
.readDouble());
246 private Character
readCharValue() throws IOException
{
247 return new Character(input
.readChar());
250 private String
readStringValue() throws IOException
{
251 int len
= readCompressedNumber();
252 byte[] data
= new byte[len
];
255 return new String(data
, "UTF8");
256 } catch (UnsupportedEncodingException e
) {
257 throw new RuntimeException(e
);
261 private Type
readTypeValue() {
262 return new Type(readType());
265 private Object
readAnyValue() throws IOException
{
266 TypeDescription type
= readType();
267 switch (type
.getTypeClass().getValue()) {
268 case TypeClass
.VOID_value
:
271 case TypeClass
.BOOLEAN_value
:
272 return readBooleanValue();
274 case TypeClass
.BYTE_value
:
275 return readByteValue();
277 case TypeClass
.SHORT_value
:
278 return readShortValue();
280 case TypeClass
.UNSIGNED_SHORT_value
:
281 return new Any(Type
.UNSIGNED_SHORT
, readShortValue());
283 case TypeClass
.LONG_value
:
284 return readLongValue();
286 case TypeClass
.UNSIGNED_LONG_value
:
287 return new Any(Type
.UNSIGNED_LONG
, readLongValue());
289 case TypeClass
.HYPER_value
:
290 return readHyperValue();
292 case TypeClass
.UNSIGNED_HYPER_value
:
293 return new Any(Type
.UNSIGNED_HYPER
, readHyperValue());
295 case TypeClass
.FLOAT_value
:
296 return readFloatValue();
298 case TypeClass
.DOUBLE_value
:
299 return readDoubleValue();
301 case TypeClass
.CHAR_value
:
302 return readCharValue();
304 case TypeClass
.STRING_value
:
305 return readStringValue();
307 case TypeClass
.TYPE_value
:
308 return readTypeValue();
310 case TypeClass
.SEQUENCE_value
:
312 Object value
= readSequenceValue(type
);
313 TypeDescription ctype
= (TypeDescription
)
314 type
.getComponentType();
315 while (ctype
.getTypeClass() == TypeClass
.SEQUENCE
) {
316 ctype
= (TypeDescription
) ctype
.getComponentType();
318 switch (ctype
.getTypeClass().getValue()) {
319 case TypeClass
.UNSIGNED_SHORT_value
:
320 case TypeClass
.UNSIGNED_LONG_value
:
321 case TypeClass
.UNSIGNED_HYPER_value
:
322 return new Any(new Type(type
), value
);
324 case TypeClass
.STRUCT_value
:
325 if (ctype
.hasTypeArguments()) {
326 return new Any(new Type(type
), value
);
333 case TypeClass
.ENUM_value
:
334 return readEnumValue(type
);
336 case TypeClass
.STRUCT_value
:
338 Object value
= readStructValue(type
);
339 return type
.hasTypeArguments()
340 ?
new Any(new Type(type
), value
) : value
;
343 case TypeClass
.EXCEPTION_value
:
344 return readExceptionValue(type
);
346 case TypeClass
.INTERFACE_value
:
348 Object value
= readInterfaceValue(type
);
349 return type
.getZClass() == XInterface
.class
350 ? value
: new Any(new Type(type
), value
);
354 throw new RuntimeException(
355 "Reading ANY with bad type " + type
.getTypeClass());
359 private Object
readSequenceValue(TypeDescription type
) throws IOException
{
360 int len
= readCompressedNumber();
361 TypeDescription ctype
= (TypeDescription
) type
.getComponentType();
362 if (ctype
.getTypeClass() == TypeClass
.BYTE
) {
363 byte[] data
= new byte[len
];
367 Object value
= Array
.newInstance(
368 ctype
.getTypeClass() == TypeClass
.ANY
369 ? Object
.class : ctype
.getZClass(), len
);
370 for (int i
= 0; i
< len
; ++i
) {
371 Array
.set(value
, i
, readValue(ctype
));
377 private Enum
readEnumValue(TypeDescription type
) throws IOException
{
380 type
.getZClass().getMethod(
381 "fromInt", new Class
[] { int.class }).
382 invoke(null, new Object
[] { readLongValue() });
383 } catch (IllegalAccessException e
) {
384 throw new RuntimeException(e
);
385 } catch (InvocationTargetException e
) {
386 throw new RuntimeException(e
);
387 } catch (NoSuchMethodException e
) {
388 throw new RuntimeException(e
);
392 private Object
readStructValue(TypeDescription type
) {
395 value
= type
.getZClass().newInstance();
396 } catch (IllegalAccessException e
) {
397 throw new RuntimeException(e
);
398 } catch (InstantiationException e
) {
399 throw new RuntimeException(e
);
401 readFields(type
, value
);
405 private Exception
readExceptionValue(TypeDescription type
) throws IOException
{
409 type
.getZClass().getConstructor(new Class
[] { String
.class }).
410 newInstance(new Object
[] { readStringValue() });
411 } catch (IllegalAccessException e
) {
412 throw new RuntimeException(e
);
413 } catch (InstantiationException e
) {
414 throw new RuntimeException(e
);
415 } catch (InvocationTargetException e
) {
416 throw new RuntimeException(e
);
417 } catch (NoSuchMethodException e
) {
418 throw new RuntimeException(e
);
420 readFields(type
, value
);
424 private Object
readInterfaceValue(TypeDescription type
) {
425 return readInterface(new Type(type
));
428 private int readCompressedNumber() throws IOException
{
429 int number
= read8Bit();
430 return number
< 0xFF ? number
: input
.readInt();
433 private void readBytes(byte[] data
) throws IOException
{
434 input
.readFully(data
);
437 private void readFields(TypeDescription type
, Object value
) {
438 IFieldDescription
[] fields
= type
.getFieldDescriptions();
439 for (int i
= 0; i
< fields
.length
; ++i
) {
441 fields
[i
].getField().set(
444 (TypeDescription
) fields
[i
].getTypeDescription()));
445 } catch (IllegalAccessException e
) {
446 throw new RuntimeException(e
);
451 private final IBridge bridge
;
452 private final String
[] objectIdCache
;
453 private final ThreadId
[] threadIdCache
;
454 private final TypeDescription
[] typeCache
;
455 private DataInputStream input
;