1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package com.sun.star.lib.uno.protocols.urp; 29 30 import com.sun.star.bridge.InvalidProtocolChangeException; 31 import com.sun.star.bridge.ProtocolProperty; 32 import com.sun.star.bridge.XProtocolProperties; 33 import com.sun.star.lang.DisposedException; 34 import com.sun.star.lib.uno.environments.remote.IProtocol; 35 import com.sun.star.lib.uno.environments.remote.Message; 36 import com.sun.star.lib.uno.environments.remote.ThreadId; 37 import com.sun.star.lib.uno.typedesc.MethodDescription; 38 import com.sun.star.lib.uno.typedesc.TypeDescription; 39 import com.sun.star.uno.Any; 40 import com.sun.star.uno.IBridge; 41 import com.sun.star.uno.IMethodDescription; 42 import com.sun.star.uno.ITypeDescription; 43 import com.sun.star.uno.Type; 44 import com.sun.star.uno.TypeClass; 45 import com.sun.star.uno.UnoRuntime; 46 import com.sun.star.uno.XCurrentContext; 47 import java.io.DataInput; 48 import java.io.DataInputStream; 49 import java.io.DataOutputStream; 50 import java.io.IOException; 51 import java.io.InputStream; 52 import java.io.OutputStream; 53 import java.lang.reflect.Array; 54 import java.util.ArrayList; 55 import java.util.Random; 56 import java.util.StringTokenizer; 57 58 // This class internally relies on the availability of Java UNO type information 59 // for the interface type com.sun.star.bridge.XProtocolProperties, even though 60 // URP itself does not rely on that type. 61 62 public final class urp implements IProtocol { 63 public urp( 64 IBridge bridge, String attributes, InputStream input, 65 OutputStream output) 66 { 67 this.input = new DataInputStream(input); 68 this.output = new DataOutputStream(output); 69 marshal = new Marshal(bridge, CACHE_SIZE); 70 unmarshal = new Unmarshal(bridge, CACHE_SIZE); 71 forceSynchronous = parseAttributes(attributes); 72 } 73 74 // @see IProtocol#init 75 public void init() throws IOException { 76 synchronized (monitor) { 77 if (state == STATE_INITIAL0) { 78 sendRequestChange(); 79 } 80 } 81 } 82 83 // @see IProtocol#terminate 84 public void terminate() { 85 synchronized (monitor) { 86 state = STATE_TERMINATED; 87 initialized = true; 88 monitor.notifyAll(); 89 } 90 } 91 92 // @see IProtocol#readMessage 93 public Message readMessage() throws IOException { 94 for (;;) { 95 if (!unmarshal.hasMore()) { 96 unmarshal.reset(readBlock()); 97 if (!unmarshal.hasMore()) { 98 throw new IOException("closeConnection message received"); 99 } 100 } 101 UrpMessage msg; 102 int header = unmarshal.read8Bit(); 103 if ((header & HEADER_LONGHEADER) != 0) { 104 if ((header & HEADER_REQUEST) != 0) { 105 msg = readLongRequest(header); 106 } else { 107 msg = readReply(header); 108 } 109 } else { 110 msg = readShortRequest(header); 111 } 112 if (msg.isInternal()) { 113 handleInternalMessage(msg); 114 } else { 115 return msg; 116 } 117 } 118 } 119 120 // @see IProtocol#writeRequest 121 public boolean writeRequest( 122 String oid, TypeDescription type, String function, ThreadId tid, 123 Object[] arguments) 124 throws IOException 125 { 126 if (oid.equals(PROPERTIES_OID)) { 127 throw new IllegalArgumentException("illegal OID " + oid); 128 } 129 synchronized (monitor) { 130 while (!initialized) { 131 try { 132 monitor.wait(); 133 } catch (InterruptedException e) { 134 Thread.currentThread().interrupt(); 135 throw new RuntimeException(e.toString()); 136 } 137 } 138 if (state == STATE_TERMINATED) { 139 throw new DisposedException(); 140 } 141 return writeRequest(false, oid, type, function, tid, arguments); 142 } 143 } 144 145 // @see IProtocol#writeReply 146 public void writeReply(boolean exception, ThreadId tid, Object result) 147 throws IOException 148 { 149 synchronized (output) { 150 writeQueuedReleases(); 151 int header = HEADER_LONGHEADER; 152 PendingRequests.Item pending = pendingIn.pop(tid); 153 TypeDescription resultType; 154 ITypeDescription[] argTypes; 155 Object[] args; 156 if (exception) { 157 header |= HEADER_EXCEPTION; 158 resultType = TypeDescription.getTypeDescription(TypeClass.ANY); 159 argTypes = null; 160 args = null; 161 } else { 162 resultType = (TypeDescription) 163 pending.function.getReturnSignature(); 164 argTypes = pending.function.getOutSignature(); 165 args = pending.arguments; 166 } 167 if (!tid.equals(outL1Tid)) { 168 header |= HEADER_NEWTID; 169 outL1Tid = tid; 170 } else { 171 tid = null; 172 } 173 marshal.write8Bit(header); 174 if (tid != null) { 175 marshal.writeThreadId(tid); 176 } 177 marshal.writeValue(resultType, result); 178 if (argTypes != null) { 179 for (int i = 0; i < argTypes.length; ++i) { 180 if (argTypes[i] != null) { 181 marshal.writeValue( 182 (TypeDescription) argTypes[i].getComponentType(), 183 Array.get(args[i], 0)); 184 } 185 } 186 } 187 writeBlock(true); 188 } 189 } 190 191 private void sendRequestChange() throws IOException { 192 if (propertiesTid == null) { 193 propertiesTid = ThreadId.createFresh(); 194 } 195 random = new Random().nextInt(); 196 writeRequest( 197 true, PROPERTIES_OID, 198 TypeDescription.getTypeDescription(XProtocolProperties.class), 199 PROPERTIES_FUN_REQUEST_CHANGE, propertiesTid, 200 new Object[] { new Integer(random) }); 201 state = STATE_REQUESTED; 202 } 203 204 private void handleInternalMessage(Message message) throws IOException { 205 if (message.isRequest()) { 206 String t = message.getType().getTypeName(); 207 if (!t.equals("com.sun.star.bridge.XProtocolProperties")) { 208 throw new IOException( 209 "read URP protocol properties request with unsupported" 210 + " type " + t); 211 } 212 int fid = message.getMethod().getIndex(); 213 switch (fid) { 214 case PROPERTIES_FID_REQUEST_CHANGE: 215 checkSynchronousPropertyRequest(message); 216 synchronized (monitor) { 217 switch (state) { 218 case STATE_INITIAL0: 219 case STATE_INITIAL: 220 writeReply( 221 false, message.getThreadId(), new Integer(1)); 222 state = STATE_WAIT; 223 break; 224 case STATE_REQUESTED: 225 int n 226 = ((Integer) message.getArguments()[0]).intValue(); 227 if (random < n) { 228 writeReply( 229 false, message.getThreadId(), new Integer(1)); 230 state = STATE_WAIT; 231 } else if (random == n) { 232 writeReply( 233 false, message.getThreadId(), new Integer(-1)); 234 state = STATE_INITIAL; 235 sendRequestChange(); 236 } else { 237 writeReply( 238 false, message.getThreadId(), new Integer(0)); 239 } 240 break; 241 default: 242 writeReply( 243 true, message.getThreadId(), 244 new com.sun.star.uno.RuntimeException( 245 "read URP protocol properties requestChange" 246 + " request in illegal state")); 247 break; 248 } 249 } 250 break; 251 case PROPERTIES_FID_COMMIT_CHANGE: 252 checkSynchronousPropertyRequest(message); 253 synchronized (monitor) { 254 if (state == STATE_WAIT) { 255 ProtocolProperty[] p = (ProtocolProperty[]) 256 message.getArguments()[0]; 257 boolean ok = true; 258 boolean cc = false; 259 int i = 0; 260 for (; i < p.length; ++i) { 261 if (p[i].Name.equals(PROPERTY_CURRENT_CONTEXT)) { 262 cc = true; 263 } else { 264 ok = false; 265 break; 266 } 267 } 268 if (ok) { 269 writeReply(false, message.getThreadId(), null); 270 } else { 271 writeReply( 272 true, message.getThreadId(), 273 new InvalidProtocolChangeException( 274 "", null, p[i], 1)); 275 } 276 state = STATE_INITIAL; 277 if (!initialized) { 278 if (cc) { 279 currentContext = true; 280 initialized = true; 281 monitor.notifyAll(); 282 } else { 283 sendRequestChange(); 284 } 285 } 286 } else { 287 writeReply( 288 true, message.getThreadId(), 289 new com.sun.star.uno.RuntimeException( 290 "read URP protocol properties commitChange" 291 + " request in illegal state")); 292 } 293 } 294 break; 295 default: 296 throw new IOException( 297 "read URP protocol properties request with unsupported" 298 + " function ID " + fid); 299 } 300 } else { 301 synchronized (monitor) { 302 if (state == STATE_COMMITTED) { 303 // commitChange reply: 304 if (!message.isAbnormalTermination()) { 305 currentContext = true; 306 } 307 state = STATE_INITIAL; 308 initialized = true; 309 monitor.notifyAll(); 310 } else { 311 // requestChange reply: 312 if (message.isAbnormalTermination()) { 313 // remote side probably does not support negotiation: 314 state = STATE_INITIAL; 315 initialized = true; 316 monitor.notifyAll(); 317 } else { 318 int n = ((Integer) message.getResult()).intValue(); 319 switch (n) { 320 case -1: 321 case 0: 322 break; 323 case 1: 324 writeRequest( 325 true, PROPERTIES_OID, 326 TypeDescription.getTypeDescription( 327 XProtocolProperties.class), 328 PROPERTIES_FUN_COMMIT_CHANGE, propertiesTid, 329 new Object[] { 330 new ProtocolProperty[] { 331 new ProtocolProperty( 332 PROPERTY_CURRENT_CONTEXT, 333 Any.VOID) } }); 334 state = STATE_COMMITTED; 335 break; 336 default: 337 throw new IOException( 338 "read URP protocol properties " 339 + PROPERTIES_FUN_REQUEST_CHANGE 340 + " reply with illegal return value " + n); 341 } 342 } 343 } 344 } 345 } 346 } 347 348 private void checkSynchronousPropertyRequest(Message message) 349 throws IOException 350 { 351 if (!message.isSynchronous()) { 352 throw new IOException( 353 "read URP protocol properties request for synchronous function" 354 + " marked as not SYNCHRONOUS"); 355 } 356 } 357 358 private byte[] readBlock() throws IOException { 359 int size = input.readInt(); 360 input.readInt(); // ignore count 361 byte[] bytes = new byte[size]; 362 input.readFully(bytes); 363 return bytes; 364 } 365 366 private UrpMessage readLongRequest(int header) throws IOException { 367 boolean sync = false; 368 if ((header & HEADER_MOREFLAGS) != 0) { 369 if (unmarshal.read8Bit() != (HEADER_MUSTREPLY | HEADER_SYNCHRONOUS)) 370 { 371 throw new IOException( 372 "read URP request with bad MUSTREPLY/SYNCHRONOUS byte"); 373 } 374 sync = true; 375 } 376 int funId = (header & HEADER_FUNCTIONID16) != 0 377 ? unmarshal.read16Bit() : unmarshal.read8Bit(); 378 if ((header & HEADER_NEWTYPE) != 0) { 379 inL1Type = unmarshal.readType(); 380 if (inL1Type.getTypeClass() != TypeClass.INTERFACE) { 381 throw new IOException( 382 "read URP request with non-interface type " + inL1Type); 383 } 384 } 385 if ((header & HEADER_NEWOID) != 0) { 386 inL1Oid = unmarshal.readObjectId(); 387 } 388 if ((header & HEADER_NEWTID) != 0) { 389 inL1Tid = unmarshal.readThreadId(); 390 } 391 return readRequest(funId, sync); 392 } 393 394 private UrpMessage readShortRequest(int header) { 395 int funId = (header & HEADER_FUNCTIONID14) != 0 396 ? ((header & HEADER_FUNCTIONID) << 8) | unmarshal.read8Bit() 397 : header & HEADER_FUNCTIONID; 398 return readRequest(funId, false); 399 } 400 401 private UrpMessage readRequest(int functionId, boolean forcedSynchronous) { 402 boolean internal = PROPERTIES_OID.equals(inL1Oid); 403 // inL1Oid may be null in XInstanceProvider.getInstance("") 404 XCurrentContext cc = 405 (currentContext && !internal 406 && functionId != MethodDescription.ID_RELEASE) 407 ? (XCurrentContext) unmarshal.readInterface( 408 new Type(XCurrentContext.class)) 409 : null; 410 IMethodDescription desc = inL1Type.getMethodDescription(functionId); 411 ITypeDescription[] inSig = desc.getInSignature(); 412 ITypeDescription[] outSig = desc.getOutSignature(); 413 Object[] args = new Object[inSig.length]; 414 for (int i = 0; i < args.length; ++i) { 415 if (inSig[i] != null) { 416 if (outSig[i] != null) { 417 Object inout = Array.newInstance( 418 outSig[i].getComponentType().getZClass(), 1); 419 Array.set( 420 inout, 0, 421 unmarshal.readValue( 422 (TypeDescription) outSig[i].getComponentType())); 423 args[i] = inout; 424 } else { 425 args[i] = unmarshal.readValue((TypeDescription) inSig[i]); 426 } 427 } else { 428 args[i] = Array.newInstance( 429 outSig[i].getComponentType().getZClass(), 1); 430 } 431 } 432 boolean sync = forcedSynchronous || !desc.isOneway(); 433 if (sync) { 434 pendingIn.push( 435 inL1Tid, new PendingRequests.Item(internal, desc, args)); 436 } 437 return new UrpMessage( 438 inL1Tid, true, inL1Oid, inL1Type, desc, sync, cc, false, null, args, 439 internal); 440 } 441 442 private UrpMessage readReply(int header) { 443 if ((header & HEADER_NEWTID) != 0) { 444 inL1Tid = unmarshal.readThreadId(); 445 } 446 PendingRequests.Item pending = pendingOut.pop(inL1Tid); 447 TypeDescription resultType; 448 ITypeDescription[] argTypes; 449 Object[] args; 450 boolean exception = (header & HEADER_EXCEPTION) != 0; 451 if (exception) { 452 resultType = TypeDescription.getTypeDescription(TypeClass.ANY); 453 argTypes = null; 454 args = null; 455 } else { 456 resultType = (TypeDescription) 457 pending.function.getReturnSignature(); 458 argTypes = pending.function.getOutSignature(); 459 args = pending.arguments; 460 } 461 Object result = resultType == null 462 ? null : unmarshal.readValue(resultType); 463 if (argTypes != null) { 464 for (int i = 0; i < argTypes.length; ++i) { 465 if (argTypes[i] != null) { 466 Array.set( 467 args[i], 0, 468 unmarshal.readValue( 469 (TypeDescription) argTypes[i].getComponentType())); 470 } 471 } 472 } 473 return new UrpMessage( 474 inL1Tid, false, null, null, null, false, null, exception, result, 475 args, pending.internal); 476 } 477 478 private boolean writeRequest( 479 boolean internal, String oid, TypeDescription type, String function, 480 ThreadId tid, Object[] arguments) 481 throws IOException 482 { 483 IMethodDescription desc = type.getMethodDescription(function); 484 synchronized (output) { 485 if (desc.getIndex() == MethodDescription.ID_RELEASE 486 && releaseQueue.size() < MAX_RELEASE_QUEUE_SIZE) 487 { 488 releaseQueue.add( 489 new QueuedRelease(internal, oid, type, desc, tid)); 490 return false; 491 } else { 492 writeQueuedReleases(); 493 return writeRequest( 494 internal, oid, type, desc, tid, arguments, true); 495 } 496 } 497 } 498 499 private boolean writeRequest( 500 boolean internal, String oid, TypeDescription type, 501 IMethodDescription desc, ThreadId tid, Object[] arguments, 502 boolean flush) 503 throws IOException 504 { 505 int funId = desc.getIndex(); 506 if (funId < 0 || funId > MAX_FUNCTIONID16) { 507 throw new IllegalArgumentException( 508 "function ID " + funId + " out of range"); 509 } 510 boolean forceSync = forceSynchronous 511 && funId != MethodDescription.ID_RELEASE; 512 boolean moreFlags = forceSync && desc.isOneway(); 513 boolean longHeader = moreFlags; 514 int header = 0; 515 if (!type.equals(outL1Type)) { 516 longHeader = true; 517 header |= HEADER_NEWTYPE; 518 outL1Type = type; 519 } else { 520 type = null; 521 } 522 if (!oid.equals(outL1Oid)) { 523 longHeader = true; 524 header |= HEADER_NEWOID; 525 outL1Oid = oid; 526 } else { 527 oid = null; 528 } 529 if (!tid.equals(outL1Tid)) { 530 longHeader = true; 531 header |= HEADER_NEWTID; 532 outL1Tid = tid; 533 } else { 534 tid = null; 535 } 536 if (funId > MAX_FUNCTIONID14) { 537 longHeader = true; 538 } 539 if (longHeader) { 540 header |= HEADER_LONGHEADER | HEADER_REQUEST; 541 if (funId > MAX_FUNCTIONID8) { 542 header |= HEADER_FUNCTIONID16; 543 } 544 if (moreFlags) { 545 header |= HEADER_MOREFLAGS; 546 } 547 marshal.write8Bit(header); 548 if (moreFlags) { 549 marshal.write8Bit(HEADER_MUSTREPLY | HEADER_SYNCHRONOUS); 550 } 551 if (funId > MAX_FUNCTIONID8) { 552 marshal.write16Bit(funId); 553 } else { 554 marshal.write8Bit(funId); 555 } 556 if (type != null) { 557 marshal.writeType(type); 558 } 559 if (oid != null) { 560 marshal.writeObjectId(oid); 561 } 562 if (tid != null) { 563 marshal.writeThreadId(tid); 564 } 565 } else { 566 if (funId > HEADER_FUNCTIONID) { 567 marshal.write8Bit(HEADER_FUNCTIONID14 | (funId >> 8)); 568 } 569 marshal.write8Bit(funId); 570 } 571 if (currentContext && !internal 572 && funId != MethodDescription.ID_RELEASE) 573 { 574 marshal.writeInterface( 575 UnoRuntime.getCurrentContext(), 576 new Type(XCurrentContext.class)); 577 } 578 ITypeDescription[] inSig = desc.getInSignature(); 579 ITypeDescription[] outSig = desc.getOutSignature(); 580 for (int i = 0; i < inSig.length; ++i) { 581 if (inSig[i] != null) { 582 if (outSig[i] != null) { 583 marshal.writeValue( 584 (TypeDescription) outSig[i].getComponentType(), 585 ((Object[]) arguments[i])[0]); 586 } else { 587 marshal.writeValue( 588 (TypeDescription) inSig[i], arguments[i]); 589 } 590 } 591 } 592 boolean sync = forceSync || !desc.isOneway(); 593 if (sync) { 594 pendingOut.push( 595 outL1Tid, new PendingRequests.Item(internal, desc, arguments)); 596 } 597 writeBlock(flush); 598 return sync; 599 } 600 601 private void writeBlock(boolean flush) throws IOException { 602 byte[] data = marshal.reset(); 603 output.writeInt(data.length); 604 output.writeInt(1); 605 output.write(data); 606 if (flush) { 607 output.flush(); 608 } 609 } 610 611 private void writeQueuedReleases() throws IOException { 612 for (int i = releaseQueue.size(); i > 0;) { 613 --i; 614 QueuedRelease r = (QueuedRelease) releaseQueue.get(i); 615 writeRequest( 616 r.internal, r.objectId, r.type, r.method, r.threadId, null, 617 false); 618 releaseQueue.remove(i); 619 } 620 } 621 622 private static boolean parseAttributes(String attributes) { 623 boolean forceSynchronous = true; 624 if (attributes != null) { 625 StringTokenizer t = new StringTokenizer(attributes, ","); 626 while (t.hasMoreTokens()) { 627 String a = t.nextToken(); 628 String v = null; 629 int i = a.indexOf('='); 630 if (i >= 0) { 631 v = a.substring(i + 1); 632 a = a.substring(0, i); 633 } 634 if (a.equalsIgnoreCase("ForceSynchronous")) { 635 forceSynchronous = parseBooleanAttributeValue(a, v); 636 } else if (a.equalsIgnoreCase("negotiate")) { 637 // Ignored: 638 parseBooleanAttributeValue(a, v); 639 } else { 640 throw new IllegalArgumentException( 641 "unknown protocol attribute " + a); 642 } 643 } 644 } 645 return forceSynchronous; 646 } 647 648 private static boolean parseBooleanAttributeValue( 649 String attribute, String value) 650 { 651 if (value == null) { 652 throw new IllegalArgumentException( 653 "missing value for protocol attribute " + attribute); 654 } 655 if (value.equals("0")) { 656 return false; 657 } else if (value.equals("1")) { 658 return true; 659 } else { 660 throw new IllegalArgumentException( 661 "bad value " + value + " for protocol attribute " + attribute); 662 } 663 } 664 665 private static final class QueuedRelease { 666 public QueuedRelease( 667 boolean internal, String objectId, TypeDescription type, 668 IMethodDescription method, ThreadId threadId) 669 { 670 this.internal = internal; 671 this.objectId = objectId; 672 this.type = type; 673 this.method = method; 674 this.threadId = threadId; 675 } 676 677 public final boolean internal; 678 public final String objectId; 679 public final TypeDescription type; 680 public final IMethodDescription method; 681 public final ThreadId threadId; 682 } 683 684 private static final String PROPERTIES_OID = "UrpProtocolProperties"; 685 private static final int PROPERTIES_FID_REQUEST_CHANGE = 4; 686 private static final String PROPERTIES_FUN_REQUEST_CHANGE = "requestChange"; 687 private static final int PROPERTIES_FID_COMMIT_CHANGE = 5; 688 private static final String PROPERTIES_FUN_COMMIT_CHANGE = "commitChange"; 689 private static final String PROPERTY_CURRENT_CONTEXT = "CurrentContext"; 690 691 private static final short CACHE_SIZE = 256; 692 693 private static final int HEADER_LONGHEADER = 0x80; 694 private static final int HEADER_REQUEST = 0x40; 695 private static final int HEADER_NEWTYPE = 0x20; 696 private static final int HEADER_NEWOID = 0x10; 697 private static final int HEADER_NEWTID = 0x08; 698 private static final int HEADER_FUNCTIONID16 = 0x04; 699 private static final int HEADER_MOREFLAGS = 0x01; 700 private static final int HEADER_MUSTREPLY = 0x80; 701 private static final int HEADER_SYNCHRONOUS = 0x40; 702 private static final int HEADER_FUNCTIONID14 = 0x40; 703 private static final int HEADER_FUNCTIONID = 0x3F; 704 private static final int HEADER_EXCEPTION = 0x20; 705 706 private static final int MAX_FUNCTIONID16 = 0xFFFF; 707 private static final int MAX_FUNCTIONID14 = 0x3FFF; 708 private static final int MAX_FUNCTIONID8 = 0xFF; 709 710 private static final int STATE_INITIAL0 = 0; 711 private static final int STATE_INITIAL = 1; 712 private static final int STATE_REQUESTED = 2; 713 private static final int STATE_COMMITTED = 3; 714 private static final int STATE_WAIT = 4; 715 private static final int STATE_TERMINATED = 5; 716 717 private static final int MAX_RELEASE_QUEUE_SIZE = 100; 718 719 private final DataInput input; 720 private final DataOutputStream output; 721 722 private final Marshal marshal; 723 private final Unmarshal unmarshal; 724 725 private final boolean forceSynchronous; 726 727 private final PendingRequests pendingIn = new PendingRequests(); 728 private final PendingRequests pendingOut = new PendingRequests(); 729 730 private final Object monitor = new Object(); 731 private int state = STATE_INITIAL0; 732 private boolean initialized = false; 733 private ThreadId propertiesTid = null; 734 private int random; 735 private boolean currentContext = false; 736 737 private ThreadId inL1Tid = null; 738 private String inL1Oid = null; 739 private TypeDescription inL1Type = null; 740 741 private ThreadId outL1Tid = null; 742 private String outL1Oid = null; 743 private ITypeDescription outL1Type = null; 744 745 private final ArrayList releaseQueue = new ArrayList(); // of QueuedRelease 746 } 747