Index: gnu/java/rmi/server/RMIIncomingThread.java =================================================================== RCS file: gnu/java/rmi/server/RMIIncomingThread.java diff -N gnu/java/rmi/server/RMIIncomingThread.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ gnu/java/rmi/server/RMIIncomingThread.java 21 Mar 2004 10:08:23 -0000 @@ -0,0 +1,58 @@ +/* + Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.rmi.server; + +public class RMIIncomingThread extends Thread { + + private String clientHost = null; + + public RMIIncomingThread(Runnable runnable, String s_clientHost) { + super(runnable); + clientHost = s_clientHost; + } + + public String toString() { + return "RMIIncoming from " + clientHost + " " + super.toString(); + } + + public String getClientHost() { + return clientHost; + } + + +} Index: gnu/java/rmi/server/UnicastConnection.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastConnection.java,v retrieving revision 1.4 diff -u -b -B -r1.4 UnicastConnection.java --- gnu/java/rmi/server/UnicastConnection.java 31 Oct 2002 18:35:21 -0000 1.4 +++ gnu/java/rmi/server/UnicastConnection.java 21 Mar 2004 10:08:23 -0000 @@ -139,20 +140,48 @@ return (dout); } +/* +* +* get ObjectInputStream for reading more objects +* +*/ ObjectInputStream getObjectInputStream() throws IOException { if (oin == null) { - oin = new RMIObjectInputStream(din); + throw new IOException("no ObjectInputtream for reading more objects"); } return (oin); } +/** +* +* starts ObjectInputStream. +* +*/ +ObjectInputStream startObjectInputStream() throws IOException { + return (oin = new RMIObjectInputStream(din)); +} + +/** +* +* get ObjectOutputStream for sending more objects +* +*/ ObjectOutputStream getObjectOutputStream() throws IOException { if (oout == null) { - oout = new RMIObjectOutputStream(dout); + throw new IOException("no ObjectOutputStream for sending more objects"); } return (oout); } +/** +* +* starts ObjectOutputStream. +* +*/ +ObjectOutputStream startObjectOutputStream() throws IOException { + return (oout = new RMIObjectOutputStream(dout)); +} + void disconnect() { try { if(oout != null) Index: gnu/java/rmi/server/UnicastConnectionManager.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastConnectionManager.java,v retrieving revision 1.5 diff -u -b -B -r1.5 UnicastConnectionManager.java --- gnu/java/rmi/server/UnicastConnectionManager.java 26 Dec 2003 01:45:41 -0000 1.5 +++ gnu/java/rmi/server/UnicastConnectionManager.java 21 Mar 2004 10:08:23 -0000 @@ -59,6 +59,7 @@ import java.util.Iterator; import gnu.java.rmi.server.UnicastConnection; +import gnu.java.rmi.server.RMIIncomingThread; public class UnicastConnectionManager implements Runnable, ProtocolConstants { @@ -173,20 +174,16 @@ /** * Server UnicastConnectionManager constructor */ -private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) { +private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) throws RemoteException { + try { ssock = ssf.createServerSocket(port); serverPort = ssock.getLocalPort(); } - catch (IOException _) { - try { - ssock = ssf.createServerSocket(0); - serverPort = ssock.getLocalPort(); - } - catch (IOException __) { + catch (IOException ioex) { ssock = null; serverPort = 0; - } + throw new java.rmi.server.ExportException("can not create Server Socket on port " + port,ioex); } serverName = localhost; serverFactory = ssf; @@ -230,7 +227,7 @@ * Return a server connection manager which will accept connection on the * given port. */ -public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) { +public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException { //System.out.println("getInstance: " + port + "," + ssf); if (ssf == null) { ssf = defaultSocketFactory; @@ -376,9 +373,17 @@ try { //System.out.println("Waiting for connection on " + serverPort); UnicastConnection conn = getServerConnection(); + + // get address of remote host for the RMIIncomingThread object + String remoteHost = null; + if (conn.sock != null) { + remoteHost = conn.sock.getInetAddress().getHostAddress(); + } + // use a thread pool to improve performance //ConnectionRunnerPool.dispatchConnection(conn); - (new Thread(conn)).start(); + (new RMIIncomingThread(conn, remoteHost)).start(); +// (new Thread(conn)).start(); } catch (Exception e) { e.printStackTrace(); Index: gnu/java/rmi/server/UnicastRef.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastRef.java,v retrieving revision 1.5 diff -u -b -B -r1.5 UnicastRef.java --- gnu/java/rmi/server/UnicastRef.java 11 Aug 2003 14:13:27 -0000 1.5 +++ gnu/java/rmi/server/UnicastRef.java 21 Mar 2004 10:08:23 -0000 @@ -116,7 +116,7 @@ dout = conn.getDataOutputStream(); dout.writeByte(MESSAGE_CALL); - out = conn.getObjectOutputStream(); + out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream objid.write(out); out.writeInt(opnum); @@ -146,19 +146,22 @@ throw new RemoteException("Call not acked:" + returncode); } - in = conn.getObjectInputStream(); + in = conn.startObjectInputStream(); // (re)start ObjectInputStream returncode = in.readUnsignedByte(); ack = UID.read(in); Class cls = method.getReturnType(); - if(cls == Void.TYPE){ - returnval = null; - in.readObject(); - }else - returnval = ((RMIObjectInputStream)in).readValue(cls); + if (returncode == RETURN_NACK) { + returnval = in.readObject(); // get Exception + + } else if(cls == Void.TYPE) { + returnval = null; + // in.readObject() // not required! returntype 'void' means no field is returned. + } else { + returnval = ((RMIObjectInputStream)in).readValue(cls); // get returnvalue } - catch (IOException e3) { + } catch (IOException e3) { //for debug: e3.printStackTrace(); throw new RemoteException("call return failed: ", e3); } @@ -174,7 +177,8 @@ manager.discardConnection(conn); if (returncode != RETURN_ACK && returnval != null) { - throw (Exception)returnval; + if (returncode == RETURN_NACK) throw (Exception)returnval; + else throw new RemoteException("unexpected returncode: " + returncode); } return (returnval); Index: gnu/java/rmi/server/UnicastRemoteCall.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastRemoteCall.java,v retrieving revision 1.8 diff -u -b -B -r1.8 UnicastRemoteCall.java --- gnu/java/rmi/server/UnicastRemoteCall.java 26 Dec 2003 01:45:41 -0000 1.8 +++ gnu/java/rmi/server/UnicastRemoteCall.java 21 Mar 2004 10:08:23 -0000 @@ -138,6 +138,21 @@ oout.flush(); } + /** + * + * (re)starts ObjectInputStream + * + */ + public ObjectInput startInputStream() throws IOException + { + if (conn != null) { + return (oin = conn.startObjectInputStream()); + } else { + return getInputStream(); // dummy Input Stream + } + + } + public ObjectInput getInputStream() throws IOException { if (conn != null) @@ -177,7 +192,7 @@ DataOutputStream dout = conn.getDataOutputStream(); dout.write(MESSAGE_CALL); - oout = conn.getObjectOutputStream(); + oout = conn.startObjectOutputStream(); // (re)start ObjectOutputStream objid.write(oout); oout.writeInt(opnum); oout.writeLong(hash); @@ -194,7 +209,7 @@ if (din.readByte() != MESSAGE_CALL_ACK) throw new RemoteException("Call not acked"); - oin = getInputStream(); + oin = startInputStream(); returncode = oin.readByte(); UID.read(oin); } Index: gnu/java/rmi/server/UnicastServer.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastServer.java,v retrieving revision 1.5 diff -u -b -B -r1.5 UnicastServer.java --- gnu/java/rmi/server/UnicastServer.java 26 Dec 2003 01:45:41 -0000 1.5 +++ gnu/java/rmi/server/UnicastServer.java 21 Mar 2004 10:08:23 -0000 @@ -99,13 +99,19 @@ case MESSAGE_CALL: incomingMessageCall(conn); break; + case MESSAGE_PING: + // jdk sends a ping before each method call -> answer it! + DataOutputStream out = conn.getDataOutputStream(); + out.writeByte(MESSAGE_PING_ACK); + out.flush(); + break; default: throw new Exception("bad method type"); } } private static void incomingMessageCall(UnicastConnection conn) throws IOException { - ObjectInputStream in = conn.getObjectInputStream(); + ObjectInputStream in = conn.startObjectInputStream(); // (re)start ObjectInputStream ObjID objid = ObjID.read(in); int method = in.readInt(); @@ -138,13 +144,18 @@ conn.getDataOutputStream().writeByte(MESSAGE_CALL_ACK); - ObjectOutputStream out = conn.getObjectOutputStream(); + ObjectOutputStream out = conn.startObjectOutputStream(); // (re)start ObjectOutputStream out.writeByte(returncode); (new UID()).write(out); + + //System.out.println("returnval=" + returnval + " returncls=" + returncls); + if(returnval != null && returncls != null) ((RMIObjectOutputStream)out).writeValue(returnval, returncls); - else if (!(returnval instanceof RMIVoidValue)) + + // 1.1/1.2 void return type detection: + else if (!(returnval instanceof RMIVoidValue || returncls == Void.TYPE)) out.writeObject(returnval); out.flush(); Index: gnu/java/rmi/server/UnicastServerRef.java =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/UnicastServerRef.java,v retrieving revision 1.8 diff -u -b -B -r1.8 UnicastServerRef.java --- gnu/java/rmi/server/UnicastServerRef.java 26 Dec 2003 01:45:41 -0000 1.8 +++ gnu/java/rmi/server/UnicastServerRef.java 21 Mar 2004 10:08:23 -0000 @@ -46,6 +46,7 @@ import java.rmi.server.RemoteStub; import java.rmi.server.ObjID; import java.rmi.server.ServerRef; +import java.rmi.server.RemoteServer; import java.rmi.server.RemoteRef; import java.rmi.server.ServerNotActiveException; import java.rmi.server.RMIClientSocketFactory; @@ -85,7 +86,7 @@ { } -public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) { +public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) throws RemoteException { super(id); manager = UnicastConnectionManager.getInstance(port, ssf); } @@ -99,13 +100,21 @@ // Find and install the stub Class cls = obj.getClass(); - stub = (RemoteStub)getHelperClass(cls, "_Stub"); + Class expCls; + try { + // where ist the _Stub? (check superclasses also) + expCls = findStubSkelClass(cls); + } catch (Exception ex) { + throw new RemoteException("can not find stubs for class: " + cls, ex); + } + + stub = (RemoteStub)getHelperClass(expCls, "_Stub"); if (stub == null) { throw new RemoteException("failed to export: " + cls); } // Find and install the skeleton (if there is one) - skel = (Skeleton)getHelperClass(cls, "_Skel"); + skel = (Skeleton)getHelperClass(expCls, "_Skel"); // Build hash of methods which may be called. buildMethodHash(obj.getClass(), true); @@ -135,6 +144,38 @@ return UnicastServer.unexportObject(this, force); } +/** +* +* The Subs/Skels might not there for the actual class, but maybe +* for one of the superclasses. +* +*/ +private Class findStubSkelClass(Class startCls) throws Exception { + Class cls = startCls; + + while (true) { + try { + String stubClassname = cls.getName() + "_Stub"; + ClassLoader cl = cls.getClassLoader(); + Class scls = cl == null ? Class.forName(stubClassname) + : cl.loadClass(stubClassname); + return cls; // found it + } catch (ClassNotFoundException e) { + Class superCls = cls.getSuperclass(); + if (superCls == null + || superCls == java.rmi.server.UnicastRemoteObject.class) + { + throw new Exception("Neither " + startCls + + " nor one of their superclasses (like" + cls + ")" + + " has a _Stub"); + } + cls = superCls; + } + } +} + + + private Object getHelperClass(Class cls, String type) { try { String classname = cls.getName(); @@ -176,8 +217,10 @@ return (null); } + + public String getClientHost() throws ServerNotActiveException { - throw new Error("Not implemented"); + return RemoteServer.getClientHost(); } private void buildMethodHash(Class cls, boolean build) { Index: gnu/java/rmi/server/Makefile.am =================================================================== RCS file: /cvsroot/classpath/classpath/gnu/java/rmi/server/Makefile.am,v retrieving revision 1.3 diff -u -b -B -r1.3 Makefile.am --- gnu/java/rmi/server/Makefile.am 26 Dec 2003 01:45:41 -0000 1.3 +++ gnu/java/rmi/server/Makefile.am 21 Mar 2004 10:08:23 -0000 @@ -5,6 +5,7 @@ ProtocolConstants.java \ RMIDefaultSocketFactory.java \ RMIHashes.java \ +RMIIncomingThread.java \ RMIObjectInputStream.java \ RMIObjectOutputStream.java \ RMIVoidValue.java \ Index: java/rmi/server/RemoteServer.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/rmi/server/RemoteServer.java,v retrieving revision 1.3 diff -u -b -B -r1.3 RemoteServer.java --- java/rmi/server/RemoteServer.java 25 Mar 2002 05:12:19 -0000 1.3 +++ java/rmi/server/RemoteServer.java 21 Mar 2004 10:08:23 -0000 @@ -39,6 +39,7 @@ import java.io.OutputStream; import java.io.PrintStream; +import gnu.java.rmi.server.RMIIncomingThread; public abstract class RemoteServer extends RemoteObject { @@ -54,7 +55,14 @@ } public static String getClientHost() throws ServerNotActiveException { - throw new Error("Not implemented"); + Thread currThread = Thread.currentThread(); + if (currThread instanceof RMIIncomingThread) { + RMIIncomingThread incomingThread = (RMIIncomingThread) currThread; + return incomingThread.getClientHost(); + } else { + throw new ServerNotActiveException( + "Unknown client host - current thread not instance of 'RMIIncomingThread'"); + } } public static void setLog(OutputStream out) {