1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 package com.sun.star.lib.uno.protocols.urp; 24 25 import com.sun.star.lib.uno.environments.remote.ThreadId; 26 import com.sun.star.lib.uno.typedesc.TypeDescription; 27 import com.sun.star.uno.Any; 28 import com.sun.star.uno.Enum; 29 import com.sun.star.uno.IBridge; 30 import com.sun.star.uno.IFieldDescription; 31 import com.sun.star.uno.Type; 32 import com.sun.star.uno.TypeClass; 33 import com.sun.star.uno.XInterface; 34 import java.io.ByteArrayInputStream; 35 import java.io.DataInputStream; 36 import java.io.IOException; 37 import java.io.UnsupportedEncodingException; 38 import java.lang.reflect.Array; 39 import java.lang.reflect.InvocationTargetException; 40 41 final class Unmarshal { Unmarshal(IBridge bridge, int cacheSize)42 public Unmarshal(IBridge bridge, int cacheSize) { 43 this.bridge = bridge; 44 objectIdCache = new String[cacheSize]; 45 threadIdCache = new ThreadId[cacheSize]; 46 typeCache = new TypeDescription[cacheSize]; 47 reset(new byte[0]); 48 } 49 read8Bit()50 public int read8Bit() { 51 try { 52 return input.readUnsignedByte(); 53 } catch (IOException e) { 54 throw new RuntimeException(e.toString()); 55 } 56 } 57 read16Bit()58 public int read16Bit() { 59 try { 60 return input.readUnsignedShort(); 61 } catch (IOException e) { 62 throw new RuntimeException(e.toString()); 63 } 64 } 65 readObjectId()66 public String readObjectId() { 67 String id = readStringValue(); 68 int index = read16Bit(); 69 if (index == 0xFFFF) { 70 if (id.length() == 0) { 71 id = null; 72 } 73 } else { 74 if (id.length() == 0) { 75 id = objectIdCache[index]; 76 } else { 77 objectIdCache[index] = id; 78 } 79 } 80 return id; 81 } 82 readInterface(Type type)83 public Object readInterface(Type type) { 84 String id = readObjectId(); 85 return id == null ? null : bridge.mapInterfaceFrom(id, type); 86 } 87 readThreadId()88 public ThreadId readThreadId() { 89 int len = readCompressedNumber(); 90 byte[] data ; 91 ThreadId id = null; 92 if (len != 0) { 93 data = new byte[len]; 94 readBytes(data); 95 id = new ThreadId(data); 96 } 97 int index = read16Bit(); 98 if (index != 0xFFFF) { 99 if (len == 0) { 100 id = threadIdCache[index]; 101 } else { 102 threadIdCache[index] = id; 103 } 104 } 105 return id; 106 } 107 readType()108 public TypeDescription readType() { 109 int b = read8Bit(); 110 TypeClass typeClass = TypeClass.fromInt(b & 0x7F); 111 if (TypeDescription.isTypeClassSimple(typeClass)) { 112 return TypeDescription.getTypeDescription(typeClass); 113 } else { 114 int index = read16Bit(); 115 TypeDescription type = null; 116 if ((b & 0x80) != 0) { 117 try { 118 type = TypeDescription.getTypeDescription( 119 readStringValue()); 120 } catch (ClassNotFoundException e) { 121 throw new RuntimeException(e.toString()); 122 } 123 } 124 if (index != 0xFFFF) { 125 if ((b & 0x80) == 0) { 126 type = typeCache[index]; 127 } else { 128 typeCache[index] = type; 129 } 130 } 131 return type; 132 } 133 } 134 readValue(TypeDescription type)135 public Object readValue(TypeDescription type) { 136 switch (type.getTypeClass().getValue()) { 137 case TypeClass.VOID_value: 138 return null; 139 140 case TypeClass.BOOLEAN_value: 141 return readBooleanValue(); 142 143 case TypeClass.BYTE_value: 144 return readByteValue(); 145 146 case TypeClass.SHORT_value: 147 case TypeClass.UNSIGNED_SHORT_value: 148 return readShortValue(); 149 150 case TypeClass.LONG_value: 151 case TypeClass.UNSIGNED_LONG_value: 152 return readLongValue(); 153 154 case TypeClass.HYPER_value: 155 case TypeClass.UNSIGNED_HYPER_value: 156 return readHyperValue(); 157 158 case TypeClass.FLOAT_value: 159 return readFloatValue(); 160 161 case TypeClass.DOUBLE_value: 162 return readDoubleValue(); 163 164 case TypeClass.CHAR_value: 165 return readCharValue(); 166 167 case TypeClass.STRING_value: 168 return readStringValue(); 169 170 case TypeClass.TYPE_value: 171 return readTypeValue(); 172 173 case TypeClass.ANY_value: 174 return readAnyValue(); 175 176 case TypeClass.SEQUENCE_value: 177 return readSequenceValue(type); 178 179 case TypeClass.ENUM_value: 180 return readEnumValue(type); 181 182 case TypeClass.STRUCT_value: 183 return readStructValue(type); 184 185 case TypeClass.EXCEPTION_value: 186 return readExceptionValue(type); 187 188 case TypeClass.INTERFACE_value: 189 return readInterfaceValue(type); 190 191 default: 192 throw new IllegalArgumentException("Bad type descriptor " + type); 193 } 194 } 195 hasMore()196 public boolean hasMore() { 197 try { 198 return input.available() > 0; 199 } catch (IOException e) { 200 throw new RuntimeException(e.toString()); 201 } 202 } 203 reset(byte[] data)204 public void reset(byte[] data) { 205 input = new DataInputStream(new ByteArrayInputStream(data)); 206 } 207 readBooleanValue()208 private Boolean readBooleanValue() { 209 try { 210 return input.readBoolean() ? Boolean.TRUE : Boolean.FALSE; 211 } catch (IOException e) { 212 throw new RuntimeException(e.toString()); 213 } 214 } 215 readByteValue()216 private Byte readByteValue() { 217 try { 218 return new Byte(input.readByte()); 219 } catch (IOException e) { 220 throw new RuntimeException(e.toString()); 221 } 222 } 223 readShortValue()224 private Short readShortValue() { 225 try { 226 return new Short(input.readShort()); 227 } catch (IOException e) { 228 throw new RuntimeException(e.toString()); 229 } 230 } 231 readLongValue()232 private Integer readLongValue() { 233 try { 234 return new Integer(input.readInt()); 235 } catch (IOException e) { 236 throw new RuntimeException(e.toString()); 237 } 238 } 239 readHyperValue()240 private Long readHyperValue() { 241 try { 242 return new Long(input.readLong()); 243 } catch (IOException e) { 244 throw new RuntimeException(e.toString()); 245 } 246 } 247 readFloatValue()248 private Float readFloatValue() { 249 try { 250 return new Float(input.readFloat()); 251 } catch (IOException e) { 252 throw new RuntimeException(e.toString()); 253 } 254 } 255 readDoubleValue()256 private Double readDoubleValue() { 257 try { 258 return new Double(input.readDouble()); 259 } catch (IOException e) { 260 throw new RuntimeException(e.toString()); 261 } 262 } 263 readCharValue()264 private Character readCharValue() { 265 try { 266 return new Character(input.readChar()); 267 } catch (IOException e) { 268 throw new RuntimeException(e.toString()); 269 } 270 } 271 readStringValue()272 private String readStringValue() { 273 int len = readCompressedNumber(); 274 byte[] data = new byte[len]; 275 readBytes(data); 276 try { 277 return new String(data, "UTF8"); 278 } catch (UnsupportedEncodingException e) { 279 throw new RuntimeException(e.toString()); 280 } 281 } 282 readTypeValue()283 private Type readTypeValue() { 284 return new Type(readType()); 285 } 286 readAnyValue()287 private Object readAnyValue() { 288 TypeDescription type = readType(); 289 switch (type.getTypeClass().getValue()) { 290 case TypeClass.VOID_value: 291 return Any.VOID; 292 293 case TypeClass.BOOLEAN_value: 294 return readBooleanValue(); 295 296 case TypeClass.BYTE_value: 297 return readByteValue(); 298 299 case TypeClass.SHORT_value: 300 return readShortValue(); 301 302 case TypeClass.UNSIGNED_SHORT_value: 303 return new Any(Type.UNSIGNED_SHORT, readShortValue()); 304 305 case TypeClass.LONG_value: 306 return readLongValue(); 307 308 case TypeClass.UNSIGNED_LONG_value: 309 return new Any(Type.UNSIGNED_LONG, readLongValue()); 310 311 case TypeClass.HYPER_value: 312 return readHyperValue(); 313 314 case TypeClass.UNSIGNED_HYPER_value: 315 return new Any(Type.UNSIGNED_HYPER, readHyperValue()); 316 317 case TypeClass.FLOAT_value: 318 return readFloatValue(); 319 320 case TypeClass.DOUBLE_value: 321 return readDoubleValue(); 322 323 case TypeClass.CHAR_value: 324 return readCharValue(); 325 326 case TypeClass.STRING_value: 327 return readStringValue(); 328 329 case TypeClass.TYPE_value: 330 return readTypeValue(); 331 332 case TypeClass.SEQUENCE_value: 333 { 334 Object value = readSequenceValue(type); 335 TypeDescription ctype = (TypeDescription) 336 type.getComponentType(); 337 while (ctype.getTypeClass() == TypeClass.SEQUENCE) { 338 ctype = (TypeDescription) ctype.getComponentType(); 339 } 340 switch (ctype.getTypeClass().getValue()) { 341 case TypeClass.UNSIGNED_SHORT_value: 342 case TypeClass.UNSIGNED_LONG_value: 343 case TypeClass.UNSIGNED_HYPER_value: 344 return new Any(new Type(type), value); 345 346 case TypeClass.STRUCT_value: 347 if (ctype.hasTypeArguments()) { 348 return new Any(new Type(type), value); 349 } 350 default: 351 return value; 352 } 353 } 354 355 case TypeClass.ENUM_value: 356 return readEnumValue(type); 357 358 case TypeClass.STRUCT_value: 359 { 360 Object value = readStructValue(type); 361 return type.hasTypeArguments() 362 ? new Any(new Type(type), value) : value; 363 } 364 365 case TypeClass.EXCEPTION_value: 366 return readExceptionValue(type); 367 368 case TypeClass.INTERFACE_value: 369 { 370 Object value = readInterfaceValue(type); 371 return type.getZClass() == XInterface.class 372 ? value : new Any(new Type(type), value); 373 } 374 375 default: 376 throw new RuntimeException( 377 "Reading ANY with bad type " + type.getTypeClass()); 378 } 379 } 380 readSequenceValue(TypeDescription type)381 private Object readSequenceValue(TypeDescription type) { 382 int len = readCompressedNumber(); 383 TypeDescription ctype = (TypeDescription) type.getComponentType(); 384 if (ctype.getTypeClass() == TypeClass.BYTE) { 385 byte[] data = new byte[len]; 386 readBytes(data); 387 return data; 388 } else { 389 Object value = Array.newInstance( 390 ctype.getTypeClass() == TypeClass.ANY 391 ? Object.class : ctype.getZClass(), len); 392 for (int i = 0; i < len; ++i) { 393 Array.set(value, i, readValue(ctype)); 394 } 395 return value; 396 } 397 } 398 readEnumValue(TypeDescription type)399 private Enum readEnumValue(TypeDescription type) { 400 try { 401 return (Enum) 402 type.getZClass().getMethod( 403 "fromInt", new Class[] { int.class }). 404 invoke(null, new Object[] { readLongValue() }); 405 } catch (IllegalAccessException e) { 406 throw new RuntimeException(e.toString()); 407 } catch (InvocationTargetException e) { 408 throw new RuntimeException(e.toString()); 409 } catch (NoSuchMethodException e) { 410 throw new RuntimeException(e.toString()); 411 } 412 } 413 readStructValue(TypeDescription type)414 private Object readStructValue(TypeDescription type) { 415 Object value; 416 try { 417 value = type.getZClass().newInstance(); 418 } catch (IllegalAccessException e) { 419 throw new RuntimeException(e.toString()); 420 } catch (InstantiationException e) { 421 throw new RuntimeException(e.toString()); 422 } 423 readFields(type, value); 424 return value; 425 } 426 readExceptionValue(TypeDescription type)427 private Exception readExceptionValue(TypeDescription type) { 428 Exception value; 429 try { 430 value = (Exception) 431 type.getZClass().getConstructor(new Class[] { String.class }). 432 newInstance(new Object[] { readStringValue() }); 433 } catch (IllegalAccessException e) { 434 throw new RuntimeException(e.toString()); 435 } catch (InstantiationException e) { 436 throw new RuntimeException(e.toString()); 437 } catch (InvocationTargetException e) { 438 throw new RuntimeException(e.toString()); 439 } catch (NoSuchMethodException e) { 440 throw new RuntimeException(e.toString()); 441 } 442 readFields(type, value); 443 return value; 444 } 445 readInterfaceValue(TypeDescription type)446 private Object readInterfaceValue(TypeDescription type) { 447 return readInterface(new Type(type)); 448 } 449 readCompressedNumber()450 private int readCompressedNumber() { 451 int number = read8Bit(); 452 try { 453 return number < 0xFF ? number : input.readInt(); 454 } catch (IOException e) { 455 throw new RuntimeException(e.toString()); 456 } 457 } 458 readBytes(byte[] data)459 private void readBytes(byte[] data) { 460 try { 461 input.readFully(data); 462 } catch (IOException e) { 463 throw new RuntimeException(e.toString()); 464 } 465 } 466 readFields(TypeDescription type, Object value)467 private void readFields(TypeDescription type, Object value) { 468 IFieldDescription[] fields = type.getFieldDescriptions(); 469 for (int i = 0; i < fields.length; ++i) { 470 try { 471 fields[i].getField().set( 472 value, 473 readValue( 474 (TypeDescription) fields[i].getTypeDescription())); 475 } catch (IllegalAccessException e) { 476 throw new RuntimeException(e.toString()); 477 } 478 } 479 } 480 481 private final IBridge bridge; 482 private final String[] objectIdCache; 483 private final ThreadId[] threadIdCache; 484 private final TypeDescription[] typeCache; 485 private DataInputStream input; 486 } 487