backport: MarshalledObject.java (equals): Check hashcode first.
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. From-SVN: r58900
This commit is contained in:
parent
396a80436c
commit
f150fe3fa7
18 changed files with 601 additions and 200 deletions
|
@ -1,3 +1,53 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2002-11-07 Mark Wielaard <mark@klomp.org>
|
2002-11-07 Mark Wielaard <mark@klomp.org>
|
||||||
|
|
||||||
* java/lang/reflect/natField.cc (getBoolean): Use getType().
|
* java/lang/reflect/natField.cc (getBoolean): Use getType().
|
||||||
|
|
|
@ -61,42 +61,22 @@ public class RMIMarshalledObjectOutputStream extends RMIObjectOutputStream
|
||||||
public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException
|
public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException
|
||||||
{
|
{
|
||||||
super(objStream);
|
super(objStream);
|
||||||
|
locBytesStream = new ByteArrayOutputStream(256);
|
||||||
|
locStream = new ObjectOutputStream(locBytesStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
//This method overrides RMIObjectOutputStream's.
|
//This method overrides RMIObjectOutputStream's.
|
||||||
protected void setAnnotation(String annotation) throws IOException{
|
protected void setAnnotation(String annotation) throws IOException{
|
||||||
synchronized(this){
|
|
||||||
if(locStream == null){
|
|
||||||
locBytesStream = new ByteArrayOutputStream();
|
|
||||||
locStream = new ObjectOutputStream(locBytesStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locStream.writeObject(annotation);
|
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 {
|
public void flush() throws IOException {
|
||||||
super.flush();
|
super.flush();
|
||||||
if(locStream != null)
|
locStream.flush();
|
||||||
locStream.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getLocBytes(){
|
public byte[] getLocBytes(){
|
||||||
if(locStream != null)
|
return locBytesStream.toByteArray();
|
||||||
return locBytesStream.toByteArray();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of RMIMarshalledObjectOutputStream
|
} // End of RMIMarshalledObjectOutputStream
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -46,24 +46,73 @@ import java.rmi.server.UnicastRemoteObject;
|
||||||
import java.rmi.server.RMISocketFactory;
|
import java.rmi.server.RMISocketFactory;
|
||||||
import gnu.java.rmi.server.UnicastServerRef;
|
import gnu.java.rmi.server.UnicastServerRef;
|
||||||
|
|
||||||
public class DGCImpl
|
import java.util.Hashtable;
|
||||||
extends UnicastRemoteObject implements DGC {
|
|
||||||
|
|
||||||
private static final long leaseValue = 600000L;
|
/**
|
||||||
|
* I let DGCImpl to extend UnicastServerRef, but not
|
||||||
|
* UnicastRemoteObject, because UnicastRemoteObject must
|
||||||
|
* exportObject automatically.
|
||||||
|
*/
|
||||||
|
public class DGCImpl
|
||||||
|
extends UnicastServerRef implements DGC {
|
||||||
|
|
||||||
|
private static final long LEASE_VALUE = 600000L;
|
||||||
|
// leaseCache caches a LeaseRecord associated with a vmid
|
||||||
|
private Hashtable leaseCache = new Hashtable();
|
||||||
|
|
||||||
public DGCImpl() throws RemoteException {
|
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 {
|
public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException {
|
||||||
VMID vmid = lease.getVMID();
|
VMID vmid = lease.getVMID();
|
||||||
|
if (vmid == null)
|
||||||
|
vmid = new VMID();
|
||||||
|
long leaseValue = LEASE_VALUE;
|
||||||
|
//long leaseValue = lease.getValue();
|
||||||
lease = new Lease(vmid, leaseValue);
|
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);
|
return (lease);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong) throws RemoteException {
|
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
|
||||||
|
|
|
@ -64,7 +64,8 @@ public RegistryImpl(int port) throws RemoteException {
|
||||||
|
|
||||||
public RegistryImpl(int port, RMIClientSocketFactory cf, RMIServerSocketFactory sf) throws RemoteException {
|
public RegistryImpl(int port, RMIClientSocketFactory cf, RMIServerSocketFactory sf) throws RemoteException {
|
||||||
super(new UnicastServerRef(new ObjID(ObjID.REGISTRY_ID), port, sf));
|
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 {
|
public Remote lookup(String name) throws RemoteException, NotBoundException, AccessException {
|
||||||
|
|
|
@ -67,7 +67,7 @@ public final class RegistryImpl_Stub
|
||||||
static {
|
static {
|
||||||
try {
|
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 });
|
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_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_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});
|
$method_lookup_2 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("lookup", new java.lang.Class[] {java.lang.String.class});
|
||||||
|
|
|
@ -91,6 +91,7 @@ class ConnectionRunnerPool
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should this value equal to number of CPU?
|
||||||
private static int size = 5;
|
private static int size = 5;
|
||||||
private static int max_size = 10;
|
private static int max_size = 10;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -50,23 +50,13 @@ import java.lang.reflect.Proxy;
|
||||||
public class RMIObjectInputStream
|
public class RMIObjectInputStream
|
||||||
extends ObjectInputStream {
|
extends ObjectInputStream {
|
||||||
|
|
||||||
UnicastConnectionManager manager;
|
|
||||||
|
|
||||||
public RMIObjectInputStream(InputStream strm, UnicastConnectionManager man) throws IOException {
|
|
||||||
super(strm);
|
|
||||||
manager = man;
|
|
||||||
enableResolveObject(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RMIObjectInputStream(InputStream strm) throws IOException {
|
public RMIObjectInputStream(InputStream strm) throws IOException {
|
||||||
this(strm, UnicastConnectionManager.getInstance(0, null));
|
super(strm);
|
||||||
|
enableResolveObject(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||||
String annotation = (String)getAnnotation();
|
String annotation = (String)getAnnotation();
|
||||||
try{
|
|
||||||
return super.resolveClass(desc);
|
|
||||||
}catch(ClassNotFoundException _){};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(annotation == null)
|
if(annotation == null)
|
||||||
|
@ -90,24 +80,23 @@ protected Class resolveProxyClass(String intfs[])
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
String annotation = (String)getAnnotation();
|
String annotation = (String)getAnnotation();
|
||||||
try{
|
|
||||||
return super.resolveProxyClass(intfs);
|
|
||||||
}catch(ClassNotFoundException _){};
|
|
||||||
|
|
||||||
Class clss[] = new Class[intfs.length];
|
Class clss[] = new Class[intfs.length];
|
||||||
if(annotation == null)
|
if(annotation == null)
|
||||||
clss[0] = RMIClassLoader.loadClass(intfs[0]);
|
clss[0] = RMIClassLoader.loadClass(intfs[0]);
|
||||||
else
|
else
|
||||||
clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]);
|
clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]);
|
||||||
|
|
||||||
//assume all interfaces can be loaded by the same classloader
|
//assume all interfaces can be loaded by the same classloader
|
||||||
ClassLoader loader = clss[0].getClassLoader();
|
ClassLoader loader = clss[0].getClassLoader();
|
||||||
if(loader == null)
|
for (int i = 0; i < intfs.length; i++)
|
||||||
for(int i = 1; i < intfs.length; i++)
|
clss[i] = Class.forName(intfs[i], false, loader);
|
||||||
clss[i] = Class.forName(intfs[i]);
|
|
||||||
else
|
try {
|
||||||
for(int i = 1; i < intfs.length; i++)
|
|
||||||
clss[i] = loader.loadClass(intfs[i]);
|
|
||||||
return Proxy.getProxyClass(loader, clss);
|
return Proxy.getProxyClass(loader, clss);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ClassNotFoundException(null, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException {
|
protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException {
|
||||||
|
@ -134,4 +123,4 @@ protected Object readValue(Class valueClass) throws IOException, ClassNotFoundEx
|
||||||
return readObject();
|
return readObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -72,10 +72,9 @@ protected Object replaceObject(Object obj)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if((obj instanceof Remote) && !(obj instanceof RemoteStub)){
|
if((obj instanceof Remote) && !(obj instanceof RemoteStub)){
|
||||||
UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null);
|
UnicastServerRef ref = UnicastServer.getExportedRef((Remote)obj);
|
||||||
try{
|
if (ref != null)
|
||||||
return ref.exportObject((Remote)obj);
|
return ref.getStub();
|
||||||
}catch(Exception e){}
|
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ DataOutputStream dout;
|
||||||
ObjectInputStream oin;
|
ObjectInputStream oin;
|
||||||
ObjectOutputStream oout;
|
ObjectOutputStream oout;
|
||||||
|
|
||||||
|
// reviveTime and expireTime make UnicastConnection pool-able
|
||||||
|
long reviveTime = 0;
|
||||||
|
long expireTime = Long.MAX_VALUE;
|
||||||
|
|
||||||
UnicastConnection(UnicastConnectionManager man, Socket sock) {
|
UnicastConnection(UnicastConnectionManager man, Socket sock) {
|
||||||
this.manager = man;
|
this.manager = man;
|
||||||
this.sock = sock;
|
this.sock = sock;
|
||||||
|
@ -137,7 +141,7 @@ DataOutputStream getDataOutputStream() throws IOException {
|
||||||
|
|
||||||
ObjectInputStream getObjectInputStream() throws IOException {
|
ObjectInputStream getObjectInputStream() throws IOException {
|
||||||
if (oin == null) {
|
if (oin == null) {
|
||||||
oin = new RMIObjectInputStream(din, manager);
|
oin = new RMIObjectInputStream(din);
|
||||||
}
|
}
|
||||||
return (oin);
|
return (oin);
|
||||||
}
|
}
|
||||||
|
@ -153,6 +157,7 @@ void disconnect() {
|
||||||
try {
|
try {
|
||||||
if(oout != null)
|
if(oout != null)
|
||||||
oout.close();
|
oout.close();
|
||||||
|
sock.close();
|
||||||
}
|
}
|
||||||
catch (IOException _) {
|
catch (IOException _) {
|
||||||
}
|
}
|
||||||
|
@ -164,17 +169,35 @@ void disconnect() {
|
||||||
sock = null;
|
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.
|
* We run connects on the server. Dispatch it then discard it.
|
||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
|
do{
|
||||||
try {
|
try {
|
||||||
UnicastServer.dispatch(this);
|
UnicastServer.dispatch(this);
|
||||||
|
//don't discardConnection explicitly, only when
|
||||||
|
// exception happens or the connection's expireTime
|
||||||
|
// comes
|
||||||
|
} catch (Exception e ){
|
||||||
manager.discardConnection(this);
|
manager.discardConnection(this);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
}while(true);
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -41,18 +41,25 @@ import java.rmi.server.RMISocketFactory;
|
||||||
import java.rmi.server.RMIServerSocketFactory;
|
import java.rmi.server.RMIServerSocketFactory;
|
||||||
import java.rmi.server.RMIClientSocketFactory;
|
import java.rmi.server.RMIClientSocketFactory;
|
||||||
import java.rmi.RemoteException;
|
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.IOException;
|
||||||
import java.io.ObjectOutput;
|
import java.io.ObjectOutput;
|
||||||
import java.io.ObjectInput;
|
import java.io.ObjectInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.lang.Thread;
|
import java.lang.Thread;
|
||||||
import java.lang.Runnable;
|
import java.lang.Runnable;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.ServerSocket;
|
||||||
import java.net.UnknownHostException;
|
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
|
public class UnicastConnectionManager
|
||||||
implements Runnable, ProtocolConstants {
|
implements Runnable, ProtocolConstants {
|
||||||
|
|
||||||
|
@ -60,15 +67,33 @@ private static String localhost;
|
||||||
// use different maps for server/client type UnicastConnectionManager
|
// use different maps for server/client type UnicastConnectionManager
|
||||||
private static Hashtable servers = new Hashtable();
|
private static Hashtable servers = new Hashtable();
|
||||||
private static Hashtable clients = new Hashtable();
|
private static Hashtable clients = new Hashtable();
|
||||||
|
private ArrayList connections; //client connection pool
|
||||||
|
|
||||||
// make serverThread volatile for poll
|
// make serverThread volatile for poll
|
||||||
private volatile Thread serverThread;
|
private volatile Thread serverThread;
|
||||||
private ServerSocket ssock;
|
private ServerSocket ssock;
|
||||||
String serverName;
|
String serverName;
|
||||||
int serverPort;
|
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 RMIServerSocketFactory serverFactory;
|
||||||
private RMIClientSocketFactory clientFactory;
|
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 {
|
static {
|
||||||
try {
|
try {
|
||||||
//Use host address instead of host name to avoid name resolving issues
|
//Use host address instead of host name to avoid name resolving issues
|
||||||
|
@ -78,16 +103,73 @@ static {
|
||||||
catch (UnknownHostException _) {
|
catch (UnknownHostException _) {
|
||||||
localhost = "localhost";
|
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) {
|
private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
|
||||||
ssock = null;
|
ssock = null;
|
||||||
serverName = host;
|
serverName = host;
|
||||||
serverPort = port;
|
serverPort = port;
|
||||||
serverFactory = null;
|
serverFactory = null;
|
||||||
clientFactory = csf;
|
clientFactory = csf;
|
||||||
|
connections = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server UnicastConnectionManager constructor
|
||||||
|
*/
|
||||||
private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
|
private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
|
||||||
try {
|
try {
|
||||||
ssock = ssf.createServerSocket(port);
|
ssock = ssf.createServerSocket(port);
|
||||||
|
@ -115,7 +197,7 @@ private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) {
|
||||||
public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
|
public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
|
||||||
//System.out.println("getInstance: " + host + "," + port + "," + csf);
|
//System.out.println("getInstance: " + host + "," + port + "," + csf);
|
||||||
if (csf == null) {
|
if (csf == null) {
|
||||||
csf = RMISocketFactory.getSocketFactory();
|
csf = defaultSocketFactory;
|
||||||
}
|
}
|
||||||
// change host name to host address to avoid name resolving issues
|
// change host name to host address to avoid name resolving issues
|
||||||
try{
|
try{
|
||||||
|
@ -126,7 +208,17 @@ public static synchronized UnicastConnectionManager getInstance(String host, int
|
||||||
UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
|
UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
|
||||||
if (man == null) {
|
if (man == null) {
|
||||||
man = new UnicastConnectionManager(host, port, csf);
|
man = new UnicastConnectionManager(host, port, csf);
|
||||||
|
if (debug) {
|
||||||
|
ncmanager++;
|
||||||
|
System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
|
||||||
|
}
|
||||||
clients.put(key, man);
|
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);
|
return (man);
|
||||||
}
|
}
|
||||||
|
@ -138,12 +230,16 @@ public static synchronized UnicastConnectionManager getInstance(String host, int
|
||||||
public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {
|
public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) {
|
||||||
//System.out.println("getInstance: " + port + "," + ssf);
|
//System.out.println("getInstance: " + port + "," + ssf);
|
||||||
if (ssf == null) {
|
if (ssf == null) {
|
||||||
ssf = RMISocketFactory.getSocketFactory();
|
ssf = defaultSocketFactory;
|
||||||
}
|
}
|
||||||
TripleKey key = new TripleKey(localhost, port, ssf);
|
TripleKey key = new TripleKey(localhost, port, ssf);
|
||||||
UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
|
UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
|
||||||
if (man == null) {
|
if (man == null) {
|
||||||
man = new UnicastConnectionManager(port, ssf);
|
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.
|
// The provided port might not be the set port.
|
||||||
key.port = man.serverPort;
|
key.port = man.serverPort;
|
||||||
servers.put(key, man);
|
servers.put(key, man);
|
||||||
|
@ -168,9 +264,14 @@ public UnicastConnection getConnection() throws IOException {
|
||||||
*/
|
*/
|
||||||
private UnicastConnection getServerConnection() throws IOException {
|
private UnicastConnection getServerConnection() throws IOException {
|
||||||
Socket sock = ssock.accept();
|
Socket sock = ssock.accept();
|
||||||
|
sock.setTcpNoDelay(true); //??
|
||||||
UnicastConnection conn = new UnicastConnection(this, sock);
|
UnicastConnection conn = new UnicastConnection(this, sock);
|
||||||
conn.acceptConnection();
|
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);
|
return (conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,10 +279,38 @@ private UnicastConnection getServerConnection() throws IOException {
|
||||||
* Make a conection from this client to the server.
|
* Make a conection from this client to the server.
|
||||||
*/
|
*/
|
||||||
private UnicastConnection getClientConnection() throws IOException {
|
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);
|
Socket sock = clientFactory.createSocket(serverName, serverPort);
|
||||||
UnicastConnection conn = new UnicastConnection(this, sock);
|
conn = new UnicastConnection(this, sock);
|
||||||
conn.makeConnection(DEFAULT_PROTOCOL);
|
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);
|
return (conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +320,19 @@ private UnicastConnection getClientConnection() throws IOException {
|
||||||
*/
|
*/
|
||||||
public void discardConnection(UnicastConnection conn) {
|
public void discardConnection(UnicastConnection conn) {
|
||||||
//System.out.println("Discarding connection " + conn);
|
//System.out.println("Discarding connection " + conn);
|
||||||
|
//conn.disconnect();
|
||||||
|
if (ssock != null) //server connection
|
||||||
conn.disconnect();
|
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 @@ public void startServer() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
serverThread = new Thread(this);
|
serverThread = new Thread(this);
|
||||||
|
// The following is not necessary when java.lang.Thread's constructor do this.
|
||||||
|
// serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
|
||||||
}
|
}
|
||||||
serverThread.start();
|
serverThread.start();
|
||||||
}
|
}
|
||||||
|
@ -231,11 +374,11 @@ public void run() {
|
||||||
//System.out.println("Waiting for connection on " + serverPort);
|
//System.out.println("Waiting for connection on " + serverPort);
|
||||||
UnicastConnection conn = getServerConnection();
|
UnicastConnection conn = getServerConnection();
|
||||||
// use a thread pool to improve performance
|
// use a thread pool to improve performance
|
||||||
// (new Thread(conn)).start();
|
//ConnectionRunnerPool.dispatchConnection(conn);
|
||||||
ConnectionRunnerPool.dispatchConnection(conn);
|
(new Thread(conn)).start();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
// e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,8 +397,9 @@ void write(ObjectOutput out) throws IOException {
|
||||||
static UnicastConnectionManager read(ObjectInput in) throws IOException {
|
static UnicastConnectionManager read(ObjectInput in) throws IOException {
|
||||||
String host = in.readUTF();
|
String host = in.readUTF();
|
||||||
int port = in.readInt();
|
int port = in.readInt();
|
||||||
RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
|
//RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
|
||||||
return (getInstance(host, port, csf));
|
//return (getInstance(host, port, csf));
|
||||||
|
return (getInstance(host, port, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -288,7 +432,7 @@ public boolean equals(Object obj) {
|
||||||
TripleKey other = (TripleKey)obj;
|
TripleKey other = (TripleKey)obj;
|
||||||
if (this.host.equals(other.host) &&
|
if (this.host.equals(other.host) &&
|
||||||
this.other == other.other &&
|
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);
|
return (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ import java.io.ObjectOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
public class UnicastRef
|
public class UnicastRef
|
||||||
implements RemoteRef, ProtocolConstants {
|
implements RemoteRef, ProtocolConstants {
|
||||||
|
|
||||||
|
@ -69,9 +71,10 @@ public ObjID objid;
|
||||||
UnicastConnectionManager manager;
|
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) {
|
public UnicastRef(ObjID objid, String host, int port, RMIClientSocketFactory csf) {
|
||||||
|
@ -84,6 +87,21 @@ public UnicastRef(ObjID objid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Remote obj, Method method, Object[] params, long opnum) throws Exception {
|
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));
|
return (invokeCommon(obj, method, params, -1, opnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,18 +125,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
|
||||||
objid.write(out);
|
objid.write(out);
|
||||||
out.writeInt(opnum);
|
out.writeInt(opnum);
|
||||||
out.writeLong(hash);
|
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
|
// must handle primitive class and their wrapper classes
|
||||||
Class clss[] = method.getParameterTypes();
|
Class clss[] = method.getParameterTypes();
|
||||||
for(int i = 0; i < clss.length; i++)
|
for(int i = 0; i < clss.length; i++)
|
||||||
|
@ -137,26 +144,30 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
|
||||||
UID ack;
|
UID ack;
|
||||||
try {
|
try {
|
||||||
din = conn.getDataInputStream();
|
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();
|
in = conn.getObjectInputStream();
|
||||||
|
|
||||||
returncode = in.readUnsignedByte();
|
returncode = in.readUnsignedByte();
|
||||||
ack = UID.read(in);
|
ack = UID.read(in);
|
||||||
//returnval = in.readObject();
|
|
||||||
Class cls = method.getReturnType();
|
Class cls = method.getReturnType();
|
||||||
if(cls == Void.TYPE){
|
if(cls == Void.TYPE){
|
||||||
returnval = null;
|
returnval = null;
|
||||||
|
in.readObject();
|
||||||
}else
|
}else
|
||||||
returnval = ((RMIObjectInputStream)in).readValue(cls);
|
returnval = ((RMIObjectInputStream)in).readValue(cls);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IOException e3) {
|
catch (IOException e3) {
|
||||||
|
//for debug: e3.printStackTrace();
|
||||||
throw new RemoteException("call return failed: ", e3);
|
throw new RemoteException("call return failed: ", e3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if DGCAck is necessary
|
/* if DGCAck is necessary??
|
||||||
//According to RMI wire protocol, send a DGCAck
|
//According to RMI wire protocol, send a DGCAck
|
||||||
// to indicate receiving return value
|
// to indicate receiving return value
|
||||||
dout.writeByte(MESSAGE_DGCACK);
|
dout.writeByte(MESSAGE_DGCACK);
|
||||||
|
@ -166,7 +177,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
|
||||||
|
|
||||||
manager.discardConnection(conn);
|
manager.discardConnection(conn);
|
||||||
|
|
||||||
if (returncode != RETURN_ACK) {
|
if (returncode != RETURN_ACK && returnval != null) {
|
||||||
throw (Exception)returnval;
|
throw (Exception)returnval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +188,18 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash) throws RemoteException {
|
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 RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash
|
||||||
*/
|
*/
|
||||||
public void invoke(RemoteCall call) throws Exception {
|
public void invoke(RemoteCall call) throws Exception {
|
||||||
UnicastRemoteCall c = (UnicastRemoteCall)call;
|
UnicastRemoteCall c = (UnicastRemoteCall)call;
|
||||||
Object ret = invokeCommon((Remote)c.getObject(), (Method)null, c.getArguments(), c.getOpnum(), c.getHash());
|
call.executeCall();
|
||||||
c.setReturnValue(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public void done(RemoteCall call) throws RemoteException {
|
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 {
|
public void writeExternal(ObjectOutput out) throws IOException {
|
||||||
|
|
|
@ -38,14 +38,24 @@ exception statement from your version. */
|
||||||
package gnu.java.rmi.server;
|
package gnu.java.rmi.server;
|
||||||
|
|
||||||
import java.lang.Exception;
|
import java.lang.Exception;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutput;
|
import java.io.ObjectOutput;
|
||||||
import java.io.ObjectInput;
|
import java.io.ObjectInput;
|
||||||
import java.io.StreamCorruptedException;
|
import java.io.StreamCorruptedException;
|
||||||
import java.rmi.server.RemoteCall;
|
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;
|
import java.util.Vector;
|
||||||
|
|
||||||
public class UnicastRemoteCall implements RemoteCall
|
public class UnicastRemoteCall
|
||||||
|
implements RemoteCall, ProtocolConstants
|
||||||
{
|
{
|
||||||
|
|
||||||
private UnicastConnection conn;
|
private UnicastConnection conn;
|
||||||
|
@ -56,6 +66,9 @@ public class UnicastRemoteCall implements RemoteCall
|
||||||
private Vector vec;
|
private Vector vec;
|
||||||
private int ptr;
|
private int ptr;
|
||||||
|
|
||||||
|
private ObjectOutput oout;
|
||||||
|
private ObjectInput oin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Incoming call.
|
* Incoming call.
|
||||||
*/
|
*/
|
||||||
|
@ -67,30 +80,71 @@ public class UnicastRemoteCall implements RemoteCall
|
||||||
/**
|
/**
|
||||||
* Outgoing call.
|
* 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.opnum = opnum;
|
||||||
this.hash = hash;
|
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
|
public ObjectOutput getOutputStream() throws IOException
|
||||||
{
|
{
|
||||||
vec = new Vector();
|
if (conn != null)
|
||||||
return new DummyObjectOutputStream();
|
{
|
||||||
|
if(oout == null)
|
||||||
|
return (oout = conn.getObjectOutputStream());
|
||||||
|
else
|
||||||
|
return oout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec = new Vector();
|
||||||
|
return (new DummyObjectOutputStream());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseOutputStream() throws IOException
|
public void releaseOutputStream() throws IOException
|
||||||
{
|
{
|
||||||
// Does nothing.
|
if(oout != null)
|
||||||
|
oout.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectInput getInputStream() throws IOException
|
public ObjectInput getInputStream() throws IOException
|
||||||
{
|
{
|
||||||
if (conn != null)
|
if (conn != null)
|
||||||
return conn.getObjectInputStream();
|
{
|
||||||
ptr = 0;
|
if(oin == null)
|
||||||
return new DummyObjectInputStream();
|
return (oin = conn.getObjectInputStream());
|
||||||
|
else
|
||||||
|
return oin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = 0;
|
||||||
|
return (new DummyObjectInputStream());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseInputStream() throws IOException
|
public void releaseInputStream() throws IOException
|
||||||
|
@ -104,15 +158,57 @@ public class UnicastRemoteCall implements RemoteCall
|
||||||
vec = new Vector();
|
vec = new Vector();
|
||||||
return new DummyObjectOutputStream();
|
return new DummyObjectOutputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeCall() throws Exception
|
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
|
public void done() throws IOException
|
||||||
{
|
{
|
||||||
/* Does nothing */
|
// conn.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object returnValue()
|
Object returnValue()
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.rmi.Remote;
|
||||||
import java.rmi.server.ObjID;
|
import java.rmi.server.ObjID;
|
||||||
import java.rmi.server.UnicastRemoteObject;
|
import java.rmi.server.UnicastRemoteObject;
|
||||||
import java.rmi.server.UID;
|
import java.rmi.server.UID;
|
||||||
|
@ -56,27 +57,36 @@ import gnu.java.rmi.dgc.DGCImpl;
|
||||||
public class UnicastServer
|
public class UnicastServer
|
||||||
implements ProtocolConstants {
|
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;
|
static private DGCImpl dgc;
|
||||||
|
|
||||||
public static void exportObject(UnicastServerRef obj) {
|
public static void exportObject(UnicastServerRef obj) {
|
||||||
startDGC();
|
startDGC();
|
||||||
objects.put(obj.objid, obj);
|
objects.put(obj.objid, obj);
|
||||||
|
refcache.put(obj.myself, obj);
|
||||||
obj.manager.startServer();
|
obj.manager.startServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIX ME: I haven't handle force parameter
|
// FIX ME: I haven't handle force parameter
|
||||||
public static boolean unexportObject(UnicastServerRef obj, boolean force) {
|
public static boolean unexportObject(UnicastServerRef obj, boolean force) {
|
||||||
objects.remove(obj.objid);
|
objects.remove(obj.objid);
|
||||||
|
refcache.remove(obj.myself);
|
||||||
obj.manager.stopServer();
|
obj.manager.stopServer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UnicastServerRef getExportedRef(Remote remote){
|
||||||
|
return (UnicastServerRef)refcache.get(remote);
|
||||||
|
}
|
||||||
|
|
||||||
private static synchronized void startDGC() {
|
private static synchronized void startDGC() {
|
||||||
if (dgc == null) {
|
if (dgc == null) {
|
||||||
try {
|
try {
|
||||||
dgc = new DGCImpl();
|
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) {
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -63,6 +63,8 @@ import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.ObjectInput;
|
||||||
|
import java.io.ObjectOutput;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
public class UnicastServerRef
|
public class UnicastServerRef
|
||||||
|
@ -71,11 +73,18 @@ public class UnicastServerRef
|
||||||
|
|
||||||
final static private Class[] stubprototype = new Class[] { RemoteRef.class };
|
final static private Class[] stubprototype = new Class[] { RemoteRef.class };
|
||||||
|
|
||||||
Remote myself;
|
Remote myself; //save the remote object itself
|
||||||
private Skeleton skel;
|
private Skeleton skel;
|
||||||
private RemoteStub stub;
|
private RemoteStub stub;
|
||||||
private Hashtable methods = new Hashtable();
|
private Hashtable methods = new Hashtable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by serialization.
|
||||||
|
*/
|
||||||
|
UnicastServerRef()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
|
public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
|
||||||
super(id);
|
super(id);
|
||||||
manager = UnicastConnectionManager.getInstance(port, ssf);
|
manager = UnicastConnectionManager.getInstance(port, ssf);
|
||||||
|
@ -84,6 +93,9 @@ public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
|
||||||
public RemoteStub exportObject(Remote obj) throws RemoteException {
|
public RemoteStub exportObject(Remote obj) throws RemoteException {
|
||||||
if (myself == null) {
|
if (myself == null) {
|
||||||
myself = obj;
|
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
|
// Find and install the stub
|
||||||
Class cls = obj.getClass();
|
Class cls = obj.getClass();
|
||||||
|
@ -112,6 +124,10 @@ public RemoteStub exportObject(Remote remote, Object obj)
|
||||||
return exportObject(remote);
|
return exportObject(remote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RemoteStub getStub(){
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean unexportObject(Remote obj, boolean force) throws RemoteException {
|
public boolean unexportObject(Remote obj, boolean force) throws RemoteException {
|
||||||
// Remove all hashes of methods which may be called.
|
// Remove all hashes of methods which may be called.
|
||||||
|
|
|
@ -78,6 +78,10 @@ public final class MarshalledObject
|
||||||
{
|
{
|
||||||
if(obj == null || !(obj instanceof MarshalledObject) )
|
if(obj == null || !(obj instanceof MarshalledObject) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// hashCode even differs, don't do the time-consuming comparisons
|
||||||
|
if (obj.hashCode() != hash)
|
||||||
|
return false;
|
||||||
|
|
||||||
MarshalledObject aobj = (MarshalledObject)obj;
|
MarshalledObject aobj = (MarshalledObject)obj;
|
||||||
if (objBytes == null || aobj.objBytes == null)
|
if (objBytes == null || aobj.objBytes == null)
|
||||||
|
|
|
@ -43,39 +43,72 @@ import java.net.URLClassLoader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.StringTokenizer;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class RMIClassLoader
|
public class RMIClassLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
static private class MyClassLoader extends URLClassLoader
|
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)
|
private MyClassLoader(URL[] urls, ClassLoader parent)
|
||||||
{
|
{
|
||||||
super (urls, 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 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;
|
private static String defaultAnnotation;
|
||||||
|
//URL object for defaultAnnotation
|
||||||
private static URL defaultCodebase;
|
private static URL defaultCodebase;
|
||||||
|
//class loader for defaultAnnotation
|
||||||
private static MyClassLoader defaultLoader;
|
private static MyClassLoader defaultLoader;
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
cacheLoaders = Collections.synchronizedMap(new WeakHashMap(5));
|
// 89 is a nice prime number for Hashtable initial capacity
|
||||||
cacheClasses = Collections.synchronizedMap(new WeakHashMap(5));
|
cacheLoaders = new Hashtable(89);
|
||||||
|
cacheAnnotations = new Hashtable(89);
|
||||||
|
|
||||||
defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
|
defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -89,9 +122,8 @@ public class RMIClassLoader
|
||||||
if (defaultCodebase != null)
|
if (defaultCodebase != null)
|
||||||
{
|
{
|
||||||
defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },
|
defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },
|
||||||
Thread.currentThread().getContextClassLoader());
|
null, defaultAnnotation);
|
||||||
cacheLoaders.put(defaultAnnotation, defaultLoader);
|
cacheLoaders.put(defaultAnnotation, defaultLoader);
|
||||||
cacheClasses.put(defaultLoader, Collections.synchronizedMap(new WeakHashMap()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,91 +136,76 @@ public class RMIClassLoader
|
||||||
return (loadClass("", name));
|
return (loadClass("", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class loadClass(URL codebase, String name)
|
|
||||||
throws MalformedURLException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
URL u = new URL(codebase, name + ".class");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class loadClass(String codebases, String name)
|
public static Class loadClass(String codebases, String name)
|
||||||
throws MalformedURLException, ClassNotFoundException
|
throws MalformedURLException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
ClassLoader loader = (ClassLoader)cacheLoaders.get(codebases);
|
Class c = null;
|
||||||
if (loader == null)
|
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||||
|
//try context class loader first
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (codebases != "")
|
c = loader.loadClass(name);
|
||||||
|
}
|
||||||
|
catch(ClassNotFoundException e) {}
|
||||||
|
|
||||||
|
if (c != null)
|
||||||
|
return c;
|
||||||
|
|
||||||
|
if (codebases.length() == 0) //==""
|
||||||
|
loader = defaultLoader;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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, " ");
|
StringTokenizer tok = new StringTokenizer(codebases, " ");
|
||||||
ArrayList urls = new ArrayList();
|
ArrayList urls = new ArrayList();
|
||||||
while (tok.hasMoreTokens())
|
while (tok.hasMoreTokens())
|
||||||
urls.add(new URL(tok.nextToken()));
|
urls.add(new URL(tok.nextToken()));
|
||||||
|
|
||||||
loader = new MyClassLoader((URL[])urls.toArray(new URL[urls.size()]),
|
loader = new MyClassLoader((URL[])urls.toArray(new URL[urls.size()]),
|
||||||
Thread.currentThread().getContextClassLoader());
|
null, codebases);
|
||||||
cacheLoaders.put(codebases, loader);
|
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;
|
return loader != null ? loader.loadClass(name) : Class.forName(name);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClassAnnotation(Class cl)
|
public static String getClassAnnotation(Class cl)
|
||||||
{
|
{
|
||||||
ClassLoader loader = cl.getClassLoader();
|
ClassLoader loader = cl.getClassLoader();
|
||||||
if (loader == null)
|
if (loader == null || loader == ClassLoader.getSystemClassLoader())
|
||||||
{
|
{
|
||||||
if (defaultCodebase != null)
|
return null; //??
|
||||||
return defaultCodebase.toExternalForm();
|
|
||||||
else
|
|
||||||
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)
|
if (loader instanceof URLClassLoader)
|
||||||
{
|
{
|
||||||
URL[] urls = ((URLClassLoader)loader).getURLs();
|
URL[] urls = ((URLClassLoader)loader).getURLs();
|
||||||
if(urls.length == 0)
|
if(urls.length == 0)
|
||||||
return null;
|
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(urls[i].toExternalForm());
|
||||||
|
annotation.append(' ');
|
||||||
}
|
}
|
||||||
return annotation.toString();
|
s = annotation.toString();
|
||||||
|
cacheAnnotations.put(loader, s);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,11 +127,11 @@ public boolean equals(Object obj) {
|
||||||
}
|
}
|
||||||
catch (InstantiationException e1)
|
catch (InstantiationException e1)
|
||||||
{
|
{
|
||||||
throw new UnmarshalException("failed to create ref");
|
throw new UnmarshalException("failed to create ref", e1);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e2)
|
catch (IllegalAccessException e2)
|
||||||
{
|
{
|
||||||
throw new UnmarshalException("failed to create ref");
|
throw new UnmarshalException("failed to create ref", e2);
|
||||||
}
|
}
|
||||||
ref.readExternal(in);
|
ref.readExternal(in);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -67,16 +67,12 @@ protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSoc
|
||||||
//this.csf = csf;
|
//this.csf = csf;
|
||||||
//this.ssf = ssf;
|
//this.ssf = ssf;
|
||||||
this.ref = new UnicastServerRef(new ObjID(), port, ssf);
|
this.ref = new UnicastServerRef(new ObjID(), port, ssf);
|
||||||
//Should we export it here?
|
exportObject(this);
|
||||||
// if we export, we got infinite recursive call:
|
|
||||||
// UnicastRemoteObject.<init>->...->UnicastServer.startDGC()->UnicastRemoteObject.<init>->...
|
|
||||||
//exportObject(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
|
protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
|
||||||
super((UnicastServerRef)ref);
|
super((UnicastServerRef)ref);
|
||||||
//Should we export it here?
|
exportObject(this);
|
||||||
//exportObject(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue