Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / gnu / java / rmi / server / UnicastServerRef.java
blobce4420c4701b5a5768d0d7e40845fcdd7a913cea
1 /* UnicastServerRef.java --
2 Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
40 package gnu.java.rmi.server;
42 import java.io.ObjectInputStream;
43 import java.lang.reflect.Constructor;
44 import java.lang.reflect.Method;
45 import java.lang.reflect.InvocationTargetException;
46 import java.rmi.Remote;
47 import java.rmi.RemoteException;
48 import java.rmi.server.RemoteStub;
49 import java.rmi.server.ObjID;
50 import java.rmi.server.ServerRef;
51 import java.rmi.server.RemoteServer;
52 import java.rmi.server.RemoteRef;
53 import java.rmi.server.ServerNotActiveException;
54 import java.rmi.server.RMIServerSocketFactory;
55 import java.rmi.server.Skeleton;
56 import java.util.Hashtable;
58 public class UnicastServerRef
59 extends UnicastRef
60 implements ServerRef{ //SHOULD implement ServerRef
62 final static private Class[] stubprototype = new Class[] { RemoteRef.class };
64 Remote myself; //save the remote object itself
65 private Skeleton skel;
66 private RemoteStub stub;
67 private Hashtable methods = new Hashtable();
69 /**
70 * Used by serialization.
72 UnicastServerRef()
76 public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) throws RemoteException {
77 super(id);
78 manager = UnicastConnectionManager.getInstance(port, ssf);
81 public RemoteStub exportObject(Remote obj) throws RemoteException {
82 if (myself == null) {
83 myself = obj;
84 // Save it to server manager, to let client calls in the same VM to issue
85 // local call
86 manager.serverobj = obj;
88 // Find and install the stub
89 Class cls = obj.getClass();
90 Class expCls;
91 try {
92 // where ist the _Stub? (check superclasses also)
93 expCls = findStubSkelClass(cls);
94 } catch (Exception ex) {
95 throw new RemoteException("can not find stubs for class: " + cls, ex);
98 stub = (RemoteStub)getHelperClass(expCls, "_Stub");
99 if (stub == null) {
100 throw new RemoteException("failed to export: " + cls);
103 // Find and install the skeleton (if there is one)
104 skel = (Skeleton)getHelperClass(expCls, "_Skel");
106 // Build hash of methods which may be called.
107 buildMethodHash(obj.getClass(), true);
109 // Export it.
110 UnicastServer.exportObject(this);
113 return (stub);
116 public RemoteStub exportObject(Remote remote, Object obj)
117 throws RemoteException
119 //FIX ME
120 return exportObject(remote);
123 public RemoteStub getStub(){
124 return stub;
128 public boolean unexportObject(Remote obj, boolean force) {
129 // Remove all hashes of methods which may be called.
130 buildMethodHash(obj.getClass(), false);
131 return UnicastServer.unexportObject(this, force);
136 * The Subs/Skels might not there for the actual class, but maybe
137 * for one of the superclasses.
140 private Class findStubSkelClass(Class startCls) throws Exception {
141 Class cls = startCls;
143 while (true) {
144 try {
145 String stubClassname = cls.getName() + "_Stub";
146 ClassLoader cl = cls.getClassLoader();
147 Class scls = cl == null ? Class.forName(stubClassname)
148 : cl.loadClass(stubClassname);
149 return cls; // found it
150 } catch (ClassNotFoundException e) {
151 Class superCls = cls.getSuperclass();
152 if (superCls == null
153 || superCls == java.rmi.server.UnicastRemoteObject.class)
155 throw new Exception("Neither " + startCls
156 + " nor one of their superclasses (like" + cls + ")"
157 + " has a _Stub");
159 cls = superCls;
166 private Object getHelperClass(Class cls, String type) {
167 try {
168 String classname = cls.getName();
169 ClassLoader cl = cls.getClassLoader();
170 Class scls = cl == null ? Class.forName(classname + type)
171 : cl.loadClass(classname + type);
172 if (type.equals("_Stub")) {
173 try {
174 // JDK 1.2 stubs
175 Constructor con = scls.getConstructor(stubprototype);
176 return (con.newInstance(new Object[]{this}));
178 catch (NoSuchMethodException e) {
180 catch (InstantiationException e) {
182 catch (IllegalAccessException e) {
184 catch (IllegalArgumentException e) {
186 catch (InvocationTargetException e) {
188 // JDK 1.1 stubs
189 RemoteStub stub = (RemoteStub)scls.newInstance();
190 UnicastRemoteStub.setStubRef(stub, this);
191 return (stub);
193 else {
194 // JDK 1.1 skel
195 return (scls.newInstance());
198 catch (ClassNotFoundException e) {
200 catch (InstantiationException e) {
202 catch (IllegalAccessException e) {
204 return (null);
209 public String getClientHost() throws ServerNotActiveException {
210 return RemoteServer.getClientHost();
213 private void buildMethodHash(Class cls, boolean build) {
214 Method[] meths = cls.getMethods();
215 for (int i = 0; i < meths.length; i++) {
216 /* Don't need to include any java.xxx related stuff */
217 if (meths[i].getDeclaringClass().getName().startsWith("java.")) {
218 continue;
220 long hash = RMIHashes.getMethodHash(meths[i]);
221 if(build)
222 methods.put(new Long (hash), meths[i]);
223 else
224 methods.remove(new Long (hash));
225 //System.out.println("meth = " + meths[i] + ", hash = " + hash);
229 Class getMethodReturnType(int method, long hash) throws Exception
231 if (method == -1) {
232 Method meth = (Method)methods.get(new Long (hash));
233 return meth.getReturnType();
234 }else
235 return null;
238 public Object incomingMessageCall(UnicastConnection conn, int method, long hash) throws Exception {
239 //System.out.println("method = " + method + ", hash = " + hash);
240 // If method is -1 then this is JDK 1.2 RMI - so use the hash
241 // to locate the method
242 if (method == -1) {
243 Method meth = (Method)methods.get(new Long (hash));
244 //System.out.println("class = " + myself.getClass() + ", meth = " + meth);
245 if (meth == null) {
246 throw new NoSuchMethodException();
249 ObjectInputStream in = conn.getObjectInputStream();
250 int nrargs = meth.getParameterTypes().length;
251 Object[] args = new Object[nrargs];
252 for (int i = 0; i < nrargs; i++) {
253 /**
254 * For debugging purposes - we don't handle CodeBases
255 * quite right so we don't always find the stubs. This
256 * lets us know that.
258 try {
259 // need to handle primitive types
260 args[i] = ((RMIObjectInputStream)in).readValue(meth.getParameterTypes()[i]);
263 catch (Exception t) {
264 t.printStackTrace();
265 throw t;
268 //We must reinterpret the exception thrown by meth.invoke()
269 //return (meth.invoke(myself, args));
270 Object ret = null;
271 try{
272 ret = meth.invoke(myself, args);
273 }catch(InvocationTargetException e){
274 Throwable cause = e.getTargetException();
275 if (cause instanceof Exception) {
276 throw (Exception)cause;
278 else if (cause instanceof Error) {
279 throw (Error)cause;
281 else {
282 throw new Error("The remote method threw a java.lang.Throwable that is neither java.lang.Exception nor java.lang.Error.", e);
285 return ret;
287 // Otherwise this is JDK 1.1 style RMI - we find the skeleton
288 // and invoke it using the method number. We wrap up our
289 // connection system in a UnicastRemoteCall so it appears in a
290 // way the Skeleton can handle.
291 else {
292 if (skel == null) {
293 throw new NoSuchMethodException();
295 UnicastRemoteCall call = new UnicastRemoteCall(conn);
296 skel.dispatch(myself, call, method, hash);
297 if (!call.isReturnValue())
298 return RMIVoidValue.INSTANCE;
299 else
300 return (call.returnValue());