2 Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.java
.rmi
.server
;
40 import java
.net
.ServerSocket
;
41 import java
.net
.Socket
;
42 import java
.net
.InetAddress
;
43 import java
.net
.UnknownHostException
;
44 import java
.rmi
.Remote
;
45 import java
.rmi
.RemoteException
;
46 import java
.rmi
.server
.RemoteStub
;
47 import java
.rmi
.server
.ObjID
;
48 import java
.rmi
.server
.ServerRef
;
49 import java
.rmi
.server
.RemoteRef
;
50 import java
.rmi
.server
.ServerNotActiveException
;
51 import java
.rmi
.server
.RMIClientSocketFactory
;
52 import java
.rmi
.server
.RMIServerSocketFactory
;
53 import java
.rmi
.server
.UID
;
54 import java
.rmi
.server
.Skeleton
;
55 import java
.rmi
.server
.RemoteCall
;
56 import java
.lang
.reflect
.Constructor
;
57 import java
.lang
.reflect
.Method
;
58 import java
.lang
.reflect
.InvocationTargetException
;
59 import java
.lang
.Thread
;
60 import java
.lang
.Exception
;
61 import java
.io
.IOException
;
62 import java
.io
.DataInputStream
;
63 import java
.io
.DataOutputStream
;
64 import java
.io
.ObjectInputStream
;
65 import java
.io
.ObjectOutputStream
;
66 import java
.io
.ObjectInput
;
67 import java
.io
.ObjectOutput
;
68 import java
.util
.Hashtable
;
70 public class UnicastServerRef
72 implements ServerRef
{ //SHOULD implement ServerRef
74 final static private Class
[] stubprototype
= new Class
[] { RemoteRef
.class };
76 Remote myself
; //save the remote object itself
77 private Skeleton skel
;
78 private RemoteStub stub
;
79 private Hashtable methods
= new Hashtable();
82 * Used by serialization.
88 public UnicastServerRef(ObjID id
, int port
, RMIServerSocketFactory ssf
) {
90 manager
= UnicastConnectionManager
.getInstance(port
, ssf
);
93 public RemoteStub
exportObject(Remote obj
) throws RemoteException
{
96 // Save it to server manager, to let client calls in the same VM to issue
98 manager
.serverobj
= obj
;
100 // Find and install the stub
101 Class cls
= obj
.getClass();
102 stub
= (RemoteStub
)getHelperClass(cls
, "_Stub");
104 throw new RemoteException("failed to export: " + cls
);
107 // Find and install the skeleton (if there is one)
108 skel
= (Skeleton
)getHelperClass(cls
, "_Skel");
110 // Build hash of methods which may be called.
111 buildMethodHash(obj
.getClass(), true);
114 UnicastServer
.exportObject(this);
120 public RemoteStub
exportObject(Remote remote
, Object obj
)
121 throws RemoteException
124 return exportObject(remote
);
127 public RemoteStub
getStub(){
132 public boolean unexportObject(Remote obj
, boolean force
) {
133 // Remove all hashes of methods which may be called.
134 buildMethodHash(obj
.getClass(), false);
135 return UnicastServer
.unexportObject(this, force
);
138 private Object
getHelperClass(Class cls
, String type
) {
140 String classname
= cls
.getName();
141 ClassLoader cl
= cls
.getClassLoader();
142 Class scls
= cl
== null ? Class
.forName(classname
+ type
)
143 : cl
.loadClass(classname
+ type
);
144 if (type
.equals("_Stub")) {
147 Constructor con
= scls
.getConstructor(stubprototype
);
148 return (con
.newInstance(new Object
[]{this}));
150 catch (NoSuchMethodException e
) {
152 catch (InstantiationException e
) {
154 catch (IllegalAccessException e
) {
156 catch (IllegalArgumentException e
) {
158 catch (InvocationTargetException e
) {
161 RemoteStub stub
= (RemoteStub
)scls
.newInstance();
162 UnicastRemoteStub
.setStubRef(stub
, this);
167 return (scls
.newInstance());
170 catch (ClassNotFoundException e
) {
172 catch (InstantiationException e
) {
174 catch (IllegalAccessException e
) {
179 public String
getClientHost() throws ServerNotActiveException
{
180 throw new Error("Not implemented");
183 private void buildMethodHash(Class cls
, boolean build
) {
184 Method
[] meths
= cls
.getMethods();
185 for (int i
= 0; i
< meths
.length
; i
++) {
186 /* Don't need to include any java.xxx related stuff */
187 if (meths
[i
].getDeclaringClass().getName().startsWith("java.")) {
190 long hash
= RMIHashes
.getMethodHash(meths
[i
]);
192 methods
.put(new Long (hash
), meths
[i
]);
194 methods
.remove(new Long (hash
));
195 //System.out.println("meth = " + meths[i] + ", hash = " + hash);
199 Class
getMethodReturnType(int method
, long hash
) throws Exception
202 Method meth
= (Method
)methods
.get(new Long (hash
));
203 return meth
.getReturnType();
208 public Object
incomingMessageCall(UnicastConnection conn
, int method
, long hash
) throws Exception
{
209 //System.out.println("method = " + method + ", hash = " + hash);
210 // If method is -1 then this is JDK 1.2 RMI - so use the hash
211 // to locate the method
213 Method meth
= (Method
)methods
.get(new Long (hash
));
214 //System.out.println("class = " + myself.getClass() + ", meth = " + meth);
216 throw new NoSuchMethodException();
219 ObjectInputStream in
= conn
.getObjectInputStream();
220 int nrargs
= meth
.getParameterTypes().length
;
221 Object
[] args
= new Object
[nrargs
];
222 for (int i
= 0; i
< nrargs
; i
++) {
224 * For debugging purposes - we don't handle CodeBases
225 * quite right so we don't always find the stubs. This
229 // need to handle primitive types
230 args
[i
] = ((RMIObjectInputStream
)in
).readValue(meth
.getParameterTypes()[i
]);
233 catch (Exception t
) {
238 //We must reinterpret the exception thrown by meth.invoke()
239 //return (meth.invoke(myself, args));
242 ret
= meth
.invoke(myself
, args
);
243 }catch(InvocationTargetException e
){
244 throw (Exception
)(e
.getTargetException());
248 // Otherwise this is JDK 1.1 style RMI - we find the skeleton
249 // and invoke it using the method number. We wrap up our
250 // connection system in a UnicastRemoteCall so it appears in a
251 // way the Skeleton can handle.
254 throw new NoSuchMethodException();
256 UnicastRemoteCall call
= new UnicastRemoteCall(conn
);
257 skel
.dispatch(myself
, call
, method
, hash
);
258 if (!call
.isReturnValue())
259 return RMIVoidValue
.INSTANCE
;
261 return (call
.returnValue());