bump product version to 5.0.4.1
[LibreOffice.git] / jurt / com / sun / star / lib / uno / protocols / urp / Marshal.java
blobc226e3a4068a951f0f03c1195e2cd876c41357e2
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 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;
37 final class Marshal {
38 public Marshal(IBridge bridge, short cacheSize) {
39 this.bridge = bridge;
40 objectIdCache = new Cache(cacheSize);
41 threadIdCache = new Cache(cacheSize);
42 typeCache = new Cache(cacheSize);
45 public void write8Bit(int value) {
46 try {
47 output.writeByte(value);
48 } catch (IOException e) {
49 throw new RuntimeException(e);
53 public void write16Bit(int value) {
54 try {
55 output.writeShort(value);
56 } catch (IOException e) {
57 throw new RuntimeException(e);
61 public void writeObjectId(String objectId) {
62 try {
63 if (objectId == null) {
64 writeStringValue(null);
65 write16Bit(0xFFFF);
66 } else {
67 boolean[] found = new boolean[1];
68 int index = objectIdCache.add(found, objectId);
69 writeStringValue(found[0] ? null : objectId);
70 write16Bit(index);
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) {
82 try {
83 byte[] data = threadId.getBytes();
84 boolean[] found = new boolean[1];
85 int index = threadIdCache.add(found, data);
86 if (found[0]) {
87 writeCompressedNumber(0);
88 } else {
89 writeCompressedNumber(data.length);
90 writeBytes(data);
92 write16Bit(index);
93 } catch (IOException e) {
94 throw new RuntimeException(e);
98 public void writeType(TypeDescription type) {
99 try {
100 TypeClass typeClass = type.getTypeClass();
101 if (TypeDescription.isTypeClassSimple(typeClass)) {
102 write8Bit(typeClass.getValue());
103 } else {
104 boolean[] found = new boolean[1];
105 int index = typeCache.add(found, type.getTypeName());
106 write8Bit(typeClass.getValue() | (found[0] ? 0 : 0x80));
107 write16Bit(index);
108 if (!found[0]) {
109 writeStringValue(type.getTypeName());
112 } catch (IOException e) {
113 throw new RuntimeException(e);
117 public void writeValue(TypeDescription type, Object value) {
118 try {
119 switch(type.getTypeClass().getValue()) {
120 case TypeClass.VOID_value:
121 break;
123 case TypeClass.BOOLEAN_value:
124 writeBooleanValue((Boolean) value);
125 break;
127 case TypeClass.BYTE_value:
128 writeByteValue((Byte) value);
129 break;
131 case TypeClass.SHORT_value:
132 case TypeClass.UNSIGNED_SHORT_value:
133 writeShortValue((Short) value);
134 break;
136 case TypeClass.LONG_value:
137 case TypeClass.UNSIGNED_LONG_value:
138 writeLongValue((Integer) value);
139 break;
141 case TypeClass.HYPER_value:
142 case TypeClass.UNSIGNED_HYPER_value:
143 writeHyperValue((Long) value);
144 break;
146 case TypeClass.FLOAT_value:
147 writeFloatValue((Float) value);
148 break;
150 case TypeClass.DOUBLE_value:
151 writeDoubleValue((Double) value);
152 break;
154 case TypeClass.CHAR_value:
155 writeCharValue((Character) value);
156 break;
158 case TypeClass.STRING_value:
159 writeStringValue((String) value);
160 break;
162 case TypeClass.TYPE_value:
163 writeTypeValue((Type) value);
164 break;
166 case TypeClass.ANY_value:
167 writeAnyValue(value);
168 break;
170 case TypeClass.SEQUENCE_value:
171 writeSequenceValue(type, value);
172 break;
174 case TypeClass.ENUM_value:
175 writeEnumValue(type, (Enum) value);
176 break;
178 case TypeClass.STRUCT_value:
179 writeStructValue(type, value);
180 break;
182 case TypeClass.EXCEPTION_value:
183 writeExceptionValue(type, (Exception) value);
184 break;
186 case TypeClass.INTERFACE_value:
187 writeInterfaceValue(type, (XInterface) value);
188 break;
190 default:
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();
208 buffer.reset();
209 return data;
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 {
245 if (value == null) {
246 writeCompressedNumber(0);
247 } else {
248 byte[] data = value.getBytes("UTF8");
249 writeCompressedNumber(data.length);
250 writeBytes(data);
254 private void writeTypeValue(Type value) throws ClassNotFoundException {
255 writeType(
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");
272 } else {
273 type = TypeDescription.getTypeDescription(value.getClass());
275 writeType(type);
276 writeValue(type, value);
279 private void writeSequenceValue(TypeDescription type, Object value) throws IOException {
280 if (value == null) {
281 writeCompressedNumber(0);
282 } else {
283 TypeDescription ctype = (TypeDescription) type.getComponentType();
284 if (ctype.getTypeClass() == TypeClass.BYTE) {
285 byte[] data = (byte[]) value;
286 writeCompressedNumber(data.length);
287 writeBytes(data);
288 } else {
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 {
299 int n;
300 if (value == null) {
301 n = ((Enum)
302 (type.getZClass().getMethod("getDefault", (Class[]) null).
303 invoke(null, (Object[]) null))).
304 getValue();
305 } else {
306 n = value.getValue();
308 write32Bit(n);
311 private void writeStructValue(TypeDescription type, Object value) throws IllegalAccessException {
312 IFieldDescription[] fields = type.getFieldDescriptions();
313 for (int i = 0; i < fields.length; ++i) {
314 writeValue(
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) {
335 write8Bit(number);
336 } else {
337 write8Bit(0xFF);
338 write32Bit(number);
342 private void writeBytes(byte[] data) throws IOException {
343 output.write(data);
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;