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); }
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; }
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; }
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); } } }
// @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); } }
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; }
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); }