bump product version to 6.4.0.3
[LibreOffice.git] / jurt / com / sun / star / lib / uno / protocols / urp / Marshal.java
blob106a8736cb3186aa7521ed17d05800c0a72683cc
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
38 final class Marshal {
39 public Marshal(IBridge bridge, short cacheSize) {
40 this.bridge = bridge;
41 objectIdCache = new Cache(cacheSize);
42 threadIdCache = new Cache(cacheSize);
43 typeCache = new Cache(cacheSize);
46 public void write8Bit(int value) {
47 try {
48 output.writeByte(value);
49 } catch (IOException e) {
50 throw new RuntimeException(e);
54 public void write16Bit(int value) {
55 try {
56 output.writeShort(value);
57 } catch (IOException e) {
58 throw new RuntimeException(e);
62 public void writeObjectId(String objectId) {
63 try {
64 if (objectId == null) {
65 writeStringValue(null);
66 write16Bit(0xFFFF);
67 } else {
68 boolean[] found = new boolean[1];
69 int index = objectIdCache.add(found, objectId);
70 writeStringValue(found[0] ? null : objectId);
71 write16Bit(index);
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) {
83 try {
84 byte[] data = threadId.getBytes();
85 boolean[] found = new boolean[1];
86 int index = threadIdCache.add(found, data);
87 if (found[0]) {
88 writeCompressedNumber(0);
89 } else {
90 writeCompressedNumber(data.length);
91 writeBytes(data);
93 write16Bit(index);
94 } catch (IOException e) {
95 throw new RuntimeException(e);
99 public void writeType(TypeDescription type) {
100 try {
101 TypeClass typeClass = type.getTypeClass();
102 if (TypeDescription.isTypeClassSimple(typeClass)) {
103 write8Bit(typeClass.getValue());
104 } else {
105 boolean[] found = new boolean[1];
106 int index = typeCache.add(found, type.getTypeName());
107 write8Bit(typeClass.getValue() | (found[0] ? 0 : 0x80));
108 write16Bit(index);
109 if (!found[0]) {
110 writeStringValue(type.getTypeName());
113 } catch (IOException e) {
114 throw new RuntimeException(e);
118 public void writeValue(TypeDescription type, Object value) {
119 try {
120 switch(type.getTypeClass().getValue()) {
121 case TypeClass.VOID_value:
122 break;
124 case TypeClass.BOOLEAN_value:
125 writeBooleanValue((Boolean) value);
126 break;
128 case TypeClass.BYTE_value:
129 writeByteValue((Byte) value);
130 break;
132 case TypeClass.SHORT_value:
133 case TypeClass.UNSIGNED_SHORT_value:
134 writeShortValue((Short) value);
135 break;
137 case TypeClass.LONG_value:
138 case TypeClass.UNSIGNED_LONG_value:
139 writeLongValue((Integer) value);
140 break;
142 case TypeClass.HYPER_value:
143 case TypeClass.UNSIGNED_HYPER_value:
144 writeHyperValue((Long) value);
145 break;
147 case TypeClass.FLOAT_value:
148 writeFloatValue((Float) value);
149 break;
151 case TypeClass.DOUBLE_value:
152 writeDoubleValue((Double) value);
153 break;
155 case TypeClass.CHAR_value:
156 writeCharValue((Character) value);
157 break;
159 case TypeClass.STRING_value:
160 writeStringValue((String) value);
161 break;
163 case TypeClass.TYPE_value:
164 writeTypeValue((Type) value);
165 break;
167 case TypeClass.ANY_value:
168 writeAnyValue(value);
169 break;
171 case TypeClass.SEQUENCE_value:
172 writeSequenceValue(type, value);
173 break;
175 case TypeClass.ENUM_value:
176 writeEnumValue(type, (Enum) value);
177 break;
179 case TypeClass.STRUCT_value:
180 writeStructValue(type, value);
181 break;
183 case TypeClass.EXCEPTION_value:
184 writeExceptionValue(type, (Exception) value);
185 break;
187 case TypeClass.INTERFACE_value:
188 writeInterfaceValue(type, (XInterface) value);
189 break;
191 default:
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();
209 buffer.reset();
210 return data;
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 {
246 if (value == null) {
247 writeCompressedNumber(0);
248 } else {
249 byte[] data = value.getBytes("UTF8");
250 writeCompressedNumber(data.length);
251 writeBytes(data);
255 private void writeTypeValue(Type value) throws ClassNotFoundException {
256 writeType(
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");
273 } else {
274 type = TypeDescription.getTypeDescription(value.getClass());
276 writeType(type);
277 writeValue(type, value);
280 private void writeSequenceValue(TypeDescription type, Object value) throws IOException {
281 if (value == null) {
282 writeCompressedNumber(0);
283 } else {
284 TypeDescription ctype = type.getComponentType();
285 if (ctype.getTypeClass() == TypeClass.BYTE) {
286 byte[] data = (byte[]) value;
287 writeCompressedNumber(data.length);
288 writeBytes(data);
289 } else {
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 {
300 int n;
301 if (value == null) {
302 n = ((Enum)
303 (type.getZClass().getMethod("getDefault", (Class[]) null).
304 invoke(null, (Object[]) null))).
305 getValue();
306 } else {
307 n = value.getValue();
309 write32Bit(n);
312 private void writeStructValue(TypeDescription type, Object value) throws IllegalAccessException {
313 FieldDescription[] fields = type.getFieldDescriptions();
314 for (int i = 0; i < fields.length; ++i) {
315 writeValue(
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) {
336 write8Bit(number);
337 } else {
338 write8Bit(0xFF);
339 write32Bit(number);
343 private void writeBytes(byte[] data) throws IOException {
344 output.write(data);
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: */