diff options
Diffstat (limited to 'libjava/gnu')
-rw-r--r-- | libjava/gnu/java/rmi/RMIMarshalledObjectInputStream.java | 70 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java | 103 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/dgc/DGCImpl.java | 6 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/dgc/DGCImpl_Skel.java | 38 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/dgc/DGCImpl_Stub.java | 38 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/registry/RegistryImpl_Skel.java | 38 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java | 38 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/ConnectionRunnerPool.java | 154 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/RMIHashes.java | 48 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/RMIObjectInputStream.java | 84 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/RMIObjectOutputStream.java | 61 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastConnection.java | 30 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastConnectionManager.java | 40 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastRef.java | 28 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastServer.java | 16 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastServerRef.java | 53 |
16 files changed, 798 insertions, 47 deletions
diff --git a/libjava/gnu/java/rmi/RMIMarshalledObjectInputStream.java b/libjava/gnu/java/rmi/RMIMarshalledObjectInputStream.java new file mode 100644 index 00000000000..8835280a0e0 --- /dev/null +++ b/libjava/gnu/java/rmi/RMIMarshalledObjectInputStream.java @@ -0,0 +1,70 @@ +/* gnu.java.rmi.RMIMarshalledObjectInputStream + Copyright (C) 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; + +import gnu.java.rmi.server.RMIObjectInputStream; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.io.ByteArrayInputStream; + +/** + * This class is only for java.rmi.MarshalledObject to deserialize object from + * objBytes and locBytes + */ + +public class RMIMarshalledObjectInputStream extends RMIObjectInputStream +{ + private ObjectInputStream locStream; + + public RMIMarshalledObjectInputStream(byte[] objBytes, byte[] locBytes) throws IOException + { + super(new ByteArrayInputStream(objBytes)); + if(locBytes != null) + locStream = new ObjectInputStream(new ByteArrayInputStream(locBytes)); + } + + //This method overrides RMIObjectInputStream's + protected Object getAnnotation() throws IOException, ClassNotFoundException + { + if(locStream == null) + return null; + return locStream.readObject(); + } + +} // End of RMIMarshalledObjectInputStream diff --git a/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java b/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java new file mode 100644 index 00000000000..66392919868 --- /dev/null +++ b/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java @@ -0,0 +1,103 @@ +/* gnu.java.rmi.RMIMarshalledObjectOutputStream + Copyright (C) 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; + +import java.io.OutputStream; +import java.io.ObjectOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.rmi.Remote; +import java.rmi.server.ObjID; +import java.rmi.server.RemoteStub; + +import gnu.java.rmi.server.RMIObjectOutputStream; +import gnu.java.rmi.server.UnicastServerRef; + +/** + * This class is only for java.rmi.MarshalledObject to serialize object and + * got objBytes and locBytes + */ +public class RMIMarshalledObjectOutputStream extends RMIObjectOutputStream +{ + private ObjectOutputStream locStream; + private ByteArrayOutputStream locBytesStream; + + public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException + { + super(objStream); + } + + //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(); + } + + public byte[] getLocBytes(){ + if(locStream != null) + return locBytesStream.toByteArray(); + return null; + } + +} // End of RMIMarshalledObjectOutputStream + diff --git a/libjava/gnu/java/rmi/dgc/DGCImpl.java b/libjava/gnu/java/rmi/dgc/DGCImpl.java index adca54fda44..fba18c1715d 100644 --- a/libjava/gnu/java/rmi/dgc/DGCImpl.java +++ b/libjava/gnu/java/rmi/dgc/DGCImpl.java @@ -49,12 +49,16 @@ import gnu.java.rmi.server.UnicastServerRef; public class DGCImpl extends UnicastRemoteObject implements DGC { +private static final long leaseValue = 600000L; + public DGCImpl() throws RemoteException { super(new UnicastServerRef(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory())); } public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException { - System.out.println("DGCImpl.dirty - not implemented"); + VMID vmid = lease.getVMID(); + lease = new Lease(vmid, leaseValue); + System.out.println("DGCImpl.dirty - not completely implemented"); return (lease); } diff --git a/libjava/gnu/java/rmi/dgc/DGCImpl_Skel.java b/libjava/gnu/java/rmi/dgc/DGCImpl_Skel.java index fd0f2eec803..545ebc7bdea 100644 --- a/libjava/gnu/java/rmi/dgc/DGCImpl_Skel.java +++ b/libjava/gnu/java/rmi/dgc/DGCImpl_Skel.java @@ -1,3 +1,41 @@ +/* DGCImpl_Skel.java + Copyright (C) 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. */ + + // Skel class generated by rmic - DO NOT EDIT! package gnu.java.rmi.dgc; diff --git a/libjava/gnu/java/rmi/dgc/DGCImpl_Stub.java b/libjava/gnu/java/rmi/dgc/DGCImpl_Stub.java index e611fb227eb..bffde5280cd 100644 --- a/libjava/gnu/java/rmi/dgc/DGCImpl_Stub.java +++ b/libjava/gnu/java/rmi/dgc/DGCImpl_Stub.java @@ -1,3 +1,41 @@ +/* DGCImpl_Stub.java + Copyright (C) 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. */ + + // Stub class generated by rmic - DO NOT EDIT! package gnu.java.rmi.dgc; diff --git a/libjava/gnu/java/rmi/registry/RegistryImpl_Skel.java b/libjava/gnu/java/rmi/registry/RegistryImpl_Skel.java index 7ba41c389cb..de6b9e42604 100644 --- a/libjava/gnu/java/rmi/registry/RegistryImpl_Skel.java +++ b/libjava/gnu/java/rmi/registry/RegistryImpl_Skel.java @@ -1,3 +1,41 @@ +/* RegistryImpl_Skel.java + Copyright (C) 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. */ + + // Skel class generated by rmic - DO NOT EDIT! package gnu.java.rmi.registry; diff --git a/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java b/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java index bfa755c3fdb..33cb06a4b68 100644 --- a/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java +++ b/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java @@ -1,3 +1,41 @@ +/* RegistryImpl_Stub.java + Copyright (C) 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. */ + + // Stub class generated by rmic - DO NOT EDIT! package gnu.java.rmi.registry; diff --git a/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java b/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java new file mode 100644 index 00000000000..df6363bdcb6 --- /dev/null +++ b/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java @@ -0,0 +1,154 @@ +/* gnu.java.rmi.server.ConnectionRunnerPool + Copyright (C) 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; + +import java.util.ArrayList; +import java.util.Arrays; + +//Should I generalize this class? + +class ConnectionRunnerPool +{ + + public static + class ConnectionRunner extends Thread{ + private UnicastConnection conn; + private volatile boolean exiting = false; + + public ConnectionRunner(ThreadGroup group, String id){ + super(group, id); + } + + public synchronized void run(){ + while(!exiting){ + if(conn == null) + try{ + wait(); + }catch(InterruptedException e){ + continue; + } + else{ + conn.run(); + conn = null; + synchronized(ConnectionRunnerPool.class){ + freelist.add(this); + if(freelist.size() == 1) + ConnectionRunnerPool.class.notifyAll(); + } + } + } + } + + public synchronized void dispatch(UnicastConnection conn){ + this.conn = conn; + notify(); + } + + void exit(){ + exiting = true; + if(conn != null) + try{ + join(500); + }catch(InterruptedException e){} + interrupt(); + } + + } + + private static int size = 5; + private static int max_size = 10; + + private static ArrayList freelist; + + private static ThreadGroup group = new ThreadGroup("pool"); + + static { + ConnectionRunner[] pools = new ConnectionRunner[size]; + for(int i = 0; i < pools.length; i++){ + pools[i] = new ConnectionRunner(group, new Integer(i).toString()); + pools[i].setContextClassLoader(Thread.currentThread().getContextClassLoader()); + pools[i].start(); + } + freelist = new ArrayList(Arrays.asList(pools)); + } + + public static void setSize(int size_){ + size = size_; + } + + public static void setMaxSize(int size){ + max_size = size; + } + + private synchronized static ConnectionRunner getConnectionRunner() + { + if(freelist.size() == 0){ + if(size < max_size){ + ++size; + ConnectionRunner a = new ConnectionRunner(group, new Integer(size).toString()); + a.start(); + freelist.add(a); + }else + while(freelist.size() == 0) + try{ + ConnectionRunnerPool.class.wait(); + }catch(InterruptedException e){} + } + + // always let the first in pool most busy or other scheduling plan?? + ConnectionRunner a = (ConnectionRunner)freelist.get(0); + freelist.remove(a); + return a; + } + + public static void dispatchConnection(UnicastConnection conn) + { + ConnectionRunner r = getConnectionRunner(); + r.dispatch(conn); + } + + public static void exit() + { + Thread[] list = new Thread[group.activeCount()]; + group.enumerate(list); + for(int i = 0; i < list.length; i++) + ((ConnectionRunner)list[i]).exit(); + } + +} diff --git a/libjava/gnu/java/rmi/server/RMIHashes.java b/libjava/gnu/java/rmi/server/RMIHashes.java index 993e5bf1d2b..6e32724d50a 100644 --- a/libjava/gnu/java/rmi/server/RMIHashes.java +++ b/libjava/gnu/java/rmi/server/RMIHashes.java @@ -39,13 +39,56 @@ package gnu.java.rmi.server; import java.lang.reflect.Method; import java.lang.Class; -import gnu.java.security.provider.SHA; +import gnu.java.io.NullOutputStream; +import gnu.java.lang.reflect.TypeSignature; +import java.security.MessageDigest; +import java.security.DigestOutputStream; +import java.io.DataOutputStream; +import java.io.ByteArrayOutputStream; public class RMIHashes { + //There're other places using DigestOutputStream to generate hash in classpath, but I think the way I used + //here is more efficient, anyway, you can switch to DigestOutputStream by doing like "//or:" comments say. + + //or:add this statement: private static final NullOutputStream nullOutputStream = new NullOutputStream (); public static long getMethodHash(Method meth) { - return meth.hashCode (); + //Object Serialization Spec 8.3 + try + { + MessageDigest md = MessageDigest.getInstance ("SHA"); + //or:remove this statement: DigestOutputStream digest_out = new DigestOutputStream (nullOutputStream, md); + ByteArrayOutputStream digest_out = new ByteArrayOutputStream(); + DataOutputStream data_out = new DataOutputStream (digest_out); + + StringBuffer sbuf = new StringBuffer(); + sbuf.append(meth.getName()); + sbuf.append('('); + Class params[] = meth.getParameterTypes(); + for(int i = 0; i < params.length; i++) + sbuf.append(TypeSignature.getEncodingOfClass(params[i])); + sbuf.append(')'); + Class rcls = meth.getReturnType(); + if(rcls != Void.TYPE) + sbuf.append(TypeSignature.getEncodingOfClass(rcls)); + else + sbuf.append('V'); + + data_out.writeUTF (sbuf.toString()); + data_out.flush(); + data_out.close (); + + md.update(digest_out.toByteArray()); //or:remove this statement + byte[] sha = md.digest (); + long result = 0; + int len = sha.length < 8 ? sha.length : 8; + for (int i=0; i < len; i++) + result += (long)(sha[i] & 0xFF) << (8 * i); + return result; + }catch(Exception _){ + return -1L; + } } public static long getInterfaceHash(Class clazz) @@ -53,3 +96,4 @@ public class RMIHashes return clazz.hashCode (); } } + diff --git a/libjava/gnu/java/rmi/server/RMIObjectInputStream.java b/libjava/gnu/java/rmi/server/RMIObjectInputStream.java index 70b6c53c304..5913e9221bf 100644 --- a/libjava/gnu/java/rmi/server/RMIObjectInputStream.java +++ b/libjava/gnu/java/rmi/server/RMIObjectInputStream.java @@ -44,6 +44,8 @@ import java.io.IOException; import java.net.URL; import java.net.MalformedURLException; import java.rmi.server.RMIClassLoader; +import java.lang.ClassNotFoundException; +import java.lang.reflect.Proxy; public class RMIObjectInputStream extends ObjectInputStream { @@ -56,20 +58,80 @@ public RMIObjectInputStream(InputStream strm, UnicastConnectionManager man) thro enableResolveObject(true); } +public RMIObjectInputStream(InputStream strm) throws IOException { + this(strm, UnicastConnectionManager.getInstance(0, null)); +} + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { -//System.out.println("Resolving class: " + desc.getName()); - String annotation = (String)readObject(); - if (annotation == null) { - return (super.resolveClass(desc)); + String annotation = (String)getAnnotation(); + try{ + return super.resolveClass(desc); + }catch(ClassNotFoundException _){}; + + try { + if(annotation == null) + return (RMIClassLoader.loadClass(desc.getName())); + else + return (RMIClassLoader.loadClass(annotation, desc.getName())); } - else { - try { - return (RMIClassLoader.loadClass(new URL(annotation), desc.getName())); - } - catch (MalformedURLException _) { - throw new ClassNotFoundException(desc.getName()); - } + catch (MalformedURLException _) { + throw new ClassNotFoundException(desc.getName()); } } +//Separate it for override by MarshalledObject +protected Object getAnnotation() + throws IOException, ClassNotFoundException +{ + return readObject(); +} + +protected Class resolveProxyClass(String intfs[]) + 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]); + return Proxy.getProxyClass(loader, clss); +} + +protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException { + if(valueClass.isPrimitive()){ + if(valueClass == Boolean.TYPE) + return new Boolean(readBoolean()); + if(valueClass == Byte.TYPE) + return new Byte(readByte()); + if(valueClass == Character.TYPE) + return new Character(readChar()); + if(valueClass == Short.TYPE) + return new Short(readShort()); + if(valueClass == Integer.TYPE) + return new Integer(readInt()); + if(valueClass == Long.TYPE) + return new Long(readLong()); + if(valueClass == Float.TYPE) + return new Float(readFloat()); + if(valueClass == Double.TYPE) + return new Double(readDouble()); + else + throw new Error("Unsupported primitive class: " + valueClass); + } else + return readObject(); } + +}
\ No newline at end of file diff --git a/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java b/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java index d729047b487..71a2bac9ded 100644 --- a/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java +++ b/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java @@ -41,17 +41,74 @@ import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.IOException; import java.rmi.server.RMIClassLoader; +import java.rmi.Remote; +import java.rmi.server.RemoteStub; +import java.rmi.server.ObjID; public class RMIObjectOutputStream extends ObjectOutputStream { public RMIObjectOutputStream(OutputStream strm) throws IOException { super(strm); + enableReplaceObject(true); +} + +//Separate it for override by MarshalledObject +protected void setAnnotation(String annotation) throws IOException{ + writeObject(annotation); } protected void annotateClass(Class cls) throws IOException { -//System.out.println("Annotating class: " + cls); - writeObject(RMIClassLoader.getClassAnnotation(cls)); + setAnnotation(RMIClassLoader.getClassAnnotation(cls)); +} + +protected void annotateProxyClass(Class cls) + throws IOException +{ + annotateClass(cls); +} + +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; +} + +protected void writeValue(Object value, Class valueClass) throws IOException{ + if(valueClass.isPrimitive()){ + if(valueClass == Boolean.TYPE) + writeBoolean(((Boolean)value).booleanValue()); + else + if(valueClass == Byte.TYPE) + writeByte(((Byte)value).byteValue()); + else + if(valueClass == Character.TYPE) + writeChar(((Character)value).charValue()); + else + if(valueClass == Short.TYPE) + writeShort(((Short)value).shortValue()); + else + if(valueClass == Integer.TYPE) + writeInt(((Integer)value).intValue()); + else + if(valueClass == Long.TYPE) + writeLong(((Long)value).longValue()); + else + if(valueClass == Float.TYPE) + writeFloat(((Float)value).floatValue()); + else + if(valueClass == Double.TYPE) + writeDouble(((Double)value).doubleValue()); + else + throw new Error("Unsupported primitive class: " + valueClass); + } else + writeObject(value); } } diff --git a/libjava/gnu/java/rmi/server/UnicastConnection.java b/libjava/gnu/java/rmi/server/UnicastConnection.java index a8951656024..e13bb686229 100644 --- a/libjava/gnu/java/rmi/server/UnicastConnection.java +++ b/libjava/gnu/java/rmi/server/UnicastConnection.java @@ -44,6 +44,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.ObjectOutput; import java.io.ObjectInput; import java.io.IOException; @@ -65,9 +67,10 @@ UnicastConnection(UnicastConnectionManager man, Socket sock) { } void acceptConnection() throws IOException { -//System.out.println("Accepting connection on " + lport); - din = new DataInputStream(sock.getInputStream()); - dout = new DataOutputStream(sock.getOutputStream()); +//System.out.println("Accepting connection on " + sock); + //Use BufferedXXXStream would be more efficient + din = new DataInputStream(new BufferedInputStream(sock.getInputStream())); + dout = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream())); int sig = din.readInt(); if (sig != PROTOCOL_HEADER) { @@ -85,6 +88,7 @@ void acceptConnection() throws IOException { // Send my hostname and port dout.writeUTF(manager.serverName); dout.writeInt(manager.serverPort); + dout.flush(); // Read their hostname and port String rhost = din.readUTF(); @@ -94,15 +98,16 @@ void acceptConnection() throws IOException { } void makeConnection(int protocol) throws IOException { - dout = new DataOutputStream(sock.getOutputStream()); - din = new DataInputStream(sock.getInputStream()); + //Use BufferedXXXStream would be more efficient + din = new DataInputStream(new BufferedInputStream(sock.getInputStream())); + dout = new DataOutputStream(new BufferedOutputStream(sock.getOutputStream())); // Send header dout.writeInt(PROTOCOL_HEADER); dout.writeShort(PROTOCOL_VERSION); dout.writeByte(protocol); - dout.flush(); - + dout.flush(); + if (protocol != SINGLE_OP_PROTOCOL) { // Get back ack. int ack = din.readUnsignedByte(); @@ -117,6 +122,7 @@ void makeConnection(int protocol) throws IOException { // Send them my endpoint dout.writeUTF(manager.serverName); dout.writeInt(manager.serverPort); + dout.flush(); } // Okay, ready to roll ... } @@ -144,13 +150,15 @@ ObjectOutputStream getObjectOutputStream() throws IOException { } void disconnect() { - oin = null; - oout = null; try { - sock.close(); + if(oout != null) + oout.close(); } catch (IOException _) { - } + } + + oin = null; + oout = null; din = null; dout = null; sock = null; diff --git a/libjava/gnu/java/rmi/server/UnicastConnectionManager.java b/libjava/gnu/java/rmi/server/UnicastConnectionManager.java index fe08ad0814d..64fecdce2a0 100644 --- a/libjava/gnu/java/rmi/server/UnicastConnectionManager.java +++ b/libjava/gnu/java/rmi/server/UnicastConnectionManager.java @@ -57,9 +57,12 @@ public class UnicastConnectionManager implements Runnable, ProtocolConstants { private static String localhost; +// use different maps for server/client type UnicastConnectionManager private static Hashtable servers = new Hashtable(); +private static Hashtable clients = new Hashtable(); -private Thread serverThread; +// make serverThread volatile for poll +private volatile Thread serverThread; private ServerSocket ssock; String serverName; int serverPort; @@ -68,7 +71,9 @@ private RMIClientSocketFactory clientFactory; static { try { - localhost = InetAddress.getLocalHost().getHostName(); + //Use host address instead of host name to avoid name resolving issues + //localhost = InetAddress.getLocalHost().getHostName(); + localhost = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException _) { localhost = "localhost"; @@ -112,11 +117,16 @@ public static synchronized UnicastConnectionManager getInstance(String host, int if (csf == null) { csf = RMISocketFactory.getSocketFactory(); } + // change host name to host address to avoid name resolving issues + try{ + host = InetAddress.getByName(host).getHostAddress(); + }catch(Exception _){} + TripleKey key = new TripleKey(host, port, csf); - UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key); + UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key); if (man == null) { man = new UnicastConnectionManager(host, port, csf); - servers.put(key, man); + clients.put(key, man); } return (man); } @@ -199,17 +209,33 @@ public void startServer() { } /** + * Stop a server on this manager + */ +public void stopServer() { + synchronized(this) { + if(serverThread != null){ + serverThread = null; + try{ + ssock.close(); + }catch(Exception _){} + } + } +} + +/** * Server thread for connection manager. */ public void run() { - for (;;) { + for (;serverThread != null;) { // if serverThread==null, then exit thread try { //System.out.println("Waiting for connection on " + serverPort); UnicastConnection conn = getServerConnection(); - (new Thread(conn)).start(); + // use a thread pool to improve performance + // (new Thread(conn)).start(); + ConnectionRunnerPool.dispatchConnection(conn); } catch (Exception e) { - e.printStackTrace(); + // e.printStackTrace(); } } } diff --git a/libjava/gnu/java/rmi/server/UnicastRef.java b/libjava/gnu/java/rmi/server/UnicastRef.java index 1c5bf577ed9..d6cda49c600 100644 --- a/libjava/gnu/java/rmi/server/UnicastRef.java +++ b/libjava/gnu/java/rmi/server/UnicastRef.java @@ -107,6 +107,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu 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) { @@ -117,6 +118,11 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu } } } + */ + // must handle primitive class and their wrapper classes + Class clss[] = method.getParameterTypes(); + for(int i = 0; i < clss.length; i++) + ((RMIObjectOutputStream)out).writeValue(params[i], clss[i]); out.flush(); } @@ -139,12 +145,25 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu returncode = in.readUnsignedByte(); ack = UID.read(in); - returnval = in.readObject(); + //returnval = in.readObject(); + Class cls = method.getReturnType(); + if(cls == Void.TYPE){ + returnval = null; + }else + returnval = ((RMIObjectInputStream)in).readValue(cls); } catch (IOException e3) { throw new RemoteException("call return failed: ", e3); } + /* if DGCAck is necessary + //According to RMI wire protocol, send a DGCAck + // to indicate receiving return value + dout.writeByte(MESSAGE_DGCACK); + ack.write(dout); + out.flush(); + */ + manager.discardConnection(conn); if (returncode != RETURN_ACK) { @@ -183,13 +202,16 @@ public void writeExternal(ObjectOutput out) throws IOException { } manager.write(out); objid.write(out); - out.writeByte(RETURN_ACK); + // This byte is somewhat confusing when interoperating with JDK + out.writeByte(0); //RETURN_ACK); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { manager = UnicastConnectionManager.read(in); objid = ObjID.read(in); - if (in.readByte() != RETURN_ACK) { + byte ack = in.readByte(); + // This byte is somewhat confusing when interoperating with JDK + if (ack != RETURN_ACK && ack != 0/*jdk ack value*/) { throw new IOException("no ack found"); } } diff --git a/libjava/gnu/java/rmi/server/UnicastServer.java b/libjava/gnu/java/rmi/server/UnicastServer.java index d9f5fb71527..15c622f48bc 100644 --- a/libjava/gnu/java/rmi/server/UnicastServer.java +++ b/libjava/gnu/java/rmi/server/UnicastServer.java @@ -65,6 +65,13 @@ public static void exportObject(UnicastServerRef obj) { obj.manager.startServer(); } +// FIX ME: I haven't handle force parameter +public static boolean unexportObject(UnicastServerRef obj, boolean force) { + objects.remove(obj.objid); + obj.manager.stopServer(); + return true; +} + private static synchronized void startDGC() { if (dgc == null) { try { @@ -100,10 +107,14 @@ private static void incomingMessageCall(UnicastConnection conn) throws IOExcepti UnicastServerRef uref = (UnicastServerRef)objects.get(objid); Object returnval; int returncode = RETURN_ACK; + // returnval is from Method.invoke(), so we must check the return class to see + // if it's primitive type + Class returncls = null; if (uref != null) { try { // Dispatch the call to it. returnval = uref.incomingMessageCall(conn, method, hash); + returncls = uref.getMethodReturnType(method, hash); } catch (Exception e) { returnval = e; @@ -121,7 +132,10 @@ private static void incomingMessageCall(UnicastConnection conn) throws IOExcepti out.writeByte(returncode); (new UID()).write(out); - out.writeObject(returnval); + if(returnval != null && returncls != null) + ((RMIObjectOutputStream)out).writeValue(returnval, returncls); + else + out.writeObject(returnval); out.flush(); } diff --git a/libjava/gnu/java/rmi/server/UnicastServerRef.java b/libjava/gnu/java/rmi/server/UnicastServerRef.java index b145089e600..196f969d292 100644 --- a/libjava/gnu/java/rmi/server/UnicastServerRef.java +++ b/libjava/gnu/java/rmi/server/UnicastServerRef.java @@ -66,14 +66,15 @@ import java.io.ObjectOutputStream; import java.util.Hashtable; public class UnicastServerRef - extends UnicastRef { + extends UnicastRef + implements ServerRef{ //SHOULD implement ServerRef final static private Class[] stubprototype = new Class[] { RemoteRef.class }; Remote myself; private Skeleton skel; private RemoteStub stub; -private Hashtable methods; +private Hashtable methods = new Hashtable(); public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) { super(id); @@ -95,7 +96,7 @@ public RemoteStub exportObject(Remote obj) throws RemoteException { skel = (Skeleton)getHelperClass(cls, "_Skel"); // Build hash of methods which may be called. - buildMethodHash(obj.getClass()); + buildMethodHash(obj.getClass(), true); // Export it. UnicastServer.exportObject(this); @@ -104,10 +105,25 @@ public RemoteStub exportObject(Remote obj) throws RemoteException { return (stub); } +public RemoteStub exportObject(Remote remote, Object obj) + throws RemoteException +{ + //FIX ME + return exportObject(remote); +} + + +public boolean unexportObject(Remote obj, boolean force) throws RemoteException { + // Remove all hashes of methods which may be called. + buildMethodHash(obj.getClass(), false); + return UnicastServer.unexportObject(this, force); +} + private Object getHelperClass(Class cls, String type) { try { - String classname = cls.getName(); - Class scls = Class.forName(classname + type); + String classname = cls.getName(); + ClassLoader cl = cls.getClassLoader(); //DONT use "Class scls = Class.forName(classname + type);" + Class scls = cl.loadClass(classname + type); if (type.equals("_Stub")) { try { // JDK 1.2 stubs @@ -147,8 +163,7 @@ public String getClientHost() throws ServerNotActiveException { throw new Error("Not implemented"); } -private void buildMethodHash(Class cls) { - methods = new Hashtable(); +private void buildMethodHash(Class cls, boolean build) { Method[] meths = cls.getMethods(); for (int i = 0; i < meths.length; i++) { /* Don't need to include any java.xxx related stuff */ @@ -156,11 +171,23 @@ private void buildMethodHash(Class cls) { continue; } long hash = RMIHashes.getMethodHash(meths[i]); - methods.put(new Long (hash), meths[i]); + if(build) + methods.put(new Long (hash), meths[i]); + else + methods.remove(new Long (hash)); //System.out.println("meth = " + meths[i] + ", hash = " + hash); } } +Class getMethodReturnType(int method, long hash) throws Exception +{ + if (method == -1) { + Method meth = (Method)methods.get(new Long (hash)); + return meth.getReturnType(); + }else + return null; +} + public Object incomingMessageCall(UnicastConnection conn, int method, long hash) throws Exception { //System.out.println("method = " + method + ", hash = " + hash); // If method is -1 then this is JDK 1.2 RMI - so use the hash @@ -189,7 +216,15 @@ public Object incomingMessageCall(UnicastConnection conn, int method, long hash) throw t; } } - return (meth.invoke(myself, args)); + //We must reinterpret the exception thrown by meth.invoke() + //return (meth.invoke(myself, args)); + Object ret = null; + try{ + ret = meth.invoke(myself, args); + }catch(InvocationTargetException e){ + throw (Exception)(e.getTargetException()); + } + return ret; } // Otherwise this is JDK 1.1 style RMI - we find the skeleton // and invoke it using the method number. We wrap up our |