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