This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: Patch: Norbert's RMI patch


Hi list,


I just commited the attached patch from Norbert Frese which fixes some 
bugs in RMI.


Michael


2004-03-20  Norbert Frese  <postfach@nfrese.net>

	* gnu/java/rmi/server/RMIIncomingThread.java: New file.
	* gcc/libjava/gnu/java/rmi/server/UnicastConnection.java:
	Create a new RMIObjectOuputStream/RMIObjectInputStream for every
	rmi-message.
	(getObjectInputStream): Return object reference, throw IOException if 
null.
	(startObjectInputStream): Create new RMIObjectInputStream on top of 
'din'.
	(getObjectOutputStream): Return object reference, throw IOException if 
null.
	(startObjectOutputStream): Create new RMIObjectOutputStream on top of 
'dout'.
	* gcc/libjava/gnu/java/rmi/server/UnicastConnectionManager.java:
	(UnicastConnectionManager): Throw RemoteException if port is not 
available.
	(getInstance): Throw RemoteException.
	(run): Lookup client host and attach it to new RMIIncomingThread for 
later retrieval.
	* gcc/libjava/gnu/java/rmi/server/UnicastRef.java:
	Start a new RMIObjectInputStream/RMIObjectOutputStream for every 
rmi-message.
	Collect Exceptions which are returned by a rmi-call and fix void 
returns.
	* gcc/libjava/gnu/java/rmi/server/UnicastRemoteCall.java:
	Start a new RMIObjectInputStream/RMIObjectOutputStream for every 
rmi-message.
	* gcc/libjava/gnu/java/rmi/server/UnicastServer.java:
	(dispatch): Answer ping messages which are sent by other java 
implementions.
	(incomingMessageCall): Start a new 
RMIObjectInputStream/RMIObjectOutputStream
	for every rmi-message and fix void return problems.
	* gcc/libjava/gnu/java/rmi/server/UnicastServerRef.java
	(UnicastServerRef): Throw RemoteException.
	(exportObject): Find the class up the class hierarchy which has a _Stub 
generated by rmic.
	In some situations it is necessary to export a subclass of the class 
which has the _Stub.
	For instance when the class with has the _Stub is abstract.
	(findStubSkelClass): New method which looks for the class which has the 
_Stub.
	(getClientHost): Implementated.
	* gcc/libjava/java/rmi/server/RemoteServer.java
	(getClientHost): Implementated.
	* gcc/libjava/Makefile.am (rmi_java_source_files):
	Added gnu/java/rmi/server/RMIIncomingThread.java.
	* Makefile.in: Regenerated.

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	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/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	7 Nov 2002 18:01:05 -0000	1.4
+++ gnu/java/rmi/server/UnicastConnection.java	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/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 16:13:01 -0000	1.5
+++ gnu/java/rmi/server/UnicastConnectionManager.java	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/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	20 Sep 2003 21:23:47 -0000	1.5
+++ gnu/java/rmi/server/UnicastRef.java	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastRemoteCall.java,v
retrieving revision 1.6
diff -u -b -B -r1.6 UnicastRemoteCall.java
--- gnu/java/rmi/server/UnicastRemoteCall.java	26 Dec 2003 16:13:01 -0000	1.6
+++ gnu/java/rmi/server/UnicastRemoteCall.java	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/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 16:13:01 -0000	1.5
+++ gnu/java/rmi/server/UnicastServer.java	20 Mar 2004 20:30:33 -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: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastServerRef.java,v
retrieving revision 1.7
diff -u -b -B -r1.7 UnicastServerRef.java
--- gnu/java/rmi/server/UnicastServerRef.java	26 Dec 2003 16:13:01 -0000	1.7
+++ gnu/java/rmi/server/UnicastServerRef.java	20 Mar 2004 20:30:33 -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: java/rmi/server/RemoteServer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/rmi/server/RemoteServer.java,v
retrieving revision 1.3
diff -u -b -B -r1.3 RemoteServer.java
--- java/rmi/server/RemoteServer.java	16 Sep 2002 09:46:36 -0000	1.3
+++ java/rmi/server/RemoteServer.java	20 Mar 2004 20:30:34 -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) {
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.367
diff -u -b -B -r1.367 Makefile.am
--- Makefile.am	20 Mar 2004 00:24:48 -0000	1.367
+++ Makefile.am	20 Mar 2004 20:30:35 -0000
@@ -1704,6 +1704,7 @@
 gnu/java/rmi/server/ProtocolConstants.java \
 gnu/java/rmi/server/RMIDefaultSocketFactory.java \
 gnu/java/rmi/server/RMIHashes.java \
+gnu/java/rmi/server/RMIIncomingThread.java \
 gnu/java/rmi/server/RMIObjectInputStream.java \
 gnu/java/rmi/server/RMIObjectOutputStream.java \
 gnu/java/rmi/server/RMIVoidValue.java \
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.in,v
retrieving revision 1.391
diff -u -b -B -r1.391 Makefile.in
--- Makefile.in	20 Mar 2004 00:24:48 -0000	1.391
+++ Makefile.in	20 Mar 2004 20:30:37 -0000
@@ -1387,6 +1387,7 @@
 gnu/java/rmi/server/ProtocolConstants.java \
 gnu/java/rmi/server/RMIDefaultSocketFactory.java \
 gnu/java/rmi/server/RMIHashes.java \
+gnu/java/rmi/server/RMIIncomingThread.java \
 gnu/java/rmi/server/RMIObjectInputStream.java \
 gnu/java/rmi/server/RMIObjectOutputStream.java \
 gnu/java/rmi/server/RMIVoidValue.java \
@@ -3347,6 +3348,7 @@
 .deps/gnu/java/rmi/server/ProtocolConstants.P \
 .deps/gnu/java/rmi/server/RMIDefaultSocketFactory.P \
 .deps/gnu/java/rmi/server/RMIHashes.P \
+.deps/gnu/java/rmi/server/RMIIncomingThread.P \
 .deps/gnu/java/rmi/server/RMIObjectInputStream.P \
 .deps/gnu/java/rmi/server/RMIObjectOutputStream.P \
 .deps/gnu/java/rmi/server/RMIVoidValue.P \

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]