hammant 2003/02/06 23:39:04 Modified: altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/stream CallbackEnabledClientCustomStreamReadWriter.java altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream StreamInvocationHandler.java altrmi/src/java/org/apache/excalibur/altrmi/common ReplyConstants.java ReqRepBytes.java altrmi/src/test/org/apache/excalibur/altrmi/test/socket CallbackEnabledCustomStreamTestCase.java Added: altrmi/src/java/org/apache/excalibur/altrmi/common ClientInvocationAbendReply.java altrmi/src/test/org/apache/excalibur/altrmi/multiprocess AbstractDyingServerTestCase.java DyingDuplexServerTestCase.java DyingSimplexServerTestCase.java MultiProcessTestCase.java MultiTestServer.java SimpleMainable.java Log: Callback stream now correctly reports abend of connection. Revision Changes Path 1.19 +60 -27 avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/stream/CallbackEnabledClientCustomStreamReadWriter.java Index: CallbackEnabledClientCustomStreamReadWriter.java =================================================================== RCS file: /home/cvs/avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/callback/stream/CallbackEnabledClientCustomStreamReadWriter.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- CallbackEnabledClientCustomStreamReadWriter.java 5 Feb 2003 07:32:07 -0000 1.18 +++ CallbackEnabledClientCustomStreamReadWriter.java 7 Feb 2003 07:39:04 -0000 1.19 @@ -28,12 +28,14 @@ import org.apache.excalibur.altrmi.common.ExceptionReply; import org.apache.excalibur.altrmi.common.InvocationException; import org.apache.excalibur.altrmi.common.ReqRepBytes; +import org.apache.excalibur.altrmi.common.ClientInvocationAbendReply; import org.apache.excalibur.altrmi.server.Server; import org.apache.excalibur.altrmi.server.PublicationException; import org.apache.excalibur.altrmi.server.ServerException; import org.apache.excalibur.altrmi.server.impl.classretrievers.PlainClassRetriever; import org.apache.excalibur.altrmi.server.impl.direct.DirectServer; + /** * Class CallbackEnabledClientCustomStreamReadWriter * This class embedds within itself a Server which holds the @@ -49,6 +51,7 @@ { //Mutex to block the client till a reply reaches back from server private Object m_replyLock = new Object(); + private boolean m_replyLockSyncedOn; private Reply m_reply = null; private ThreadContext m_messageLoopThreadContext = null; private boolean m_isStopped = false; @@ -103,18 +106,24 @@ { ReqRepBytes reqRepBytes = ReqRepBytes.getRequestReplyBytesFromDataStream(m_dataInputStream); - if (reqRepBytes.getIOException() != null) + if (reqRepBytes.getIOException() != null && reqRepBytes.ioeDuringReadInt()) { IOException ioe = reqRepBytes.getIOException(); - if (ioe != null) + if ((ioe instanceof EOFException && reqRepBytes.ioeDuringReadInt()) + || ioe instanceof SocketException) { - if ((ioe instanceof EOFException && reqRepBytes.ioeDuringReadInt()) - || ioe instanceof SocketException) + if (m_replyLockSyncedOn) { - m_isStopped = true; - // restart ? - return; + m_reply = new ClientInvocationAbendReply(ioe); + synchronized (m_replyLock) + { + m_replyLock.notify(); + } } + + m_isStopped = true; + // restart ? + return; } System.out.println("--> ##1 " + reqRepBytes.getIOException()); } @@ -122,44 +131,66 @@ // Is a reply. if (!(reqRepBytes.isRequest())) { - try + if (reqRepBytes.hadIOE()) { - m_reply = (Reply) SerializationHelper.getInstanceFromBytes(reqRepBytes.getBytes(), m_interfacesClassLoader); - ; + m_reply = new ExceptionReply(new InvocationException("IOException", reqRepBytes.getIOException())); } - catch (ClassNotFoundException e) + else { - m_reply = new ExceptionReply(new InvocationException("ClassNotFoundException", e)); + try + { + m_reply = (Reply) SerializationHelper.getInstanceFromBytes(reqRepBytes.getBytes(), m_interfacesClassLoader); + } + catch (ClassNotFoundException e) + { + m_reply = new ExceptionReply(new InvocationException("ClassNotFoundException", e)); + } } synchronized (m_replyLock) { m_replyLock.notify(); } + } // Is a request. else if (reqRepBytes.isRequest()) { - try + Object obj = null; + Reply reply = null; + if (reqRepBytes.hadIOE()) { - Object obj = null; - Reply reply = null; + reply = new ClientInvocationAbendReply(reqRepBytes.getIOException()); try { - obj = SerializationHelper.getInstanceFromBytes(reqRepBytes.getBytes(), m_interfacesClassLoader); - reply = m_clientServerHostingExposedObjects.handleInvocation((Request) obj, "callback"); + postReply(reply); } - catch (ClassNotFoundException e) + catch (IOException e) { - reply = new ExceptionReply(new InvocationException("ClassNotFoundException", e)); + // ? } - postReply(reply); } - catch (IOException ioe) + else { - if (ioe instanceof EOFException) + try + { + try + { + obj = SerializationHelper.getInstanceFromBytes(reqRepBytes.getBytes(), m_interfacesClassLoader); + reply = m_clientServerHostingExposedObjects.handleInvocation((Request) obj, "callback"); + } + catch (ClassNotFoundException e) + { + reply = new ExceptionReply(new InvocationException("ClassNotFoundException", e)); + } + postReply(reply); + } + catch (IOException ioe) { - m_isStopped = true; - return; + if (ioe instanceof EOFException) + { + m_isStopped = true; + return; + } } } } @@ -177,6 +208,7 @@ { synchronized (m_replyLock) { + m_replyLockSyncedOn = true; try { m_replyLock.wait(); @@ -185,6 +217,7 @@ { e.printStackTrace(); } + m_replyLockSyncedOn = false; } } return m_reply; @@ -193,12 +226,12 @@ /* * @see ClientStreamReadWriter#postRequest(Request) */ - public Reply postRequest(Request altrmiRequest) + public Reply postRequest(Request request) throws IOException, ClassNotFoundException { if (m_isStopped) throw new IOException("Server Stoppped"); - writeRequest(altrmiRequest); + writeRequest(request); Reply r = readReply(); m_reply = null; return r; 1.17 +10 -1 avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/StreamInvocationHandler.java Index: StreamInvocationHandler.java =================================================================== RCS file: /home/cvs/avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/client/impl/stream/StreamInvocationHandler.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- StreamInvocationHandler.java 19 Jan 2003 11:10:00 -0000 1.16 +++ StreamInvocationHandler.java 7 Feb 2003 07:39:04 -0000 1.17 @@ -25,6 +25,8 @@ import org.apache.excalibur.altrmi.common.PublishedNameRequest; import org.apache.excalibur.altrmi.common.TryLaterReply; import org.apache.excalibur.altrmi.common.RequestConstants; +import org.apache.excalibur.altrmi.common.ReplyConstants; +import org.apache.excalibur.altrmi.common.ClientInvocationAbendReply; /** * Class StreamInvocationHandler @@ -136,6 +138,13 @@ if( reply.getReplyCode() >= 100 ) { + // special case for callabcks. + if (reply.getReplyCode() == ReplyConstants.CLIENTABEND) + { + ClientInvocationAbendReply abendReply = (ClientInvocationAbendReply) reply; + throw abendReply.getIOException(); + } + if( reply instanceof TryLaterReply ) { int millis = ( (TryLaterReply)reply ).getSuggestedDelayMillis(); 1.2 +7 -5 avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/common/ReplyConstants.java Index: ReplyConstants.java =================================================================== RCS file: /home/cvs/avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/common/ReplyConstants.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ReplyConstants.java 5 Jan 2003 23:24:56 -0000 1.1 +++ ReplyConstants.java 7 Feb 2003 07:39:04 -0000 1.2 @@ -8,12 +8,12 @@ package org.apache.excalibur.altrmi.common; -/** - * Interface ReplyConstants +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. * - * - * @author Paul Hammant <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a> - * @version * $Revision$ + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. */ public interface ReplyConstants { @@ -100,5 +100,7 @@ * The proxy class could not be retrieved. */ int CLASSRETRIEVALFAILEDREPLY = 107; + + int CLIENTABEND = 108; } 1.2 +5 -0 avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/common/ReqRepBytes.java Index: ReqRepBytes.java =================================================================== RCS file: /home/cvs/avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/common/ReqRepBytes.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ReqRepBytes.java 5 Feb 2003 00:10:26 -0000 1.1 +++ ReqRepBytes.java 7 Feb 2003 07:39:04 -0000 1.2 @@ -35,6 +35,11 @@ return (m_ioe != null & m_byteSize == 0); } + public boolean hadIOE() + { + return (m_ioe != null); + } + public int getByteSize() { return m_byteSize; 1.1 avalon-excalibur/altrmi/src/java/org/apache/excalibur/altrmi/common/ClientInvocationAbendReply.java Index: ClientInvocationAbendReply.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.common; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; /** * Class ClientInvocationAbendReply - a special case for Callback transports. * * * @author Paul Hammant * @version $Revision: 1.1 $ */ public final class ClientInvocationAbendReply extends Reply { private IOException m_replyExcpt; /** * Constructor ExceptionReply * * * @param replyExcpt the exception received for the invocation * */ public ClientInvocationAbendReply( IOException replyExcpt ) { this.m_replyExcpt = replyExcpt; } /** * Get reply exception. * * * @return the transported exception * */ public IOException getIOException() { return m_replyExcpt; } /** * Gets number that represents type for this class. * This is quicker than instanceof for type checking. * * @return the representative code * @see ReplyConstants * */ public int getReplyCode() { return ReplyConstants.CLIENTABEND; } /** * The object implements the writeExternal method to save its contents * by calling the methods of DataOutput for its primitive values or * calling the writeObject method of ObjectOutput for objects, strings, * and arrays. * * @serialData Overriding methods should use this tag to describe * the data layout of this Externalizable object. * List the sequence of element types and, if possible, * relate the element to a public/protected field and/or * method of this Externalizable class. * * @param out the stream to write the object to * @exception IOException Includes any I/O exceptions that may occur */ public void writeExternal( ObjectOutput out ) throws IOException { throw new UnsupportedOperationException(); } /** * The object implements the readExternal method to restore its * contents by calling the methods of DataInput for primitive * types and readObject for objects, strings and arrays. The * readExternal method must read the values in the same sequence * and with the same types as were written by writeExternal. * * @param in the stream to read data from in order to restore the object * @exception IOException if I/O errors occur * @exception ClassNotFoundException If the class for an object being * restored cannot be found. */ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException { throw new UnsupportedOperationException(); } } 1.15 +0 -6 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/socket/CallbackEnabledCustomStreamTestCase.java Index: CallbackEnabledCustomStreamTestCase.java =================================================================== RCS file: /home/cvs/avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/test/socket/CallbackEnabledCustomStreamTestCase.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- CallbackEnabledCustomStreamTestCase.java 5 Feb 2003 00:55:23 -0000 1.14 +++ CallbackEnabledCustomStreamTestCase.java 7 Feb 2003 07:39:04 -0000 1.15 @@ -63,7 +63,6 @@ hc.getClientInvocationHandler().setConnectionListener(new ConnectionListener() { public void methodCalled(String methodSignature, long duration, String annotation) { - System.out.println("CallbackEnabledCustomStreamTestCase.methodCalled " + methodSignature); } public boolean methodLogging() @@ -73,27 +72,22 @@ public void serviceSuspended(Request altrmiRequest, int attempt, int suggestedWaitMillis) { - System.out.println("CallbackEnabledCustomStreamTestCase.serviceSuspended"); } public void serviceAbend(int attempt, IOException cause) { - System.out.println("CallbackEnabledCustomStreamTestCase.serviceAbend"); } public void invocationFailure(String name, InvocationException ie) { - System.out.println("CallbackEnabledCustomStreamTestCase.invocationFailure"); } public void unexpectedClosedConnection(String name, ConnectionClosedException cce) { - System.out.println("CallbackEnabledCustomStreamTestCase.unexpectedClosedConnection"); } public void unexpectedInterruption(String name, InterruptedException ie) { - System.out.println("CallbackEnabledCustomStreamTestCase.unexpectedInterruption"); } }); altrmiFactory.setHostContext(hc , false); 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/AbstractDyingServerTestCase.java Index: AbstractDyingServerTestCase.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.multiprocess; import junit.framework.TestCase; import org.apache.excalibur.altrmi.client.impl.ClientSideClassFactory; import org.apache.excalibur.altrmi.client.ConnectionListener; import org.apache.excalibur.altrmi.client.ConnectionClosedException; import org.apache.excalibur.altrmi.client.HostContext; import org.apache.excalibur.altrmi.test.TestInterface; import org.apache.excalibur.altrmi.common.Request; import org.apache.excalibur.altrmi.common.InvocationException; import org.apache.excalibur.altrmi.common.ConnectionException; import java.io.IOException; /** * AbstractDyingServerTestCase * * @author Paul Hammant * @version $Revision: 1.1 $ */ public abstract class AbstractDyingServerTestCase extends TestCase { private Process m_process; protected ClientSideClassFactory altrmiFactory; private TestInterface testClient; private boolean abended; public AbstractDyingServerTestCase(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); String classpath = System.getProperty("java.class.path"); String command = "java -cp " + classpath + " org.apache.excalibur.altrmi.multiprocess.MultiTestServer " + getServerType(); //System.out.println("command = " + command); m_process = Runtime.getRuntime().exec(command); abended = false; Thread.currentThread().sleep(1000); // Client side setup altrmiFactory = new ClientSideClassFactory(); } protected abstract String getServerType(); protected void checkHostContext(HostContext hostContext) throws ConnectionException { altrmiFactory.setHostContext(hostContext, false); hostContext.getClientInvocationHandler().setConnectionListener(new MockConnectionListener()); testClient = (TestInterface) altrmiFactory.lookup("Hello"); testClient.hello2(123); try { testClient.hello("hi"); fail("Server should have ended, we should have got an excpetion on invocation."); } catch (InvocationException ie) { // kewl, maybe server ended abnormally? assertTrue("server should have abended", abended); } } protected void tearDown() throws Exception { try { m_process.destroy(); } catch (Exception e) { } finally { super.tearDown(); } } private class MockConnectionListener implements ConnectionListener { public void methodCalled(String methodSignature, long duration, String annotation) { } public boolean methodLogging() { return false; } public void serviceSuspended(Request altrmiRequest, int attempt, int suggestedWaitMillis) { } public void serviceAbend(int attempt, IOException cause) { abended = true; throw new InvocationException("yee haa!"); } public void invocationFailure(String name, InvocationException ie) { } public void unexpectedClosedConnection(String name, ConnectionClosedException cce) { } public void unexpectedInterruption(String name, InterruptedException ie) { } } } 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/DyingDuplexServerTestCase.java Index: DyingDuplexServerTestCase.java =================================================================== /** * Created by IntelliJ IDEA. * User: Administrator * Date: Feb 6, 2003 * Time: 9:10:48 PM * To change this template use Options | File Templates. */ package org.apache.excalibur.altrmi.multiprocess; import org.apache.excalibur.altrmi.client.impl.callback.socket.CallbackEnabledSocketCustomStreamHostContext; /** * DyingDuplexServerTestCase * * @author Paul Hammant * @version $Revision: 1.1 $ */ public class DyingDuplexServerTestCase extends AbstractDyingServerTestCase { public DyingDuplexServerTestCase(String name) { super(name); } protected String getServerType() { return "2"; } public void testFailingDuplexServer() throws Exception { CallbackEnabledSocketCustomStreamHostContext hostContext = new CallbackEnabledSocketCustomStreamHostContext("127.0.0.1", 12345); checkHostContext(hostContext); } } 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/DyingSimplexServerTestCase.java Index: DyingSimplexServerTestCase.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.multiprocess; import org.apache.excalibur.altrmi.client.impl.socket.SocketCustomStreamHostContext; /** * DyingSimplexServerTestCase * * @author Paul Hammant * @version $Revision: 1.1 $ */ public class DyingSimplexServerTestCase extends AbstractDyingServerTestCase { public DyingSimplexServerTestCase(String name) { super(name); } protected String getServerType() { return "1"; } public void testFailingSimplexServer() throws Exception { SocketCustomStreamHostContext hostContext = new SocketCustomStreamHostContext("127.0.0.1", 12345); checkHostContext(hostContext); } } 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/MultiProcessTestCase.java Index: MultiProcessTestCase.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.multiprocess; import junit.framework.TestCase; /** * MultiProcessTestCase * * @author Paul Hammant * @version $Revision: 1.1 $ */ public class MultiProcessTestCase extends TestCase { private Process m_process; public MultiProcessTestCase(String name) { super(name); Class cl = SimpleMainable.class; } protected void setUp() throws Exception { super.setUp(); String classpath = System.getProperty("java.class.path"); String command = "java -cp " + classpath + " org.apache.excalibur.altrmi.multiprocess.SimpleMainable"; //System.out.println("command = " + command); m_process = Runtime.getRuntime().exec(command); } public void testProcessKill() throws Exception { Thread.currentThread().sleep(1000); m_process.destroy(); boolean killed = false; int rc = -1; while (killed == false) { try { rc = m_process.exitValue(); killed = true; } catch (IllegalThreadStateException e) { try { Thread.currentThread().sleep(50); } catch (InterruptedException ie) { } } } assertTrue(rc > 0); } } 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/MultiTestServer.java Index: MultiTestServer.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.multiprocess; import org.apache.excalibur.altrmi.server.impl.socket.CompleteSocketCustomStreamServer; import org.apache.excalibur.altrmi.server.impl.AbstractServer; import org.apache.excalibur.altrmi.server.impl.callback.socket.CallbackEnabledSocketCustomStreamServer; import org.apache.excalibur.altrmi.server.PublicationDescription; import org.apache.excalibur.altrmi.test.TestInterface; import org.apache.excalibur.altrmi.test.TestInterface2; import org.apache.excalibur.altrmi.test.TestObject; import org.apache.excalibur.altrmi.test.TestCallBackListener; import org.apache.excalibur.altrmi.test.TestInterface3; import java.beans.PropertyVetoException; import java.io.IOException; /** * MultiTestServer * * @author Paul Hammant * @version $Revision: 1.1 $ */ public class MultiTestServer { private AbstractServer m_server; private TestInterface testServer; public MultiTestServer(String type) throws Exception{ if (type.equals("1")) { m_server = new CompleteSocketCustomStreamServer(12345); } else { m_server = new CallbackEnabledSocketCustomStreamServer(12345); } testServer = new TestInterface() { public void hello(String greeting) { System.out.println("exit!"); System.exit(10); } public int hello2(int greeting) { return 123; } public boolean hello3(short greeting) throws PropertyVetoException, IOException { return false; } public StringBuffer hello4(float greeting1, double greeting2) { return null; } public void testSpeed() { } public TestInterface2 makeTestInterface2(String thingName) { return null; } public void morphName(TestInterface2 forThisImpl) { } public TestInterface2 findTestInterface2ByName(String nameToFind) { return null; } public TestInterface2[] getTestInterface2s() { return new TestInterface2[0]; } public TestObject[] getTestObjects() { return new TestObject[0]; } public void changeTestObjectNames() { } public void makeNewTestObjectNames() { } public boolean addCallBackListener(TestCallBackListener testCallbackListener) { return false; } public void ping() { } }; PublicationDescription pd = new PublicationDescription(TestInterface.class, new Class[] { TestInterface3.class, TestInterface2.class }); m_server.publish(testServer, "Hello", pd); m_server.start(); } public static void main(String[] args) throws Exception { new MultiTestServer(args[0]); } } 1.1 avalon-excalibur/altrmi/src/test/org/apache/excalibur/altrmi/multiprocess/SimpleMainable.java Index: SimpleMainable.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.altrmi.multiprocess; /** * SimpleMainable * * @author Paul Hammant * @version $Revision: 1.1 $ */ public class SimpleMainable { public static void main(String[] args) { System.out.println("SimpleMainable.main"); System.exit(10); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]