RMIIncomingThread.java: New file.
authorNorbert Frese <postfach@nfrese.net>
Sat, 20 Mar 2004 20:30:56 +0000 (20:30 +0000)
committerMichael Koch <mkoch@gcc.gnu.org>
Sat, 20 Mar 2004 20:30:56 +0000 (20:30 +0000)
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.

From-SVN: r79755

libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gnu/java/rmi/server/RMIIncomingThread.java [new file with mode: 0644]
libjava/gnu/java/rmi/server/UnicastConnection.java
libjava/gnu/java/rmi/server/UnicastConnectionManager.java
libjava/gnu/java/rmi/server/UnicastRef.java
libjava/gnu/java/rmi/server/UnicastRemoteCall.java
libjava/gnu/java/rmi/server/UnicastServer.java
libjava/gnu/java/rmi/server/UnicastServerRef.java
libjava/java/rmi/server/RemoteServer.java

index 119c586737c0e85219330b366d4d1be7a86f8e8f..3fa4bcb6f06ef43371b51ea5ce8f9aaf49b8bcdd 100644 (file)
@@ -1,3 +1,39 @@
+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.
+
 2004-03-20  Michael Koch  <konqueror@gmx.de>
 
        * java/net/InetAddress.java
index 254c9ca53f799587173b10c40ca3e632ff7ce62f..ddec112c38c3359e71f98d2a7eb687aa2c22082e 100644 (file)
@@ -1704,6 +1704,7 @@ gnu/java/rmi/server/ConnectionRunnerPool.java \
 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 e664a10fbbdb7ab698423b1ba2cc68e0d6183801..c23863a1526b40250d8f066dbce3561cb32cc99b 100644 (file)
@@ -1387,6 +1387,7 @@ gnu/java/rmi/server/ConnectionRunnerPool.java \
 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 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .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 \
diff --git a/libjava/gnu/java/rmi/server/RMIIncomingThread.java b/libjava/gnu/java/rmi/server/RMIIncomingThread.java
new file mode 100644 (file)
index 0000000..2855c03
--- /dev/null
@@ -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 14d28f26c91b6ab015cee8b0c94c56cd32e8a006..19e074a08602cbabaf4352287ff591782c7a5bf5 100644 (file)
@@ -104,6 +104,7 @@ void acceptConnection() throws IOException {
 void makeConnection(int protocol) throws IOException {
     //Use BufferedXXXStream would be more efficient
        din = new DataInputStream(new BufferedInputStream(sock.getInputStream()));
+
        dout = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream()));
 
        // Send header
@@ -139,20 +140,48 @@ DataOutputStream getDataOutputStream() throws IOException {
        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)
@@ -200,4 +229,5 @@ public void run() {
     }while(true);
 }
 
+
 }
index 3b9aa40e0b8fc2e40935e654c897f24015a9b158..b7a505d20840ac8b765abe9083e057cbfe695cb9 100644 (file)
@@ -59,6 +59,7 @@ import java.util.Hashtable;
 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 @@ private UnicastConnectionManager(String host, int port, RMIClientSocketFactory c
 /**
   * 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 __) {
-                       ssock = null;
-                       serverPort = 0;
-               }
+       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 @@ public static synchronized UnicastConnectionManager getInstance(String host, int
  * 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 @@ public void run() {
                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 aaec7a3b470d07fa6f308ba42bae151ca94ec224..60a745e84f578cba9d30fc817ee0e10daf16b3bf 100644 (file)
@@ -116,7 +116,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
                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 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
                        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 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
        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 2d7d6d4a9ff1287776940b59b49b1157293737e9..76dd8e215b75d2194bffc34f5d2fc8e32d0a8288 100644 (file)
@@ -138,6 +138,21 @@ public class UnicastRemoteCall
       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 @@ public class UnicastRemoteCall
        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 @@ public class UnicastRemoteCall
         if (din.readByte() != MESSAGE_CALL_ACK)
            throw new RemoteException("Call not acked");
 
-        oin = getInputStream();
+        oin = startInputStream();
         returncode = oin.readByte();
         UID.read(oin);
       }
index fb6ec1f35a5e61ebef712becf2c7b3316597162d..ace43f0186166427b12a3845750deee17a145b57 100644 (file)
@@ -99,13 +99,19 @@ public static void dispatch(UnicastConnection conn) throws Exception {
        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 @@ private static void incomingMessageCall(UnicastConnection conn) throws IOExcepti
 
        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 b004927502fbe024abe8f5a24cf028f9223b7d93..3e9529c598b3b56331863eb2a5d3a64114911b8f 100644 (file)
@@ -46,6 +46,7 @@ import java.rmi.RemoteException;
 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 @@ UnicastServerRef()
 {
 }
 
-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 @@ public RemoteStub exportObject(Remote obj) throws RemoteException {
 
                // 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 @@ public boolean unexportObject(Remote obj, boolean force) {
     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 @@ private Object getHelperClass(Class cls, String type) {
        return (null);
 }
 
+
+
 public String getClientHost() throws ServerNotActiveException {
-       throw new Error("Not implemented");
+       return RemoteServer.getClientHost();
 }
 
 private void buildMethodHash(Class cls, boolean build) {
index b9cfc4e898e6dc3b3f41071cd6888f32d4410127..85a2d955124978343ff9cc2f36e71cb8b75a0ba3 100644 (file)
@@ -39,6 +39,7 @@ package java.rmi.server;
 
 import java.io.OutputStream;
 import java.io.PrintStream;
+import gnu.java.rmi.server.RMIIncomingThread;
 
 public abstract class RemoteServer
        extends RemoteObject {
@@ -54,7 +55,14 @@ protected RemoteServer(RemoteRef ref) {
 }
 
 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) {