2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / gnu / java / rmi / server / UnicastServerRef.java
blobb004927502fbe024abe8f5a24cf028f9223b7d93
1 /*
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)
9 any later version.
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
19 02111-1307 USA.
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
24 combination.
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
71 extends UnicastRef
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();
81 /**
82 * Used by serialization.
84 UnicastServerRef()
88 public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) {
89 super(id);
90 manager = UnicastConnectionManager.getInstance(port, ssf);
93 public RemoteStub exportObject(Remote obj) throws RemoteException {
94 if (myself == null) {
95 myself = obj;
96 // Save it to server manager, to let client calls in the same VM to issue
97 // local call
98 manager.serverobj = obj;
100 // Find and install the stub
101 Class cls = obj.getClass();
102 stub = (RemoteStub)getHelperClass(cls, "_Stub");
103 if (stub == null) {
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);
113 // Export it.
114 UnicastServer.exportObject(this);
117 return (stub);
120 public RemoteStub exportObject(Remote remote, Object obj)
121 throws RemoteException
123 //FIX ME
124 return exportObject(remote);
127 public RemoteStub getStub(){
128 return stub;
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) {
139 try {
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")) {
145 try {
146 // JDK 1.2 stubs
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) {
160 // JDK 1.1 stubs
161 RemoteStub stub = (RemoteStub)scls.newInstance();
162 UnicastRemoteStub.setStubRef(stub, this);
163 return (stub);
165 else {
166 // JDK 1.1 skel
167 return (scls.newInstance());
170 catch (ClassNotFoundException e) {
172 catch (InstantiationException e) {
174 catch (IllegalAccessException e) {
176 return (null);
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.")) {
188 continue;
190 long hash = RMIHashes.getMethodHash(meths[i]);
191 if(build)
192 methods.put(new Long (hash), meths[i]);
193 else
194 methods.remove(new Long (hash));
195 //System.out.println("meth = " + meths[i] + ", hash = " + hash);
199 Class getMethodReturnType(int method, long hash) throws Exception
201 if (method == -1) {
202 Method meth = (Method)methods.get(new Long (hash));
203 return meth.getReturnType();
204 }else
205 return null;
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
212 if (method == -1) {
213 Method meth = (Method)methods.get(new Long (hash));
214 //System.out.println("class = " + myself.getClass() + ", meth = " + meth);
215 if (meth == null) {
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++) {
223 /**
224 * For debugging purposes - we don't handle CodeBases
225 * quite right so we don't always find the stubs. This
226 * lets us know that.
228 try {
229 // need to handle primitive types
230 args[i] = ((RMIObjectInputStream)in).readValue(meth.getParameterTypes()[i]);
233 catch (Exception t) {
234 t.printStackTrace();
235 throw t;
238 //We must reinterpret the exception thrown by meth.invoke()
239 //return (meth.invoke(myself, args));
240 Object ret = null;
241 try{
242 ret = meth.invoke(myself, args);
243 }catch(InvocationTargetException e){
244 throw (Exception)(e.getTargetException());
246 return ret;
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.
252 else {
253 if (skel == null) {
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;
260 else
261 return (call.returnValue());