bump product version to 5.0.4.1
[LibreOffice.git] / jurt / com / sun / star / lib / uno / protocols / urp / Unmarshal.java
blob48d7630dd7e24de2f844240fdc69372f631589fc
1 /*
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) {
39 this.bridge = bridge;
40 objectIdCache = new String[cacheSize];
41 threadIdCache = new ThreadId[cacheSize];
42 typeCache = new TypeDescription[cacheSize];
43 reset(new byte[0]);
46 public int read8Bit() {
47 try {
48 return input.readUnsignedByte();
49 } catch (IOException e) {
50 throw new RuntimeException(e);
54 public int read16Bit() {
55 try {
56 return input.readUnsignedShort();
57 } catch (IOException e) {
58 throw new RuntimeException(e);
62 public String readObjectId() {
63 try {
64 String id = readStringValue();
65 int index = read16Bit();
66 if (index == 0xFFFF) {
67 if (id.length() == 0) {
68 id = null;
70 } else {
71 if (id.length() == 0) {
72 id = objectIdCache[index];
73 } else {
74 objectIdCache[index] = id;
77 return 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() {
89 try {
90 int len = readCompressedNumber();
91 byte[] data ;
92 ThreadId id = null;
93 if (len != 0) {
94 data = new byte[len];
95 readBytes(data);
96 id = new ThreadId(data);
98 int index = read16Bit();
99 if (index != 0xFFFF) {
100 if (len == 0) {
101 id = threadIdCache[index];
102 } else {
103 threadIdCache[index] = id;
106 return id;
107 } catch (IOException e) {
108 throw new RuntimeException(e);
112 public TypeDescription readType() {
113 int b = read8Bit();
114 TypeClass typeClass = TypeClass.fromInt(b & 0x7F);
115 if (TypeDescription.isTypeClassSimple(typeClass)) {
116 return TypeDescription.getTypeDescription(typeClass);
117 } else {
118 int index = read16Bit();
119 TypeDescription type = null;
120 if ((b & 0x80) != 0) {
121 try {
122 type = TypeDescription.getTypeDescription(
123 readStringValue());
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];
133 } else {
134 typeCache[index] = type;
137 return type;
141 public Object readValue(TypeDescription type) {
142 try {
143 switch (type.getTypeClass().getValue()) {
144 case TypeClass.VOID_value:
145 return null;
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);
198 default:
199 throw new IllegalArgumentException("Bad type descriptor " + type);
201 } catch (IOException e) {
202 throw new RuntimeException(e);
206 public boolean hasMore() {
207 try {
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];
253 readBytes(data);
254 try {
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:
269 return Any.VOID;
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);
328 default:
329 return 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);
353 default:
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];
364 readBytes(data);
365 return data;
366 } else {
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));
373 return value;
377 private Enum readEnumValue(TypeDescription type) throws IOException {
378 try {
379 return (Enum)
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) {
393 Object value;
394 try {
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);
402 return value;
405 private Exception readExceptionValue(TypeDescription type) throws IOException {
406 Exception value;
407 try {
408 value = (Exception)
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);
421 return 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) {
440 try {
441 fields[i].getField().set(
442 value,
443 readValue(
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;