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]

RMI patch


Hi,

Here is the RMI patch that I told about on the java mailinglist. I tried
it a bit with the test program from bug #7938 but that test program
still doesn't work. (It did show that natField.cc needed to make sure
that the type class is resolved as fixed in my previous patch).

So even after this patch we need someone to really care about RMI and
hack this implementation into something workable.

2002-11-07  Mark Wielaard  <mark@klomp.org>

        Merge Orp RMI patches from Wu Gansha <gansha.wu@intel.com>
        * java/rmi/MarshalledObject.java (equals): Check hashcode first.

        * java/rmi/server/RMIClassLoader.java (MyClassLoader): Create/Use
        annotation. 
        (loadClass): Take String as codebases.
        (getClassAnnotation): Use MyClassLoader annotations.
        * java/rmi/server/UnicastRemoteObject.java (UnicastRemoteObject):
        call exportObject(this). 

        * gnu/java/rmi/RMIMarshalledObjectOutputStream.java
        (RMIMarshalledObjectOutputStream): set locBytesStream and locStream.
        (setAnnotation): Don't set locBytesStream and locStream.
        (replaceObject): Removed.
        (flush): Don't test locStream.
        (getLocBytes): LikeWise.
        * gnu/java/rmi/dgc/DGCImpl.java: extends UnicastServerRef.
        (leaseCache): New field.
        (dirty): Use leaseCache.
        (LeaseRecord): New inner class.
        * gnu/java/rmi/registry/RegistryImpl.java (RegistryImpl): Don't
        explicitly call exportObject().
        * gnu/java/rmi/registry/RegistryImpl_Stub.java: set useNewInvoke to
        false to communicate with Sun JDK130.
        * gnu/java/rmi/server/ConnectionRunnerPool.java: Add CPU comment.
        * gnu/java/rmi/server/RMIObjectInputStream.java
        (UnicastConnectionManager): Removed field.
        * gnu/java/rmi/server/RMIObjectOutputStream.java (replaceObject):
        Use UnicastServer.getExportedRef().
        * gnu/java/rmi/server/UnicastConnection.java (reviveTime): New field.
        (expireTime): Likewise.
        (CONNECTION_TIMEOUT): Likewise.
        (disconnect): Call sock.close().
        (isExpired): New method.
        (resetTime): Likewise.
        (run): Use do while loop and catch Exception for discardConnection().
        * gnu/java/rmi/server/UnicastConnectionManager.java: Pool connections.
        * gnu/java/rmi/server/UnicastRef.java: Lots of changes.
        * gnu/java/rmi/server/UnicastRemoteCall.java: Lots of changes.
        * gnu/java/rmi/server/UnicastServer.java (refcache): New field.
        (exportObject): Use refcache.
        (unexportObject): Likewise.
        (getExportedRef): New method.
        * gnu/java/rmi/server/UnicastServerRef.java (UnicastServerRef): New
        constructor.
        (exportObject): Save manager.serverobj.
        (getStub): New method.

Should I commit this?

Cheers,

Mark
Index: java/rmi/MarshalledObject.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/rmi/MarshalledObject.java,v
retrieving revision 1.3
diff -u -r1.3 MarshalledObject.java
--- java/rmi/MarshalledObject.java	1 Oct 2002 03:46:43 -0000	1.3
+++ java/rmi/MarshalledObject.java	7 Nov 2002 15:46:12 -0000
@@ -78,6 +78,10 @@
   {
     if(obj == null || !(obj instanceof MarshalledObject) )
       return false;
+
+    // hashCode even differs, don't do the time-consuming comparisons
+    if (obj.hashCode() != hash)
+      return false;
     
     MarshalledObject aobj = (MarshalledObject)obj;
     if (objBytes == null || aobj.objBytes == null)
Index: java/rmi/server/RMIClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/rmi/server/RMIClassLoader.java,v
retrieving revision 1.4
diff -u -r1.4 RMIClassLoader.java
--- java/rmi/server/RMIClassLoader.java	1 Oct 2002 03:46:43 -0000	1.4
+++ java/rmi/server/RMIClassLoader.java	7 Nov 2002 15:46:12 -0000
@@ -43,39 +43,72 @@
 import java.io.IOException;
 import java.io.DataInputStream;
 import java.net.MalformedURLException;
-import java.util.StringTokenizer;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Hashtable;
 import java.util.Map;
+import java.util.StringTokenizer;
 import java.util.WeakHashMap;
-import java.util.ArrayList;
 
 public class RMIClassLoader
 {
 
   static private class MyClassLoader extends URLClassLoader
   {
+
+    private MyClassLoader(URL[] urls, ClassLoader parent, String annotation)
+    {
+      super(urls, parent);
+      this.annotation = annotation;
+    }
+
     private MyClassLoader(URL[] urls, ClassLoader parent)
     {
       super (urls, parent);
+      this.annotation = urlToAnnotation(urls);
     }
 
-    Class defineClass(String name, byte[] data)
+    public static String urlToAnnotation(URL[] urls)
     {
-      return defineClass(name, data, 0, data.length);
+      if (urls.length == 0)
+	return null;
+
+      StringBuffer annotation = new StringBuffer(64*urls.length);
+      for(int i = 0; i < urls.length; i++)
+	{
+	  annotation.append(urls[i].toExternalForm());
+	  annotation.append(' ');
+	}
+
+      return annotation.toString();
+    }
+
+    public final String getClassAnnotation(){
+      return annotation;
     }
+
+    private final String annotation;
+
   }
 
   private static Map cacheLoaders; //map annotations to loaders
-  private static Map cacheClasses; //map loader to classes that the loader loaded+
+  private static Map cacheAnnotations; //map loaders to annotations
+
+  //defaultAnnotation is got from system property
+  // "java.rmi.server.defaultAnnotation"
   private static String defaultAnnotation;
+  //URL object for defaultAnnotation
   private static URL defaultCodebase;
+  //class loader for defaultAnnotation
   private static MyClassLoader defaultLoader;
   
   static
   {
-    cacheLoaders = Collections.synchronizedMap(new WeakHashMap(5)); 
-    cacheClasses = Collections.synchronizedMap(new WeakHashMap(5));
+    // 89 is a nice prime number for Hashtable initial capacity
+    cacheLoaders = new Hashtable(89);
+    cacheAnnotations = new Hashtable(89);
+    
     defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
     try 
       {
@@ -89,9 +122,8 @@
     if (defaultCodebase != null)
       {
         defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },
-					  Thread.currentThread().getContextClassLoader());
+					  null, defaultAnnotation);
         cacheLoaders.put(defaultAnnotation, defaultLoader);
-        cacheClasses.put(defaultLoader, Collections.synchronizedMap(new WeakHashMap())); 
       }
   }
   
@@ -104,91 +136,76 @@
     return (loadClass("", name));
   }
 
-  public static Class loadClass(URL codebase, String name) 
+  public static Class loadClass(String codebases, String name) 
     throws MalformedURLException, ClassNotFoundException 
   {
-    URL u = new URL(codebase, name + ".class");
+    Class c = null;
+    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    //try context class loader first
     try 
       {
-	URLConnection conn = u.openConnection();
-	DataInputStream strm = new DataInputStream(conn.getInputStream());
-	byte data[] = new byte[conn.getContentLength()];
-	strm.readFully(data);
-	return (defaultLoader.defineClass(name, data));
-      }
-    catch (IOException _) 
-      {
-	throw new ClassNotFoundException(name);
+	    c = loader.loadClass(name);       
       }
-  }
-  
-  public static Class loadClass(String codebases, String name) 
-    throws MalformedURLException, ClassNotFoundException 
-  {
-    ClassLoader loader = (ClassLoader)cacheLoaders.get(codebases);
-    if (loader == null)
+    catch(ClassNotFoundException e) {}
+
+    if (c != null)
+      return c;
+
+    if (codebases.length() == 0) //==""
+      loader = defaultLoader;
+    else 
       {
-	if (codebases != "")
+	loader = (ClassLoader)cacheLoaders.get(codebases);
+	if (loader == null)
 	  {
-	    //codebases are separated by " "
+	    //create an entry in cacheLoaders mapping a loader to codebases.
+            
+	    // codebases are separated by " "
 	    StringTokenizer tok = new StringTokenizer(codebases, " "); 
 	    ArrayList urls = new ArrayList();
 	    while (tok.hasMoreTokens())
 	      urls.add(new URL(tok.nextToken()));
-	    
+  
 	    loader = new MyClassLoader((URL[])urls.toArray(new URL[urls.size()]),
-				       Thread.currentThread().getContextClassLoader());
+					null, codebases);
 	    cacheLoaders.put(codebases, loader);
-	    cacheClasses.put(loader, Collections.synchronizedMap(new WeakHashMap())); 
-	  }
-	else
-	  {
-	    //if codebases is empty, construct a classloader 
-	    // based on current context classloader,
-	    // and we won't cache classloader for empty codebases
-	    loader = new MyClassLoader(new URL[]{ defaultCodebase },
-				       Thread.currentThread().getContextClassLoader());
 	  }
       }
 
-    Class c = null;
-    Map classes = (Map)cacheClasses.get(loader);
-    if (classes != null)
-      {
-        c = (Class)classes.get(name);
-        if (c == null)
-	  {
-            c = loader.loadClass(name);
-            classes.put(name, c); 
-	  }
-      }else
-        c = loader.loadClass(name);
-    
-    return c;
+    return loader.loadClass(name);
   }
   
   public static String getClassAnnotation(Class cl)
   {
     ClassLoader loader = cl.getClassLoader();
-    if (loader == null)
+    if (loader == null || loader == ClassLoader.getSystemClassLoader())
       {
-	if (defaultCodebase != null)
-	  return defaultCodebase.toExternalForm();
-	else
-	  return null;
+	return null; //??
+      }
+	
+    if (loader instanceof MyClassLoader)
+      {
+	return ((MyClassLoader)loader).getClassAnnotation();
       }
+	
+    String s = (String)cacheAnnotations.get(loader);
+    if (s != null)
+      return s;
+	    
     if (loader instanceof URLClassLoader)
       {
 	URL[] urls = ((URLClassLoader)loader).getURLs();
 	if(urls.length == 0)
 	  return null;
-	StringBuffer annotation = new StringBuffer(urls[0].toExternalForm());
-	for(int i = 1; i < urls.length; i++)
+
+	StringBuffer annotation = new StringBuffer(64*urls.length);
+	for(int i = 0; i < urls.length; i++)
 	  {
-	    annotation.append(' ');
 	    annotation.append(urls[i].toExternalForm());
+	    annotation.append(' ');
 	  }
-	return annotation.toString();
+	s = annotation.toString();
+	cacheAnnotations.put(loader, s);
       }
     return null;
   }
Index: java/rmi/server/RemoteObject.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/rmi/server/RemoteObject.java,v
retrieving revision 1.3
diff -u -r1.3 RemoteObject.java
--- java/rmi/server/RemoteObject.java	1 Oct 2002 03:46:43 -0000	1.3
+++ java/rmi/server/RemoteObject.java	7 Nov 2002 15:46:12 -0000
@@ -127,11 +127,11 @@
 	  }
 	catch (InstantiationException e1) 
 	  {
-	    throw new UnmarshalException("failed to create ref");
+	    throw new UnmarshalException("failed to create ref", e1);
 	  }
 	catch (IllegalAccessException e2) 
 	  {
-	    throw new UnmarshalException("failed to create ref");
+	    throw new UnmarshalException("failed to create ref", e2);
 	  }
 	ref.readExternal(in);
       }
Index: java/rmi/server/UnicastRemoteObject.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/rmi/server/UnicastRemoteObject.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastRemoteObject.java
--- java/rmi/server/UnicastRemoteObject.java	1 Oct 2002 03:46:43 -0000	1.3
+++ java/rmi/server/UnicastRemoteObject.java	7 Nov 2002 15:46:12 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -67,16 +67,12 @@
   //this.csf = csf;
   //this.ssf = ssf;
   this.ref = new UnicastServerRef(new ObjID(), port, ssf);
-  //Should we export it here?
-  // if we export, we got infinite recursive call:
-  //  UnicastRemoteObject.<init>->...->UnicastServer.startDGC()->UnicastRemoteObject.<init>->...
-  //exportObject(this);
+  exportObject(this);
 }
 
 protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
 	super((UnicastServerRef)ref);
-       //Should we export it here?
-       //exportObject(this);
+	exportObject(this);
 }
 
 public Object clone() throws CloneNotSupportedException {
Index: gnu/java/rmi/RMIMarshalledObjectOutputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java,v
retrieving revision 1.1
diff -u -r1.1 RMIMarshalledObjectOutputStream.java
--- gnu/java/rmi/RMIMarshalledObjectOutputStream.java	1 Oct 2002 03:46:41 -0000	1.1
+++ gnu/java/rmi/RMIMarshalledObjectOutputStream.java	7 Nov 2002 15:46:12 -0000
@@ -61,42 +61,22 @@
   public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException
   {
     super(objStream);
+    locBytesStream = new ByteArrayOutputStream(256);
+    locStream = new ObjectOutputStream(locBytesStream);
   }
   
   //This method overrides RMIObjectOutputStream's.
   protected void setAnnotation(String annotation) throws IOException{
-    synchronized(this){
-      if(locStream == null){
-	locBytesStream = new ByteArrayOutputStream();
-	locStream = new ObjectOutputStream(locBytesStream);
-      }
-    }
     locStream.writeObject(annotation);
   }
   
-  //This method overrides ObjectOutputStream's to replace Remote to RemoteStub 
-  protected Object replaceObject(Object obj) throws IOException
-  {
-    if((obj instanceof Remote) && !(obj instanceof RemoteStub))
-      {
-	UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null);
-	try{
-	  return ref.exportObject((Remote)obj);
-	}catch(Exception e){}
-      }
-    return obj;
-  }
-  
   public void flush() throws IOException {
     super.flush();
-    if(locStream != null)
-      locStream.flush();
+    locStream.flush();
   }
   
   public byte[] getLocBytes(){
-    if(locStream != null)
-      return locBytesStream.toByteArray();
-    return null;
+    return locBytesStream.toByteArray();
   }
   
 } // End of RMIMarshalledObjectOutputStream
Index: gnu/java/rmi/dgc/DGCImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/dgc/DGCImpl.java,v
retrieving revision 1.3
diff -u -r1.3 DGCImpl.java
--- gnu/java/rmi/dgc/DGCImpl.java	1 Oct 2002 03:46:41 -0000	1.3
+++ gnu/java/rmi/dgc/DGCImpl.java	7 Nov 2002 15:46:12 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -46,24 +46,73 @@
 import java.rmi.server.RMISocketFactory;
 import gnu.java.rmi.server.UnicastServerRef;
 
+import java.util.Hashtable;
+
+/**
+  * I let DGCImpl to extend UnicastServerRef, but not 
+  * UnicastRemoteObject, because UnicastRemoteObject must
+  * exportObject automatically.
+  */
 public class DGCImpl
-	extends UnicastRemoteObject implements DGC {
+    extends UnicastServerRef implements DGC {
 
-private static final long leaseValue = 600000L;
+    private static final long LEASE_VALUE = 600000L;
+    // leaseCache caches a LeaseRecord associated with a vmid
+    private Hashtable leaseCache = new Hashtable();
 
 public DGCImpl() throws RemoteException {
-	super(new UnicastServerRef(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory()));
+    	super(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory());
 }
 
 public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException {
 	VMID vmid = lease.getVMID();
+    	if (vmid == null)
+    	    vmid = new VMID();
+    	long leaseValue = LEASE_VALUE;
+    	//long leaseValue = lease.getValue();
     lease = new Lease(vmid, leaseValue);
-	System.out.println("DGCImpl.dirty - not completely implemented");
+        synchronized(leaseCache){
+            LeaseRecord lr = (LeaseRecord)leaseCache.get(vmid);
+            if (lr != null)
+                lr.reset(leaseValue);
+            else{
+                lr = new LeaseRecord(vmid, leaseValue);
+                leaseCache.put(vmid, lr);
+            }
+        }
+        
 	return (lease);
 }
 
 public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong) throws RemoteException {
-	System.out.println("DGCImpl.clean - not implemented");
+  // Not implemented
 }
+    
+  /**
+   * LeaseRecord associates a vmid to expireTime.
+   */
+  private static class LeaseRecord{
+    private VMID vmid;
+    private long expireTime;
+    
+    LeaseRecord(VMID vmid, long leaseValue){
+      this.vmid = vmid;
+      reset(leaseValue);
+    }
+    
+    // reset expireTime
+    void reset(long leaseValue){
+      long l = System.currentTimeMillis();
+      expireTime = l + leaseValue;
+    }
+
+    boolean isExpired(){
+      long l = System.currentTimeMillis();
+      if ( l > expireTime)
+	return true;
+      return false;
+    }
+        
+  } //End of LeaseRecord
 
-}
+} //End of DGCImpl
Index: gnu/java/rmi/registry/RegistryImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/registry/RegistryImpl.java,v
retrieving revision 1.3
diff -u -r1.3 RegistryImpl.java
--- gnu/java/rmi/registry/RegistryImpl.java	25 Mar 2002 22:08:26 -0000	1.3
+++ gnu/java/rmi/registry/RegistryImpl.java	7 Nov 2002 15:46:12 -0000
@@ -64,7 +64,8 @@
 
 public RegistryImpl(int port, RMIClientSocketFactory cf, RMIServerSocketFactory sf) throws RemoteException {
 	super(new UnicastServerRef(new ObjID(ObjID.REGISTRY_ID), port, sf));
-	((UnicastServerRef)getRef()).exportObject(this);
+	// The following is unnecessary, because UnicastRemoteObject export itself automatically.
+	//((UnicastServerRef)getRef()).exportObject(this);
 }
 
 public Remote lookup(String name) throws RemoteException, NotBoundException, AccessException {
Index: gnu/java/rmi/registry/RegistryImpl_Stub.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java,v
retrieving revision 1.2
diff -u -r1.2 RegistryImpl_Stub.java
--- gnu/java/rmi/registry/RegistryImpl_Stub.java	1 Oct 2002 03:46:41 -0000	1.2
+++ gnu/java/rmi/registry/RegistryImpl_Stub.java	7 Nov 2002 15:46:13 -0000
@@ -67,7 +67,7 @@
     static {
         try {
             java.rmi.server.RemoteRef.class.getMethod("invoke", new java.lang.Class[] { java.rmi.Remote.class, java.lang.reflect.Method.class, java.lang.Object[].class, long.class });
-            useNewInvoke = true;
+            useNewInvoke = false;
             $method_bind_0 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("bind", new java.lang.Class[] {java.lang.String.class, java.rmi.Remote.class});
             $method_list_1 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("list", new java.lang.Class[] {});
             $method_lookup_2 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("lookup", new java.lang.Class[] {java.lang.String.class});
Index: gnu/java/rmi/server/ConnectionRunnerPool.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java,v
retrieving revision 1.1
diff -u -r1.1 ConnectionRunnerPool.java
--- gnu/java/rmi/server/ConnectionRunnerPool.java	1 Oct 2002 03:46:42 -0000	1.1
+++ gnu/java/rmi/server/ConnectionRunnerPool.java	7 Nov 2002 15:46:13 -0000
@@ -91,6 +91,7 @@
       
     }
   
+  // Should this value equal to number of CPU?
   private static int size = 5;
   private static int max_size = 10;
   
Index: gnu/java/rmi/server/RMIObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/RMIObjectInputStream.java,v
retrieving revision 1.3
diff -u -r1.3 RMIObjectInputStream.java
--- gnu/java/rmi/server/RMIObjectInputStream.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/RMIObjectInputStream.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -50,23 +50,13 @@
 public class RMIObjectInputStream
 	extends ObjectInputStream {
 
-UnicastConnectionManager manager;
-
-public RMIObjectInputStream(InputStream strm, UnicastConnectionManager man) throws IOException {
+public RMIObjectInputStream(InputStream strm) throws IOException {
 	super(strm);
-	manager = man;
 	enableResolveObject(true);
 }
 
-public RMIObjectInputStream(InputStream strm) throws IOException {
-	this(strm, UnicastConnectionManager.getInstance(0, null));
-}
-
 protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
 	String annotation = (String)getAnnotation();
-	try{
-		return super.resolveClass(desc);
-	}catch(ClassNotFoundException _){};
 	
 	try {
 		if(annotation == null)
@@ -90,24 +80,23 @@
         throws IOException, ClassNotFoundException
 {
     String annotation = (String)getAnnotation();
-    try{
-		return super.resolveProxyClass(intfs);
-	}catch(ClassNotFoundException _){};
 	
     Class clss[] = new Class[intfs.length];
     if(annotation == null)
         clss[0] = RMIClassLoader.loadClass(intfs[0]);
     else
         clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]);
+    
     //assume all interfaces can be loaded by the same classloader
     ClassLoader loader = clss[0].getClassLoader();
-    if(loader == null)
-        for(int i = 1; i < intfs.length; i++)
-            clss[i] = Class.forName(intfs[i]);    
-    else
-        for(int i = 1; i < intfs.length; i++)
-            clss[i] = loader.loadClass(intfs[i]);    
+    for (int i = 0; i < intfs.length; i++)
+        clss[i] = Class.forName(intfs[i], false, loader);
+        
+    try {
     return Proxy.getProxyClass(loader, clss);
+	} catch (IllegalArgumentException e) {
+	    throw new ClassNotFoundException(null, e);
+	}  
 }
 
 protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException {
@@ -134,4 +123,4 @@
         return readObject();
 }
 
-}
\ No newline at end of file
+}
Index: gnu/java/rmi/server/RMIObjectOutputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java,v
retrieving revision 1.3
diff -u -r1.3 RMIObjectOutputStream.java
--- gnu/java/rmi/server/RMIObjectOutputStream.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/RMIObjectOutputStream.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -72,10 +72,9 @@
         throws IOException
 {
     if((obj instanceof Remote) && !(obj instanceof RemoteStub)){
-	    UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null);
-		try{
-		    return ref.exportObject((Remote)obj);
-		}catch(Exception e){}
+	    UnicastServerRef ref = UnicastServer.getExportedRef((Remote)obj);
+	    if (ref != null)
+		    return ref.getStub();
     }
     return obj;
 }
Index: gnu/java/rmi/server/UnicastConnection.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastConnection.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastConnection.java
--- gnu/java/rmi/server/UnicastConnection.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/UnicastConnection.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -61,6 +61,10 @@
 ObjectInputStream oin;
 ObjectOutputStream oout;
 
+// reviveTime and expireTime make UnicastConnection pool-able
+long reviveTime = 0;
+long expireTime = Long.MAX_VALUE;
+
 UnicastConnection(UnicastConnectionManager man, Socket sock) {
 	this.manager = man;
 	this.sock = sock;
@@ -137,7 +141,7 @@
 
 ObjectInputStream getObjectInputStream() throws IOException {
 	if (oin == null) {
-		oin = new RMIObjectInputStream(din, manager);
+        oin = new RMIObjectInputStream(din);
 	}
 	return (oin);
 }
@@ -153,6 +157,7 @@
 	try {
 	    if(oout != null)
 	        oout.close();
+        sock.close();
 	}
 	catch (IOException _) {
     }
@@ -164,17 +169,35 @@
 	sock = null;
 }
 
+public static final long CONNECTION_TIMEOUT = 10000L;
+
+static boolean isExpired(UnicastConnection conn, long l){
+    if (l <= conn.expireTime )
+        return false;
+    return true;
+}
+
+static void resetTime(UnicastConnection conn){
+    long l = System.currentTimeMillis();
+    conn.reviveTime = l;
+    conn.expireTime = l + CONNECTION_TIMEOUT;
+}
+
 /**
  * We run connects on the server. Dispatch it then discard it.
  */
 public void run() {
+    do{
 	try {
 		UnicastServer.dispatch(this);
+            //don't discardConnection explicitly, only when
+            //  exception happens or the connection's expireTime 
+            //  comes
+        } catch (Exception e ){
 		manager.discardConnection(this);
+            break;
 	}
-	catch (Exception e) {
-		e.printStackTrace();
-	}
+    }while(true);
 }
 
 }
Index: gnu/java/rmi/server/UnicastConnectionManager.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastConnectionManager.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastConnectionManager.java
--- gnu/java/rmi/server/UnicastConnectionManager.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/UnicastConnectionManager.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -41,18 +41,25 @@
 import java.rmi.server.RMIServerSocketFactory;
 import java.rmi.server.RMIClientSocketFactory;
 import java.rmi.RemoteException;
-import gnu.java.rmi.server.UnicastConnection;
-import java.util.Hashtable;
-import java.net.Socket;
-import java.net.ServerSocket;
 import java.io.IOException;
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
+import java.io.DataInputStream;
 import java.lang.Thread;
 import java.lang.Runnable;
 import java.net.InetAddress;
+import java.net.Socket;
+import java.net.ServerSocket;
 import java.net.UnknownHostException;
 
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import gnu.java.rmi.server.UnicastConnection;
+
 public class UnicastConnectionManager
 	implements Runnable, ProtocolConstants {
 
@@ -60,15 +67,33 @@
 // use different maps for server/client type UnicastConnectionManager
 private static Hashtable servers = new Hashtable();
 private static Hashtable clients = new Hashtable();
+private ArrayList connections; //client connection pool
 
 // make serverThread volatile for poll
 private volatile Thread serverThread;
 private ServerSocket ssock;
 String serverName;
 int serverPort;
+
+static private Thread scavenger;
+
+// If client and server are in the same VM, serverobj represents server
+Object serverobj;
+
+private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
 private RMIServerSocketFactory serverFactory;
 private RMIClientSocketFactory clientFactory;
 
+// The following is for debug
+private static int ncsock = 0;    //count of client socket
+private static int nssock = 0;    //count of server socket
+private static int ncmanager = 0; //count of client manager
+private static int nsmanager = 0; //count of server manager
+
+private static final boolean debug = false;
+
+private static final Object GLOBAL_LOCK = new Object();
+
 static {
         try {
                 //Use host address instead of host name to avoid name resolving issues
@@ -78,16 +103,73 @@
         catch (UnknownHostException _) {
                 localhost = "localhost";
         }
+        
+        
+}
+
+//Only one scavenger thread running globally
+private static void startScavenger(){
+    scavenger = new Thread(new Runnable(){
+        public void run(){
+            if (debug) System.out.println("************* start scavenger.");
+            boolean liveon = true;
+            while (liveon){
+                // Sleep for the expire timeout
+                try{
+                    Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
+                }catch(InterruptedException _ie){
+                    break;
+                }
+                liveon = false;
+                // Scavenge all clients' connections that're expired
+                Iterator iter = clients.values().iterator();
+                long l = System.currentTimeMillis();
+                try{
+                    while(iter.hasNext()){
+                        UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
+                        ArrayList conns = man.connections;
+                        synchronized(conns) { // is the lock a little coarser?
+                            for (int last = conns.size() - 1;
+                                 last >= 0;
+                                 --last)
+                            {
+                                UnicastConnection conn = (UnicastConnection)conns.get(last);
+                                if (UnicastConnection.isExpired(conn, l)){
+                                    conns.remove(last);
+                                    conn.disconnect();
+                                    conn = null;   
+                                }else
+                                    liveon = true; //there're still live connections
+                            }
+                        }
+                    }
+                }catch(ConcurrentModificationException cme) {
+                    // handle it lazily
+                    liveon = true;
+                }
+            }
+            scavenger = null;
+            if (debug) System.out.println("************* exit scavenger.");
+        }
+    });
+    scavenger.start();
 }
 
+/**
+  * Client UnicastConnectionManager constructor
+  */
 private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
 	ssock = null;
 	serverName = host;
 	serverPort = port;
 	serverFactory = null;
 	clientFactory = csf;
+    connections = new ArrayList();
 }
 
+/**
+  * Server UnicastConnectionManager constructor
+  */
 private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
 	try {
 		ssock = ssf.createServerSocket(port);
@@ -115,7 +197,7 @@
 public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
 //System.out.println("getInstance: " + host + "," + port + "," + csf);
 	if (csf == null) {
-		csf = RMISocketFactory.getSocketFactory();
+        csf = defaultSocketFactory;
 	}
 	// change host name to host address to avoid name resolving issues
 	try{
@@ -126,7 +208,17 @@
 	UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
 	if (man == null) {
 		man = new UnicastConnectionManager(host, port, csf);
+        if (debug) {
+            ncmanager++;
+            System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
+        }
 		clients.put(key, man);
+        
+        // Detect if client and server are in the same VM, i.e., their keys are equal
+        UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
+        if(svrman != null){ // server and client are in the same VM
+            man.serverobj = svrman.serverobj;
+        }
 	}
 	return (man);
 }
@@ -138,12 +230,16 @@
 public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {
 //System.out.println("getInstance: " + port + "," + ssf);
 	if (ssf == null) {
-		ssf = RMISocketFactory.getSocketFactory();
+        ssf = defaultSocketFactory;
 	}
 	TripleKey key = new TripleKey(localhost, port, ssf);
 	UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
 	if (man == null) {
 		man = new UnicastConnectionManager(port, ssf);
+        if (debug) {
+            nsmanager++;
+            System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
+        }
 		// The provided port might not be the set port.
 		key.port = man.serverPort;
 		servers.put(key, man);
@@ -168,9 +264,14 @@
  */
 private UnicastConnection getServerConnection() throws IOException {
 	Socket sock = ssock.accept();
+    sock.setTcpNoDelay(true); //??
 	UnicastConnection conn = new UnicastConnection(this, sock);
 	conn.acceptConnection();
-//System.out.println("Server connection " + conn);
+    if (debug){
+        nssock++;
+        System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
+    }
+    //System.out.println("Server connection " + sock);
 	return (conn);
 }
 
@@ -178,10 +279,38 @@
  * Make a conection from this client to the server.
  */
 private UnicastConnection getClientConnection() throws IOException {
+    ArrayList conns = connections;
+    UnicastConnection conn;
+    
+    synchronized(conns) {
+        int nconn = conns.size() - 1;
+    
+        // if there're free connections in connection pool
+        if(nconn >= 0) {
+            conn = (UnicastConnection)conns.get(nconn);
+            //Should we check if conn is alive using Ping??
+            conns.remove(nconn);
+            
+            // Check if the connection is already expired
+            long l = System.currentTimeMillis();
+            if (!UnicastConnection.isExpired(conn, l)){
+                return conn;
+            }else {
+                conn.disconnect();
+                conn = null;   
+            }
+        }
+    }
+    
 	Socket sock = clientFactory.createSocket(serverName, serverPort);
-	UnicastConnection conn = new UnicastConnection(this, sock);
+    conn = new UnicastConnection(this, sock);
 	conn.makeConnection(DEFAULT_PROTOCOL);
-//System.out.println("Client connection " + conn);
+    
+    if (debug) {
+        ncsock++;
+        System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
+    }
+
 	return (conn);
 }
 
@@ -191,7 +320,19 @@
  */
 public void discardConnection(UnicastConnection conn) {
 //System.out.println("Discarding connection " + conn);
+    //conn.disconnect();
+    if (ssock != null) //server connection
 	conn.disconnect();
+    else {
+        // To client connection, we'd like to return back to pool
+        UnicastConnection.resetTime(conn);
+        //Ensure there're only one scavenger globally
+        synchronized(GLOBAL_LOCK) {
+            connections.add(conn); //borrow this lock to garantee thread safety 
+            if (scavenger == null)
+                startScavenger();
+        }
+    }
 }
 
 /**
@@ -204,6 +345,8 @@
 			return;
 		}
 		serverThread = new Thread(this);
+        // The following is not necessary when java.lang.Thread's constructor do this.
+        // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
 	}
 	serverThread.start();
 }
@@ -231,11 +374,11 @@
 //System.out.println("Waiting for connection on " + serverPort);
 			UnicastConnection conn = getServerConnection();
 			// use a thread pool to improve performance
-			// (new Thread(conn)).start();
-			ConnectionRunnerPool.dispatchConnection(conn);
+            //ConnectionRunnerPool.dispatchConnection(conn);
+            (new Thread(conn)).start();
 		}
 		catch (Exception e) {
-			// e.printStackTrace();
+            e.printStackTrace();
 		}
 	}
 }
@@ -254,8 +397,9 @@
 static UnicastConnectionManager read(ObjectInput in) throws IOException {
         String host = in.readUTF();
         int port = in.readInt();
-	RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
-        return (getInstance(host, port, csf));
+        //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
+        //return (getInstance(host, port, csf));
+        return (getInstance(host, port, null));
 }
 
 }
@@ -288,7 +432,7 @@
 		TripleKey other = (TripleKey)obj;
 		if (this.host.equals(other.host) &&
 		    this.other == other.other &&
-		    (this.port == other.port || this.port == 0 || other.port == 0)) {
+            (this.port == other.port /* || this.port == 0 || other.port == 0*/)) {
 			return (true);
 		}
 	}
Index: gnu/java/rmi/server/UnicastRef.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastRef.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastRef.java
--- gnu/java/rmi/server/UnicastRef.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/UnicastRef.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -62,6 +62,8 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 
+import java.lang.reflect.InvocationTargetException;
+
 public class UnicastRef
 	implements RemoteRef, ProtocolConstants {
 
@@ -69,9 +71,10 @@
 UnicastConnectionManager manager;
 
 /**
- * Used by serialization.
+ * Used by serialization, and let subclass capable of having default constructor
  */
-private UnicastRef() {
+//private 
+UnicastRef() {
 }
 
 public UnicastRef(ObjID objid, String host, int port, RMIClientSocketFactory csf) {
@@ -84,6 +87,21 @@
 }
 
 public Object invoke(Remote obj, Method method, Object[] params, long opnum) throws Exception {
+    // Check if client and server are in the same VM, then local call can be used to
+    // replace remote call, but it's somewhat violating remote semantic.
+    Object svrobj = manager.serverobj;
+    if(svrobj != null){
+        //local call
+		Object ret = null;
+		try{
+		    ret = method.invoke(svrobj, params);
+		}catch(InvocationTargetException e){
+		    throw (Exception)e.getTargetException();
+		}
+		//System.out.println("\n\n ***** local call: " + method + "\nreturn: " + ret + "\n\n");
+		return ret;
+	}
+	//System.out.println("***************** remote call:" + manager.serverPort);
 	return (invokeCommon(obj, method, params, -1, opnum));
 }
 
@@ -107,18 +125,7 @@
 		objid.write(out);
 		out.writeInt(opnum);
 		out.writeLong(hash);
-		/*
-		if (params != null) {
-			for (int i = 0; i < params.length; i++) {
-				if (params[i] instanceof UnicastRemoteObject) {
-					out.writeObject(UnicastRemoteObject.exportObject((UnicastRemoteObject)params[i]));
-				}
-				else {
-					out.writeObject(params[i]);
-				}
-			}
-		}
-		*/
+		
 		// must handle primitive class and their wrapper classes
 		Class clss[] = method.getParameterTypes();
 	    for(int i = 0; i < clss.length; i++)
@@ -137,26 +144,30 @@
 	UID ack;
 	try {
 		din = conn.getDataInputStream();
-		if (din.readUnsignedByte() != MESSAGE_CALL_ACK) {
-			throw new RemoteException("Call not acked");
+		
+		if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK) {
+		    conn.disconnect();
+			throw new RemoteException("Call not acked:" + returncode);
 		}
 
 		in = conn.getObjectInputStream();
-
 		returncode = in.readUnsignedByte();
 		ack = UID.read(in);
-		//returnval = in.readObject();
+
 		Class cls = method.getReturnType();
         if(cls == Void.TYPE){
             returnval = null;
+            in.readObject();
         }else
             returnval = ((RMIObjectInputStream)in).readValue(cls);
+
 	}
 	catch (IOException e3) {
+	    //for debug: e3.printStackTrace();
 		throw new RemoteException("call return failed: ", e3);
 	}
 
-    /* if DGCAck is necessary
+    /* if DGCAck is necessary??
     //According to RMI wire protocol, send a DGCAck 
     // to indicate receiving return value
     dout.writeByte(MESSAGE_DGCACK);
@@ -166,7 +177,7 @@
     
 	manager.discardConnection(conn);
 
-	if (returncode != RETURN_ACK) {
+	if (returncode != RETURN_ACK && returnval != null) {
 		throw (Exception)returnval;
 	}
 
@@ -177,7 +188,18 @@
  * @deprecated
  */
 public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash) throws RemoteException {
-	return (new UnicastRemoteCall(obj, opnum, hash));
+    UnicastConnection conn;
+    
+	try {
+		conn = manager.getConnection();
+	}
+	catch (IOException e1) {
+		throw new RemoteException("connection failed to host: " + manager.serverName, e1);
+	}
+
+    //obj: useless?
+
+	return (new UnicastRemoteCall(conn, objid, opnum, hash));
 }
 
 /**
@@ -185,15 +207,19 @@
  */
 public void invoke(RemoteCall call) throws Exception {
 	UnicastRemoteCall c = (UnicastRemoteCall)call;
-	Object ret = invokeCommon((Remote)c.getObject(), (Method)null, c.getArguments(), c.getOpnum(), c.getHash());
-	c.setReturnValue(ret);
+	call.executeCall();
 }
 
 /**
  * @deprecated
  */
 public void done(RemoteCall call) throws RemoteException {
-	/* Does nothing */
+	UnicastRemoteCall c = (UnicastRemoteCall)call;
+	try{
+	    c.done();
+	} catch(IOException e){}
+    UnicastConnection conn = c.getConnection();
+	manager.discardConnection(conn);
 }
 
 public void writeExternal(ObjectOutput out) throws IOException {
Index: gnu/java/rmi/server/UnicastRemoteCall.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastRemoteCall.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastRemoteCall.java
--- gnu/java/rmi/server/UnicastRemoteCall.java	14 Feb 2002 23:16:02 -0000	1.3
+++ gnu/java/rmi/server/UnicastRemoteCall.java	7 Nov 2002 15:46:13 -0000
@@ -38,14 +38,24 @@
 package gnu.java.rmi.server;
 
 import java.lang.Exception;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
 import java.io.StreamCorruptedException;
 import java.rmi.server.RemoteCall;
+import java.rmi.RemoteException;
+import java.rmi.MarshalException;
+import java.rmi.UnmarshalException;
+import java.rmi.server.UID;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteObject;
+
 import java.util.Vector;
 
-public class UnicastRemoteCall implements RemoteCall
+public class UnicastRemoteCall
+	implements RemoteCall, ProtocolConstants
 {
 
   private UnicastConnection conn;
@@ -56,6 +66,9 @@
   private Vector vec;
   private int ptr;
 
+  private ObjectOutput oout;
+  private ObjectInput oin;
+
   /**
    * Incoming call.
    */
@@ -67,30 +80,71 @@
   /**
    * Outgoing call.
    */
-  UnicastRemoteCall(Object obj, int opnum, long hash)
+  UnicastRemoteCall(UnicastConnection conn, ObjID objid, int opnum, long hash)
+    throws RemoteException
   {
-    this.object = obj;
+    this.conn = conn;
     this.opnum = opnum;
     this.hash = hash;
+    
+    // signal the call when constructing
+    try
+      {
+	DataOutputStream dout = conn.getDataOutputStream();
+	dout.write(MESSAGE_CALL);
+	
+	oout = conn.getObjectOutputStream();
+	objid.write(oout);
+	oout.writeInt(opnum);
+	oout.writeLong(hash);
+      }
+    catch(IOException ex)
+      {
+	throw new MarshalException("Try to write header but failed.", ex);
+      }
   }
-
+  
+  UnicastConnection getConnection()
+  {
+    return conn;
+  }
+  
   public ObjectOutput getOutputStream() throws IOException
   {
-    vec = new Vector();
-    return new DummyObjectOutputStream();
+    if (conn != null)
+      {
+	if(oout == null)
+	  return (oout = conn.getObjectOutputStream());
+	else
+	  return oout;
+      }
+    else
+      {
+	vec = new Vector();
+	return (new DummyObjectOutputStream());
+      }
   }
 
   public void releaseOutputStream() throws IOException
   {
-    // Does nothing.
+    if(oout != null)
+      oout.flush();
   }
 
   public ObjectInput getInputStream() throws IOException
   {
     if (conn != null)
-      return conn.getObjectInputStream();
-    ptr = 0;
-    return new DummyObjectInputStream();
+      {
+	if(oin == null)
+	  return (oin = conn.getObjectInputStream());
+	else
+	  return oin;
+      }
+    else
+      {
+	ptr = 0;
+	return (new DummyObjectInputStream());
+      }
   }
 
   public void releaseInputStream() throws IOException
@@ -104,15 +158,57 @@
     vec = new Vector();
     return new DummyObjectOutputStream();
   }
-
+  
   public void executeCall() throws Exception
   {
-    throw new Error("Not implemented");
+    byte returncode;
+    ObjectInput oin;
+    try
+      {
+	releaseOutputStream();
+	DataInputStream din = conn.getDataInputStream();
+        if (din.readByte() != MESSAGE_CALL_ACK)
+	    throw new RemoteException("Call not acked");
+
+        oin = getInputStream();
+        returncode = oin.readByte();
+        UID.read(oin);
+      }
+    catch(IOException ex)
+      {
+        throw new UnmarshalException("Try to read header but failed:", ex);
+      }
+    
+    //check return code
+    switch(returncode)
+      {
+      case RETURN_ACK: //it's ok
+	return;
+      case RETURN_NACK:
+	Object returnobj;
+	try
+	  {
+	    returnobj = oin.readObject();
+	  }
+	catch(Exception ex2)
+	  {
+	    throw new UnmarshalException
+	      ("Try to read exception object but failed", ex2);
+	  }
+	
+	if(!(returnobj instanceof Exception))
+	  throw new UnmarshalException("Should be Exception type here: "
+				       + returnobj);
+	throw (Exception)returnobj;
+	
+      default:
+	throw new UnmarshalException("Invalid return code");
+      }
   }
 
   public void done() throws IOException
   {
-    /* Does nothing */
+    // conn.disconnect();
   }
 
   Object returnValue()
Index: gnu/java/rmi/server/UnicastServer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastServer.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastServer.java
--- gnu/java/rmi/server/UnicastServer.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/UnicastServer.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -45,6 +45,7 @@
 import java.net.InetAddress;
 import java.util.Hashtable;
 import java.net.UnknownHostException;
+import java.rmi.Remote;
 import java.rmi.server.ObjID;
 import java.rmi.server.UnicastRemoteObject;
 import java.rmi.server.UID;
@@ -56,27 +57,36 @@
 public class UnicastServer
 	implements ProtocolConstants {
 
-static private Hashtable objects = new Hashtable();
+static private Hashtable objects = new Hashtable();  //mapping OBJID to server ref
+static private Hashtable refcache = new Hashtable(); //mapping obj itself to server ref
 static private DGCImpl dgc;
 
 public static void exportObject(UnicastServerRef obj) {
 	startDGC();
 	objects.put(obj.objid, obj);
+	refcache.put(obj.myself, obj);
 	obj.manager.startServer();
 }
 
 // FIX ME: I haven't handle force parameter
 public static boolean unexportObject(UnicastServerRef obj, boolean force) {
 	objects.remove(obj.objid);
+	refcache.remove(obj.myself);
 	obj.manager.stopServer();
 	return true;
 }
 
+public static UnicastServerRef getExportedRef(Remote remote){
+    return (UnicastServerRef)refcache.get(remote);
+}
+
 private static synchronized void startDGC() {
 	if (dgc == null) {
 		try {
 			dgc = new DGCImpl();
-			((UnicastServerRef)dgc.getRef()).exportObject(dgc);
+			// Changed DGCImpl to inherit UnicastServerRef directly
+			//((UnicastServerRef)dgc.getRef()).exportObject(dgc);
+			dgc.exportObject(dgc);
 		}
 		catch (RemoteException e) {
 			e.printStackTrace();
Index: gnu/java/rmi/server/UnicastServerRef.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/rmi/server/UnicastServerRef.java,v
retrieving revision 1.3
diff -u -r1.3 UnicastServerRef.java
--- gnu/java/rmi/server/UnicastServerRef.java	1 Oct 2002 03:46:42 -0000	1.3
+++ gnu/java/rmi/server/UnicastServerRef.java	7 Nov 2002 15:46:13 -0000
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+  Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -63,6 +63,8 @@
 import java.io.DataOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Hashtable;
 
 public class UnicastServerRef
@@ -71,11 +73,18 @@
 
 final static private Class[] stubprototype = new Class[] { RemoteRef.class };
 
-Remote myself;
+Remote myself; //save the remote object itself
 private Skeleton skel;
 private RemoteStub stub;
 private Hashtable methods = new Hashtable();
 
+/**
+ * Used by serialization.
+ */
+UnicastServerRef()
+{
+}
+
 public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
 	super(id);
 	manager = UnicastConnectionManager.getInstance(port, ssf);
@@ -84,6 +93,9 @@
 public RemoteStub exportObject(Remote obj) throws RemoteException {
 	if (myself == null) {
 		myself = obj;
+		// Save it to server manager, to let client calls in the same VM to issue
+		//  local call
+		manager.serverobj = obj;
 
 		// Find and install the stub
 		Class cls = obj.getClass();
@@ -110,6 +122,10 @@
 {
     //FIX ME
 	return exportObject(remote);
+}
+
+public RemoteStub getStub(){
+    return stub;
 }
 
 

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