예제 #1
0
 private UrpMessage readReply(int header) {
   if ((header & HEADER_NEWTID) != 0) {
     inL1Tid = unmarshal.readThreadId();
   }
   PendingRequests.Item pending = pendingOut.pop(inL1Tid);
   TypeDescription resultType;
   ITypeDescription[] argTypes;
   Object[] args;
   boolean exception = (header & HEADER_EXCEPTION) != 0;
   if (exception) {
     resultType = TypeDescription.getTypeDescription(TypeClass.ANY);
     argTypes = null;
     args = null;
   } else {
     resultType = (TypeDescription) pending.function.getReturnSignature();
     argTypes = pending.function.getOutSignature();
     args = pending.arguments;
   }
   Object result = resultType == null ? null : unmarshal.readValue(resultType);
   if (argTypes != null) {
     for (int i = 0; i < argTypes.length; ++i) {
       if (argTypes[i] != null) {
         Array.set(
             args[i], 0, unmarshal.readValue((TypeDescription) argTypes[i].getComponentType()));
       }
     }
   }
   return new UrpMessage(
       inL1Tid, false, null, null, null, false, null, exception, result, args, pending.internal);
 }
예제 #2
0
 private void sendRequestChange() throws IOException {
   if (propertiesTid == null) {
     propertiesTid = ThreadId.createFresh();
   }
   random = new Random().nextInt();
   writeRequest(
       true,
       PROPERTIES_OID,
       TypeDescription.getTypeDescription(XProtocolProperties.class),
       PROPERTIES_FUN_REQUEST_CHANGE,
       propertiesTid,
       new Object[] {new Integer(random)});
   state = STATE_REQUESTED;
 }
예제 #3
0
  public Object sendRequest(String oid, Type type, String operation, Object[] params)
      throws Throwable {
    Object result = null;

    checkDisposed();

    ThreadId threadId = _iThreadPool.getThreadId();
    Object handle = _iThreadPool.attach(threadId);
    try {
      boolean sync;
      try {
        sync =
            _iProtocol.writeRequest(
                oid, TypeDescription.getTypeDescription(type), operation, threadId, params);
      } catch (IOException e) {
        dispose(e);
        throw (DisposedException) new DisposedException(e.toString()).initCause(e);
      }
      if (sync && Thread.currentThread() != _messageDispatcher) {
        result = _iThreadPool.enter(handle, threadId);
      }
    } finally {
      _iThreadPool.detach(handle, threadId);
      if (operation.equals("release")) release(); // kill this bridge, if this was the last proxy
    }

    if (DEBUG) System.err.println("##### " + getClass().getName() + ".sendRequest left:" + result);

    // On the wire (at least in URP), the result of queryInterface is
    // transported as an ANY, but in Java it shall be transported as a
    // direct reference to the UNO object (represented as a Java Object),
    // never boxed in a com.sun.star.uno.Any:
    if (operation.equals("queryInterface") && result instanceof Any) {
      Any a = (Any) result;
      if (a.getType().getTypeClass() == TypeClass.INTERFACE) {
        result = a.getObject();
      } else {
        result = null; // should never happen
      }
    }

    return result;
  }
예제 #4
0
 private boolean writeRequest(
     boolean internal,
     String oid,
     TypeDescription type,
     String function,
     ThreadId tid,
     Object[] arguments)
     throws IOException {
   IMethodDescription desc = type.getMethodDescription(function);
   synchronized (output) {
     if (desc.getIndex() == MethodDescription.ID_RELEASE
         && releaseQueue.size() < MAX_RELEASE_QUEUE_SIZE) {
       releaseQueue.add(new QueuedRelease(internal, oid, type, desc, tid));
       return false;
     } else {
       writeQueuedReleases();
       return writeRequest(internal, oid, type, desc, tid, arguments, true);
     }
   }
 }
예제 #5
0
 // @see IProtocol#writeReply
 public void writeReply(boolean exception, ThreadId tid, Object result) throws IOException {
   synchronized (output) {
     writeQueuedReleases();
     int header = HEADER_LONGHEADER;
     PendingRequests.Item pending = pendingIn.pop(tid);
     TypeDescription resultType;
     ITypeDescription[] argTypes;
     Object[] args;
     if (exception) {
       header |= HEADER_EXCEPTION;
       resultType = TypeDescription.getTypeDescription(TypeClass.ANY);
       argTypes = null;
       args = null;
     } else {
       resultType = (TypeDescription) pending.function.getReturnSignature();
       argTypes = pending.function.getOutSignature();
       args = pending.arguments;
     }
     if (!tid.equals(outL1Tid)) {
       header |= HEADER_NEWTID;
       outL1Tid = tid;
     } else {
       tid = null;
     }
     marshal.write8Bit(header);
     if (tid != null) {
       marshal.writeThreadId(tid);
     }
     marshal.writeValue(resultType, result);
     if (argTypes != null) {
       for (int i = 0; i < argTypes.length; ++i) {
         if (argTypes[i] != null) {
           marshal.writeValue(
               (TypeDescription) argTypes[i].getComponentType(), Array.get(args[i], 0));
         }
       }
     }
     writeBlock(true);
   }
 }
예제 #6
0
 private boolean writeRequest(
     boolean internal,
     String oid,
     TypeDescription type,
     IMethodDescription desc,
     ThreadId tid,
     Object[] arguments,
     boolean flush)
     throws IOException {
   int funId = desc.getIndex();
   if (funId < 0 || funId > MAX_FUNCTIONID16) {
     throw new IllegalArgumentException("function ID " + funId + " out of range");
   }
   boolean forceSync = forceSynchronous && funId != MethodDescription.ID_RELEASE;
   boolean moreFlags = forceSync && desc.isOneway();
   boolean longHeader = moreFlags;
   int header = 0;
   if (!type.equals(outL1Type)) {
     longHeader = true;
     header |= HEADER_NEWTYPE;
     outL1Type = type;
   } else {
     type = null;
   }
   if (!oid.equals(outL1Oid)) {
     longHeader = true;
     header |= HEADER_NEWOID;
     outL1Oid = oid;
   } else {
     oid = null;
   }
   if (!tid.equals(outL1Tid)) {
     longHeader = true;
     header |= HEADER_NEWTID;
     outL1Tid = tid;
   } else {
     tid = null;
   }
   if (funId > MAX_FUNCTIONID14) {
     longHeader = true;
   }
   if (longHeader) {
     header |= HEADER_LONGHEADER | HEADER_REQUEST;
     if (funId > MAX_FUNCTIONID8) {
       header |= HEADER_FUNCTIONID16;
     }
     if (moreFlags) {
       header |= HEADER_MOREFLAGS;
     }
     marshal.write8Bit(header);
     if (moreFlags) {
       marshal.write8Bit(HEADER_MUSTREPLY | HEADER_SYNCHRONOUS);
     }
     if (funId > MAX_FUNCTIONID8) {
       marshal.write16Bit(funId);
     } else {
       marshal.write8Bit(funId);
     }
     if (type != null) {
       marshal.writeType(type);
     }
     if (oid != null) {
       marshal.writeObjectId(oid);
     }
     if (tid != null) {
       marshal.writeThreadId(tid);
     }
   } else {
     if (funId > HEADER_FUNCTIONID) {
       marshal.write8Bit(HEADER_FUNCTIONID14 | (funId >> 8));
     }
     marshal.write8Bit(funId);
   }
   if (currentContext && !internal && funId != MethodDescription.ID_RELEASE) {
     marshal.writeInterface(UnoRuntime.getCurrentContext(), new Type(XCurrentContext.class));
   }
   ITypeDescription[] inSig = desc.getInSignature();
   ITypeDescription[] outSig = desc.getOutSignature();
   for (int i = 0; i < inSig.length; ++i) {
     if (inSig[i] != null) {
       if (outSig[i] != null) {
         marshal.writeValue(
             (TypeDescription) outSig[i].getComponentType(), ((Object[]) arguments[i])[0]);
       } else {
         marshal.writeValue((TypeDescription) inSig[i], arguments[i]);
       }
     }
   }
   boolean sync = forceSync || !desc.isOneway();
   if (sync) {
     pendingOut.push(outL1Tid, new PendingRequests.Item(internal, desc, arguments));
   }
   writeBlock(flush);
   return sync;
 }
예제 #7
0
 private void handleInternalMessage(Message message) throws IOException {
   if (message.isRequest()) {
     String t = message.getType().getTypeName();
     if (!t.equals("com.sun.star.bridge.XProtocolProperties")) {
       throw new IOException(
           "read URP protocol properties request with unsupported" + " type " + t);
     }
     int fid = message.getMethod().getIndex();
     switch (fid) {
       case PROPERTIES_FID_REQUEST_CHANGE:
         checkSynchronousPropertyRequest(message);
         synchronized (monitor) {
           switch (state) {
             case STATE_INITIAL0:
             case STATE_INITIAL:
               writeReply(false, message.getThreadId(), new Integer(1));
               state = STATE_WAIT;
               break;
             case STATE_REQUESTED:
               int n = ((Integer) message.getArguments()[0]).intValue();
               if (random < n) {
                 writeReply(false, message.getThreadId(), new Integer(1));
                 state = STATE_WAIT;
               } else if (random == n) {
                 writeReply(false, message.getThreadId(), new Integer(-1));
                 state = STATE_INITIAL;
                 sendRequestChange();
               } else {
                 writeReply(false, message.getThreadId(), new Integer(0));
               }
               break;
             default:
               writeReply(
                   true,
                   message.getThreadId(),
                   new com.sun.star.uno.RuntimeException(
                       "read URP protocol properties requestChange"
                           + " request in illegal state"));
               break;
           }
         }
         break;
       case PROPERTIES_FID_COMMIT_CHANGE:
         checkSynchronousPropertyRequest(message);
         synchronized (monitor) {
           if (state == STATE_WAIT) {
             ProtocolProperty[] p = (ProtocolProperty[]) message.getArguments()[0];
             boolean ok = true;
             boolean cc = false;
             int i = 0;
             for (; i < p.length; ++i) {
               if (p[i].Name.equals(PROPERTY_CURRENT_CONTEXT)) {
                 cc = true;
               } else {
                 ok = false;
                 break;
               }
             }
             if (ok) {
               writeReply(false, message.getThreadId(), null);
             } else {
               writeReply(
                   true,
                   message.getThreadId(),
                   new InvalidProtocolChangeException("", null, p[i], 1));
             }
             state = STATE_INITIAL;
             if (!initialized) {
               if (cc) {
                 currentContext = true;
                 initialized = true;
                 monitor.notifyAll();
               } else {
                 sendRequestChange();
               }
             }
           } else {
             writeReply(
                 true,
                 message.getThreadId(),
                 new com.sun.star.uno.RuntimeException(
                     "read URP protocol properties commitChange" + " request in illegal state"));
           }
         }
         break;
       default:
         throw new IOException(
             "read URP protocol properties request with unsupported" + " function ID " + fid);
     }
   } else {
     synchronized (monitor) {
       if (state == STATE_COMMITTED) {
         // commitChange reply:
         if (!message.isAbnormalTermination()) {
           currentContext = true;
         }
         state = STATE_INITIAL;
         initialized = true;
         monitor.notifyAll();
       } else {
         // requestChange reply:
         if (message.isAbnormalTermination()) {
           // remote side probably does not support negotiation:
           state = STATE_INITIAL;
           initialized = true;
           monitor.notifyAll();
         } else {
           int n = ((Integer) message.getResult()).intValue();
           switch (n) {
             case -1:
             case 0:
               break;
             case 1:
               writeRequest(
                   true,
                   PROPERTIES_OID,
                   TypeDescription.getTypeDescription(XProtocolProperties.class),
                   PROPERTIES_FUN_COMMIT_CHANGE,
                   propertiesTid,
                   new Object[] {
                     new ProtocolProperty[] {
                       new ProtocolProperty(PROPERTY_CURRENT_CONTEXT, Any.VOID)
                     }
                   });
               state = STATE_COMMITTED;
               break;
             default:
               throw new IOException(
                   "read URP protocol properties "
                       + PROPERTIES_FUN_REQUEST_CHANGE
                       + " reply with illegal return value "
                       + n);
           }
         }
       }
     }
   }
 }
public final class JobQueue_Test {
  @Test
  public void testThreadLeavesJobQueueOnDispose0() throws InterruptedException {
    testThreadLeavesJobQueueOnDispose(0);
  }

  @Test
  public void testThreadLeavesJobQueueOnDispose5000() throws InterruptedException {
    testThreadLeavesJobQueueOnDispose(5000);
  }

  private void testThreadLeavesJobQueueOnDispose(int waitTime) throws InterruptedException {
    TestThread t = new TestThread(waitTime);
    t.waitToStart();
    String msg = "xcxxxxxxxx";
    t._jobQueue.dispose(t._disposeId, new RuntimeException(msg));
    t.waitToTerminate();
    /*TODO: below test fails with "expected:<xcxxxxxxxx> but was:<null>":
            assertEquals(msg, t._message);
    */
  }

  @Test
  public void testThreadLeavesJobQueueOnReply0() throws InterruptedException {
    testThreadLeavesJobQueueOnReply(0);
  }

  @Test
  public void testThreadLeavesJobQueueOnReply5000() throws InterruptedException {
    testThreadLeavesJobQueueOnReply(5000);
  }

  private void testThreadLeavesJobQueueOnReply(int waitTime) throws InterruptedException {
    TestThread t = new TestThread(waitTime);
    t.waitToStart();
    // put reply job:
    t._jobQueue.putJob(
        new Job(
            null,
            __iReceiver,
            new Message(null, false, "oid", __workAt_td, null, false, null, false, null, null)),
        null);
    t.waitToTerminate();
    assertTrue(true); // TODO! ???
  }

  @Test
  public void testStaticThreadExecutesJobs0() throws InterruptedException {
    testStaticThreadExecutesJobs(0);
  }

  @Test
  public void testStaticThreadExecutesJobs5000() throws InterruptedException {
    testStaticThreadExecutesJobs(5000);
  }

  private void testStaticThreadExecutesJobs(int waitTime) throws InterruptedException {
    TestThread t = new TestThread(waitTime);
    t.waitToStart();
    testExecuteJobs(t._jobQueue);
    t._jobQueue.dispose(t._disposeId, new RuntimeException("xxxxxxxxxxxxx"));
    t.waitToTerminate();
  }

  @Test
  public void testDynamicThreadExecutesJob() throws InterruptedException {
    testExecuteJobs(new JobQueue(__javaThreadPoolFactory, ThreadId.createFresh(), true));
  }

  @Test
  public void testStaticThreadExecutesAsyncs() throws InterruptedException {
    TestThread t = new TestThread();
    JobQueue async_jobQueue = new JobQueue(__javaThreadPoolFactory, t._threadId);
    assertEquals(1, async_jobQueue._ref_count);
    t._jobQueue = __javaThreadPoolFactory.getJobQueue(t._threadId);
    assertEquals(1, t._jobQueue._ref_count);
    t.waitToStart();
    TestWorkAt workAt = new TestWorkAt();
    testAsyncJobQueue(workAt, async_jobQueue, t._threadId);
    t._jobQueue.dispose(t._disposeId, new RuntimeException("xxxxxxxxxxxxx"));
    t.waitToTerminate();
    assertEquals(TestWorkAt.MESSAGES, workAt._async_counter);
    assertEquals(TestWorkAt.MESSAGES, workAt._sync_counter);
  }

  @Test
  public void testDynamicThreadExecutesAsyncs() throws InterruptedException {
    ThreadId threadId = ThreadId.createFresh();
    JobQueue async_jobQueue = new JobQueue(__javaThreadPoolFactory, threadId);
    TestWorkAt workAt = new TestWorkAt();
    testAsyncJobQueue(workAt, async_jobQueue, threadId);
    assertEquals(TestWorkAt.MESSAGES, workAt._async_counter);
    assertEquals(TestWorkAt.MESSAGES, workAt._sync_counter);
  }

  private void testExecuteJobs(JobQueue jobQueue) throws InterruptedException {
    TestWorkAt workAt = new TestWorkAt();
    testSendRequests(workAt, "increment", jobQueue);
    synchronized (workAt) {
      jobQueue.putJob(
          new Job(
              workAt,
              __iReceiver,
              new Message(
                  null,
                  true,
                  "oid",
                  __workAt_td,
                  __workAt_td.getMethodDescription("notifyme"),
                  true,
                  null,
                  false,
                  null,
                  null)),
          null);
      while (!workAt._notified) {
        workAt.wait();
      }
    }
    assertEquals(TestWorkAt.MESSAGES, workAt._counter);
  }

  private void testAsyncJobQueue(TestWorkAt workAt, JobQueue async_jobQueue, ThreadId threadId)
      throws InterruptedException {
    // put slow async calls first, followed by fast sync calls:
    testSendRequests(workAt, "asyncCall", async_jobQueue);
    testSendRequests(workAt, "syncCall", __javaThreadPoolFactory.getJobQueue(threadId));
    synchronized (workAt) {
      async_jobQueue._sync_jobQueue.putJob(
          new Job(
              workAt,
              __iReceiver,
              new Message(
                  null,
                  true,
                  "oid",
                  __workAt_td,
                  __workAt_td.getMethodDescription("notifyme"),
                  true,
                  null,
                  false,
                  null,
                  null)),
          null);
      while (!workAt._notified) {
        workAt.wait();
      }
    }
    assertTrue(workAt.passedAsyncTest());
  }

  private void testSendRequests(TestWorkAt workAt, String operation, JobQueue jobQueue) {
    Message iMessage =
        new Message(
            null,
            true,
            "oid",
            __workAt_td,
            __workAt_td.getMethodDescription(operation),
            true,
            null,
            false,
            null,
            null);
    for (int i = 0; i < TestWorkAt.MESSAGES; ++i) {
      Thread.yield(); // force scheduling
      jobQueue.putJob(new Job(workAt, __iReceiver, iMessage), new Object());
    }
  }

  private static final class TestThread extends Thread {
    public final ThreadId _threadId = JavaThreadPoolFactory.getThreadId();
    public final Object _disposeId = new Object();
    public JobQueue _jobQueue = null;

    public TestThread(int waitTime) {
      this.waitTime = waitTime;
      _jobQueue = new JobQueue(__javaThreadPoolFactory, _threadId, false);
    }

    public TestThread() {
      waitTime = 0;
    }

    public void run() {
      synchronized (lock) {
        state = STATE_STARTED;
        lock.notifyAll();
      }
      try {
        if (waitTime != 0) {
          Thread.sleep(waitTime);
        }
        _jobQueue.enter(_disposeId);
      } catch (Throwable e) {
      }
      synchronized (lock) {
        state = STATE_DONE;
        lock.notifyAll();
      }
    }

    public void waitToStart() throws InterruptedException {
      start();
      synchronized (lock) {
        while (state == STATE_INITIAL) {
          lock.wait();
        }
      }
    }

    public void waitToTerminate() throws InterruptedException {
      synchronized (lock) {
        while (state != STATE_DONE) {
          lock.wait();
        }
      }
      join();
    }

    private final int waitTime;

    private final Object lock = new Object();
    private int state = STATE_INITIAL;
    private static final int STATE_INITIAL = 0;
    private static final int STATE_STARTED = 1;
    private static final int STATE_DONE = 2;
  }

  private static final JavaThreadPoolFactory __javaThreadPoolFactory = new JavaThreadPoolFactory();
  private static final IReceiver __iReceiver = new TestReceiver();
  private static final TypeDescription __workAt_td =
      TypeDescription.getTypeDescription(TestIWorkAt.class);
}