xref: /AOO41X/main/jurt/com/sun/star/lib/uno/protocols/urp/Marshal.java (revision 2be432768a66cc90838f6a32e76ec156f587e741)
1*2be43276SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2be43276SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2be43276SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2be43276SAndrew Rist  * distributed with this work for additional information
6*2be43276SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2be43276SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2be43276SAndrew Rist  * "License"); you may not use this file except in compliance
9*2be43276SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*2be43276SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*2be43276SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2be43276SAndrew Rist  * software distributed under the License is distributed on an
15*2be43276SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2be43276SAndrew Rist  * KIND, either express or implied.  See the License for the
17*2be43276SAndrew Rist  * specific language governing permissions and limitations
18*2be43276SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*2be43276SAndrew Rist  *************************************************************/
21*2be43276SAndrew Rist 
22*2be43276SAndrew Rist 
23cdf0e10cSrcweir package com.sun.star.lib.uno.protocols.urp;
24cdf0e10cSrcweir 
25cdf0e10cSrcweir import com.sun.star.lib.uno.environments.remote.ThreadId;
26cdf0e10cSrcweir import com.sun.star.lib.uno.typedesc.TypeDescription;
27cdf0e10cSrcweir import com.sun.star.uno.Any;
28cdf0e10cSrcweir import com.sun.star.uno.Enum;
29cdf0e10cSrcweir import com.sun.star.uno.IBridge;
30cdf0e10cSrcweir import com.sun.star.uno.IFieldDescription;
31cdf0e10cSrcweir import com.sun.star.uno.Type;
32cdf0e10cSrcweir import com.sun.star.uno.TypeClass;
33cdf0e10cSrcweir import com.sun.star.uno.XInterface;
34cdf0e10cSrcweir import java.io.ByteArrayOutputStream;
35cdf0e10cSrcweir import java.io.DataOutput;
36cdf0e10cSrcweir import java.io.DataOutputStream;
37cdf0e10cSrcweir import java.io.IOException;
38cdf0e10cSrcweir import java.io.UnsupportedEncodingException;
39cdf0e10cSrcweir import java.lang.reflect.Array;
40cdf0e10cSrcweir import java.lang.reflect.InvocationTargetException;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir final class Marshal {
Marshal(IBridge bridge, short cacheSize)43cdf0e10cSrcweir     public Marshal(IBridge bridge, short cacheSize) {
44cdf0e10cSrcweir         this.bridge = bridge;
45cdf0e10cSrcweir         objectIdCache = new Cache(cacheSize);
46cdf0e10cSrcweir         threadIdCache = new Cache(cacheSize);
47cdf0e10cSrcweir         typeCache = new Cache(cacheSize);
48cdf0e10cSrcweir     }
49cdf0e10cSrcweir 
write8Bit(int value)50cdf0e10cSrcweir     public void write8Bit(int value) {
51cdf0e10cSrcweir         try {
52cdf0e10cSrcweir             output.writeByte(value);
53cdf0e10cSrcweir         } catch (IOException e) {
54cdf0e10cSrcweir             throw new RuntimeException(e.toString());
55cdf0e10cSrcweir         }
56cdf0e10cSrcweir     }
57cdf0e10cSrcweir 
write16Bit(int value)58cdf0e10cSrcweir     public void write16Bit(int value) {
59cdf0e10cSrcweir         try {
60cdf0e10cSrcweir             output.writeShort(value);
61cdf0e10cSrcweir         } catch (IOException e) {
62cdf0e10cSrcweir             throw new RuntimeException(e.toString());
63cdf0e10cSrcweir         }
64cdf0e10cSrcweir     }
65cdf0e10cSrcweir 
writeObjectId(String objectId)66cdf0e10cSrcweir     public void writeObjectId(String objectId) {
67cdf0e10cSrcweir         if (objectId == null) {
68cdf0e10cSrcweir             writeStringValue(null);
69cdf0e10cSrcweir             write16Bit(0xFFFF);
70cdf0e10cSrcweir         } else {
71cdf0e10cSrcweir             boolean[] found = new boolean[1];
72cdf0e10cSrcweir             int index = objectIdCache.add(found, objectId);
73cdf0e10cSrcweir             writeStringValue(found[0] ? null : objectId);
74cdf0e10cSrcweir             write16Bit(index);
75cdf0e10cSrcweir         }
76cdf0e10cSrcweir     }
77cdf0e10cSrcweir 
writeInterface(XInterface object, Type type)78cdf0e10cSrcweir     public void writeInterface(XInterface object, Type type) {
79cdf0e10cSrcweir         writeObjectId((String) bridge.mapInterfaceTo(object, type));
80cdf0e10cSrcweir     }
81cdf0e10cSrcweir 
writeThreadId(ThreadId threadId)82cdf0e10cSrcweir     public void writeThreadId(ThreadId threadId) {
83cdf0e10cSrcweir         byte[] data = threadId.getBytes();
84cdf0e10cSrcweir         boolean[] found = new boolean[1];
85cdf0e10cSrcweir         int index = threadIdCache.add(found, data);
86cdf0e10cSrcweir         if (found[0]) {
87cdf0e10cSrcweir             writeCompressedNumber(0);
88cdf0e10cSrcweir         } else {
89cdf0e10cSrcweir             writeCompressedNumber(data.length);
90cdf0e10cSrcweir             writeBytes(data);
91cdf0e10cSrcweir         }
92cdf0e10cSrcweir         write16Bit(index);
93cdf0e10cSrcweir     }
94cdf0e10cSrcweir 
writeType(TypeDescription type)95cdf0e10cSrcweir     public void writeType(TypeDescription type) {
96cdf0e10cSrcweir         TypeClass typeClass = type.getTypeClass();
97cdf0e10cSrcweir         if (TypeDescription.isTypeClassSimple(typeClass)) {
98cdf0e10cSrcweir             write8Bit(typeClass.getValue());
99cdf0e10cSrcweir         } else {
100cdf0e10cSrcweir             boolean[] found = new boolean[1];
101cdf0e10cSrcweir             int index = typeCache.add(found, type.getTypeName());
102cdf0e10cSrcweir             write8Bit(typeClass.getValue() | (found[0] ? 0 : 0x80));
103cdf0e10cSrcweir             write16Bit(index);
104cdf0e10cSrcweir             if (!found[0]) {
105cdf0e10cSrcweir                 writeStringValue(type.getTypeName());
106cdf0e10cSrcweir             }
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir     }
109cdf0e10cSrcweir 
writeValue(TypeDescription type, Object value)110cdf0e10cSrcweir     public void writeValue(TypeDescription type, Object value) {
111cdf0e10cSrcweir         switch(type.getTypeClass().getValue()) {
112cdf0e10cSrcweir         case TypeClass.VOID_value:
113cdf0e10cSrcweir             break;
114cdf0e10cSrcweir 
115cdf0e10cSrcweir         case TypeClass.BOOLEAN_value:
116cdf0e10cSrcweir             writeBooleanValue((Boolean) value);
117cdf0e10cSrcweir             break;
118cdf0e10cSrcweir 
119cdf0e10cSrcweir         case TypeClass.BYTE_value:
120cdf0e10cSrcweir             writeByteValue((Byte) value);
121cdf0e10cSrcweir             break;
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         case TypeClass.SHORT_value:
124cdf0e10cSrcweir         case TypeClass.UNSIGNED_SHORT_value:
125cdf0e10cSrcweir             writeShortValue((Short) value);
126cdf0e10cSrcweir             break;
127cdf0e10cSrcweir 
128cdf0e10cSrcweir         case TypeClass.LONG_value:
129cdf0e10cSrcweir         case TypeClass.UNSIGNED_LONG_value:
130cdf0e10cSrcweir             writeLongValue((Integer) value);
131cdf0e10cSrcweir             break;
132cdf0e10cSrcweir 
133cdf0e10cSrcweir         case TypeClass.HYPER_value:
134cdf0e10cSrcweir         case TypeClass.UNSIGNED_HYPER_value:
135cdf0e10cSrcweir             writeHyperValue((Long) value);
136cdf0e10cSrcweir             break;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         case TypeClass.FLOAT_value:
139cdf0e10cSrcweir             writeFloatValue((Float) value);
140cdf0e10cSrcweir             break;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir         case TypeClass.DOUBLE_value:
143cdf0e10cSrcweir             writeDoubleValue((Double) value);
144cdf0e10cSrcweir             break;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir         case TypeClass.CHAR_value:
147cdf0e10cSrcweir             writeCharValue((Character) value);
148cdf0e10cSrcweir             break;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir         case TypeClass.STRING_value:
151cdf0e10cSrcweir             writeStringValue((String) value);
152cdf0e10cSrcweir             break;
153cdf0e10cSrcweir 
154cdf0e10cSrcweir         case TypeClass.TYPE_value:
155cdf0e10cSrcweir             writeTypeValue((Type) value);
156cdf0e10cSrcweir             break;
157cdf0e10cSrcweir 
158cdf0e10cSrcweir         case TypeClass.ANY_value:
159cdf0e10cSrcweir             writeAnyValue(value);
160cdf0e10cSrcweir             break;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         case TypeClass.SEQUENCE_value:
163cdf0e10cSrcweir             writeSequenceValue(type, value);
164cdf0e10cSrcweir             break;
165cdf0e10cSrcweir 
166cdf0e10cSrcweir         case TypeClass.ENUM_value:
167cdf0e10cSrcweir             writeEnumValue(type, (Enum) value);
168cdf0e10cSrcweir             break;
169cdf0e10cSrcweir 
170cdf0e10cSrcweir         case TypeClass.STRUCT_value:
171cdf0e10cSrcweir             writeStructValue(type, value);
172cdf0e10cSrcweir             break;
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         case TypeClass.EXCEPTION_value:
175cdf0e10cSrcweir             writeExceptionValue(type, (Exception) value);
176cdf0e10cSrcweir             break;
177cdf0e10cSrcweir 
178cdf0e10cSrcweir         case TypeClass.INTERFACE_value:
179cdf0e10cSrcweir             writeInterfaceValue(type, (XInterface) value);
180cdf0e10cSrcweir             break;
181cdf0e10cSrcweir 
182cdf0e10cSrcweir         default:
183cdf0e10cSrcweir             throw new IllegalArgumentException("Bad type descriptor " + type);
184cdf0e10cSrcweir         }
185cdf0e10cSrcweir     }
186cdf0e10cSrcweir 
reset()187cdf0e10cSrcweir     public byte[] reset() {
188cdf0e10cSrcweir         byte[] data = buffer.toByteArray();
189cdf0e10cSrcweir         buffer.reset();
190cdf0e10cSrcweir         return data;
191cdf0e10cSrcweir     }
192cdf0e10cSrcweir 
writeBooleanValue(Boolean value)193cdf0e10cSrcweir     private void writeBooleanValue(Boolean value) {
194cdf0e10cSrcweir         try {
195cdf0e10cSrcweir             output.writeBoolean(value != null && value.booleanValue());
196cdf0e10cSrcweir         } catch (IOException e) {
197cdf0e10cSrcweir             throw new RuntimeException(e.toString());
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir 
writeByteValue(Byte value)201cdf0e10cSrcweir     private void writeByteValue(Byte value) {
202cdf0e10cSrcweir         write8Bit(value == null ? 0 : value.byteValue());
203cdf0e10cSrcweir     }
204cdf0e10cSrcweir 
writeShortValue(Short value)205cdf0e10cSrcweir     private void writeShortValue(Short value) {
206cdf0e10cSrcweir         write16Bit(value == null ? 0 : value.shortValue());
207cdf0e10cSrcweir     }
208cdf0e10cSrcweir 
writeLongValue(Integer value)209cdf0e10cSrcweir     private void writeLongValue(Integer value) {
210cdf0e10cSrcweir         write32Bit(value == null ? 0 : value.intValue());
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
writeHyperValue(Long value)213cdf0e10cSrcweir     private void writeHyperValue(Long value) {
214cdf0e10cSrcweir         try {
215cdf0e10cSrcweir             output.writeLong(value == null ? 0 : value.longValue());
216cdf0e10cSrcweir         } catch (IOException e) {
217cdf0e10cSrcweir             throw new RuntimeException(e.toString());
218cdf0e10cSrcweir         }
219cdf0e10cSrcweir     }
220cdf0e10cSrcweir 
writeFloatValue(Float value)221cdf0e10cSrcweir     private void writeFloatValue(Float value) {
222cdf0e10cSrcweir         try {
223cdf0e10cSrcweir             output.writeFloat(value == null ? 0 : value.floatValue());
224cdf0e10cSrcweir         } catch (IOException e) {
225cdf0e10cSrcweir             throw new RuntimeException(e.toString());
226cdf0e10cSrcweir         }
227cdf0e10cSrcweir     }
228cdf0e10cSrcweir 
writeDoubleValue(Double value)229cdf0e10cSrcweir     private void writeDoubleValue(Double value) {
230cdf0e10cSrcweir         try {
231cdf0e10cSrcweir             output.writeDouble(value == null ? 0 : value.doubleValue());
232cdf0e10cSrcweir         } catch (IOException e) {
233cdf0e10cSrcweir             throw new RuntimeException(e.toString());
234cdf0e10cSrcweir         }
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir 
writeCharValue(Character value)237cdf0e10cSrcweir     private void writeCharValue(Character value) {
238cdf0e10cSrcweir         try {
239cdf0e10cSrcweir             output.writeChar(value == null ? 0 : value.charValue());
240cdf0e10cSrcweir         } catch (IOException e) {
241cdf0e10cSrcweir             throw new RuntimeException(e.toString());
242cdf0e10cSrcweir         }
243cdf0e10cSrcweir     }
244cdf0e10cSrcweir 
writeStringValue(String value)245cdf0e10cSrcweir     private void writeStringValue(String value) {
246cdf0e10cSrcweir         if (value == null) {
247cdf0e10cSrcweir             writeCompressedNumber(0);
248cdf0e10cSrcweir         } else {
249cdf0e10cSrcweir             byte[] data;
250cdf0e10cSrcweir             try {
251cdf0e10cSrcweir                 data = value.getBytes("UTF8");
252cdf0e10cSrcweir             } catch (UnsupportedEncodingException e) {
253cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
254cdf0e10cSrcweir             }
255cdf0e10cSrcweir             writeCompressedNumber(data.length);
256cdf0e10cSrcweir             writeBytes(data);
257cdf0e10cSrcweir         }
258cdf0e10cSrcweir     }
259cdf0e10cSrcweir 
writeTypeValue(Type value)260cdf0e10cSrcweir     private void writeTypeValue(Type value) {
261cdf0e10cSrcweir         try {
262cdf0e10cSrcweir             writeType(
263cdf0e10cSrcweir                 TypeDescription.getTypeDescription(
264cdf0e10cSrcweir                     value == null ? Type.VOID : value));
265cdf0e10cSrcweir         } catch (ClassNotFoundException e) {
266cdf0e10cSrcweir             throw new RuntimeException(e.toString());
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir     }
269cdf0e10cSrcweir 
writeAnyValue(Object value)270cdf0e10cSrcweir     private void writeAnyValue(Object value) {
271cdf0e10cSrcweir         TypeDescription type;
272cdf0e10cSrcweir         if (value == null || value instanceof XInterface) {
273cdf0e10cSrcweir             type = TypeDescription.getTypeDescription(XInterface.class);
274cdf0e10cSrcweir         } else if (value instanceof Any) {
275cdf0e10cSrcweir             Any any = (Any) value;
276cdf0e10cSrcweir             try {
277cdf0e10cSrcweir                 type = TypeDescription.getTypeDescription(any.getType());
278cdf0e10cSrcweir             } catch (ClassNotFoundException e) {
279cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
280cdf0e10cSrcweir             }
281cdf0e10cSrcweir             value = any.getObject();
282cdf0e10cSrcweir         } else if (value.getClass() == Object.class) {
283cdf0e10cSrcweir             // Avoid StackOverflowError:
284cdf0e10cSrcweir             throw new IllegalArgumentException(
285cdf0e10cSrcweir                 "Object instance does not represent UNO value");
286cdf0e10cSrcweir         } else {
287cdf0e10cSrcweir             type = TypeDescription.getTypeDescription(value.getClass());
288cdf0e10cSrcweir         }
289cdf0e10cSrcweir         writeType(type);
290cdf0e10cSrcweir         writeValue(type, value);
291cdf0e10cSrcweir     }
292cdf0e10cSrcweir 
writeSequenceValue(TypeDescription type, Object value)293cdf0e10cSrcweir     private void writeSequenceValue(TypeDescription type, Object value) {
294cdf0e10cSrcweir         if (value == null) {
295cdf0e10cSrcweir             writeCompressedNumber(0);
296cdf0e10cSrcweir         } else {
297cdf0e10cSrcweir             TypeDescription ctype = (TypeDescription) type.getComponentType();
298cdf0e10cSrcweir             if (ctype.getTypeClass() == TypeClass.BYTE) {
299cdf0e10cSrcweir                 byte[] data = (byte[]) value;
300cdf0e10cSrcweir                 writeCompressedNumber(data.length);
301cdf0e10cSrcweir                 writeBytes(data);
302cdf0e10cSrcweir             } else {
303cdf0e10cSrcweir                 int len = Array.getLength(value);
304cdf0e10cSrcweir                 writeCompressedNumber(len);
305cdf0e10cSrcweir                 for (int i = 0; i < len; ++i) {
306cdf0e10cSrcweir                     writeValue(ctype, Array.get(value, i));
307cdf0e10cSrcweir                 }
308cdf0e10cSrcweir             }
309cdf0e10cSrcweir         }
310cdf0e10cSrcweir     }
311cdf0e10cSrcweir 
writeEnumValue(TypeDescription type, Enum value)312cdf0e10cSrcweir     private void writeEnumValue(TypeDescription type, Enum value) {
313cdf0e10cSrcweir         int n;
314cdf0e10cSrcweir         if (value == null) {
315cdf0e10cSrcweir             try {
316cdf0e10cSrcweir                 n = ((Enum)
317cdf0e10cSrcweir                      (type.getZClass().getMethod("getDefault", null).
318cdf0e10cSrcweir                       invoke(null, null))).
319cdf0e10cSrcweir                     getValue();
320cdf0e10cSrcweir             } catch (IllegalAccessException e) {
321cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
322cdf0e10cSrcweir             } catch (InvocationTargetException e) {
323cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
324cdf0e10cSrcweir             } catch (NoSuchMethodException e) {
325cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
326cdf0e10cSrcweir             }
327cdf0e10cSrcweir         } else {
328cdf0e10cSrcweir             n = value.getValue();
329cdf0e10cSrcweir         }
330cdf0e10cSrcweir         write32Bit(n);
331cdf0e10cSrcweir     }
332cdf0e10cSrcweir 
writeStructValue(TypeDescription type, Object value)333cdf0e10cSrcweir     private void writeStructValue(TypeDescription type, Object value) {
334cdf0e10cSrcweir         IFieldDescription[] fields = type.getFieldDescriptions();
335cdf0e10cSrcweir         for (int i = 0; i < fields.length; ++i) {
336cdf0e10cSrcweir             try {
337cdf0e10cSrcweir                 writeValue(
338cdf0e10cSrcweir                     (TypeDescription) fields[i].getTypeDescription(),
339cdf0e10cSrcweir                     value == null ? null : fields[i].getField().get(value));
340cdf0e10cSrcweir             } catch (IllegalAccessException e) {
341cdf0e10cSrcweir                 throw new RuntimeException(e.toString());
342cdf0e10cSrcweir             }
343cdf0e10cSrcweir         }
344cdf0e10cSrcweir     }
345cdf0e10cSrcweir 
writeExceptionValue(TypeDescription type, Exception value)346cdf0e10cSrcweir     private void writeExceptionValue(TypeDescription type, Exception value) {
347cdf0e10cSrcweir         writeStringValue(value == null ? null : value.getMessage());
348cdf0e10cSrcweir         writeStructValue(type, value);
349cdf0e10cSrcweir     }
350cdf0e10cSrcweir 
writeInterfaceValue(TypeDescription type, XInterface value)351cdf0e10cSrcweir     private void writeInterfaceValue(TypeDescription type, XInterface value) {
352cdf0e10cSrcweir         writeInterface(value, new Type(type));
353cdf0e10cSrcweir     }
354cdf0e10cSrcweir 
write32Bit(int value)355cdf0e10cSrcweir     private void write32Bit(int value) {
356cdf0e10cSrcweir         try {
357cdf0e10cSrcweir             output.writeInt(value);
358cdf0e10cSrcweir         } catch (IOException e) {
359cdf0e10cSrcweir             throw new RuntimeException(e.toString());
360cdf0e10cSrcweir         }
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
writeCompressedNumber(int number)363cdf0e10cSrcweir     private void writeCompressedNumber(int number) {
364cdf0e10cSrcweir         if (number >= 0 && number < 0xFF) {
365cdf0e10cSrcweir             write8Bit(number);
366cdf0e10cSrcweir         } else {
367cdf0e10cSrcweir             write8Bit(0xFF);
368cdf0e10cSrcweir             write32Bit(number);
369cdf0e10cSrcweir         }
370cdf0e10cSrcweir     }
371cdf0e10cSrcweir 
writeBytes(byte[] data)372cdf0e10cSrcweir     private void writeBytes(byte[] data) {
373cdf0e10cSrcweir         try {
374cdf0e10cSrcweir             output.write(data);
375cdf0e10cSrcweir         } catch (IOException e) {
376cdf0e10cSrcweir             throw new RuntimeException(e.toString());
377cdf0e10cSrcweir         }
378cdf0e10cSrcweir     }
379cdf0e10cSrcweir 
380cdf0e10cSrcweir     private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
381cdf0e10cSrcweir     private final DataOutput output = new DataOutputStream(buffer);
382cdf0e10cSrcweir     private final IBridge bridge;
383cdf0e10cSrcweir     private final Cache objectIdCache;
384cdf0e10cSrcweir     private final Cache threadIdCache;
385cdf0e10cSrcweir     private final Cache typeCache;
386cdf0e10cSrcweir }
387