]>
Commit | Line | Data |
---|---|---|
83e7315b TT |
1 | /* |
2 | Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GNU Classpath. | |
5 | ||
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. | |
10 | ||
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. | |
15 | ||
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. | |
20 | ||
92aaa246 MW |
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. | |
25 | ||
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. */ | |
83e7315b TT |
37 | |
38 | package gnu.java.rmi.server; | |
39 | ||
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.util.Hashtable; | |
67 | ||
68 | public class UnicastServerRef | |
d74732f5 TT |
69 | extends UnicastRef |
70 | implements ServerRef{ //SHOULD implement ServerRef | |
83e7315b TT |
71 | |
72 | final static private Class[] stubprototype = new Class[] { RemoteRef.class }; | |
73 | ||
74 | Remote myself; | |
75 | private Skeleton skel; | |
76 | private RemoteStub stub; | |
d74732f5 | 77 | private Hashtable methods = new Hashtable(); |
83e7315b TT |
78 | |
79 | public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) { | |
80 | super(id); | |
81 | manager = UnicastConnectionManager.getInstance(port, ssf); | |
82 | } | |
83 | ||
84 | public RemoteStub exportObject(Remote obj) throws RemoteException { | |
85 | if (myself == null) { | |
86 | myself = obj; | |
87 | ||
88 | // Find and install the stub | |
89 | Class cls = obj.getClass(); | |
90 | stub = (RemoteStub)getHelperClass(cls, "_Stub"); | |
91 | if (stub == null) { | |
92 | throw new RemoteException("failed to export: " + cls); | |
93 | } | |
94 | ||
95 | // Find and install the skeleton (if there is one) | |
96 | skel = (Skeleton)getHelperClass(cls, "_Skel"); | |
97 | ||
98 | // Build hash of methods which may be called. | |
d74732f5 | 99 | buildMethodHash(obj.getClass(), true); |
83e7315b TT |
100 | |
101 | // Export it. | |
102 | UnicastServer.exportObject(this); | |
103 | } | |
104 | ||
105 | return (stub); | |
106 | } | |
107 | ||
d74732f5 TT |
108 | public RemoteStub exportObject(Remote remote, Object obj) |
109 | throws RemoteException | |
110 | { | |
111 | //FIX ME | |
112 | return exportObject(remote); | |
113 | } | |
114 | ||
115 | ||
116 | public boolean unexportObject(Remote obj, boolean force) throws RemoteException { | |
117 | // Remove all hashes of methods which may be called. | |
118 | buildMethodHash(obj.getClass(), false); | |
119 | return UnicastServer.unexportObject(this, force); | |
120 | } | |
121 | ||
83e7315b TT |
122 | private Object getHelperClass(Class cls, String type) { |
123 | try { | |
d74732f5 TT |
124 | String classname = cls.getName(); |
125 | ClassLoader cl = cls.getClassLoader(); //DONT use "Class scls = Class.forName(classname + type);" | |
126 | Class scls = cl.loadClass(classname + type); | |
83e7315b TT |
127 | if (type.equals("_Stub")) { |
128 | try { | |
129 | // JDK 1.2 stubs | |
130 | Constructor con = scls.getConstructor(stubprototype); | |
131 | return (con.newInstance(new Object[]{this})); | |
132 | } | |
133 | catch (NoSuchMethodException e) { | |
134 | } | |
135 | catch (InstantiationException e) { | |
136 | } | |
137 | catch (IllegalAccessException e) { | |
138 | } | |
139 | catch (IllegalArgumentException e) { | |
140 | } | |
141 | catch (InvocationTargetException e) { | |
142 | } | |
143 | // JDK 1.1 stubs | |
144 | RemoteStub stub = (RemoteStub)scls.newInstance(); | |
145 | UnicastRemoteStub.setStubRef(stub, this); | |
146 | return (stub); | |
147 | } | |
148 | else { | |
149 | // JDK 1.1 skel | |
150 | return (scls.newInstance()); | |
151 | } | |
152 | } | |
153 | catch (ClassNotFoundException e) { | |
154 | } | |
155 | catch (InstantiationException e) { | |
156 | } | |
157 | catch (IllegalAccessException e) { | |
158 | } | |
159 | return (null); | |
160 | } | |
161 | ||
162 | public String getClientHost() throws ServerNotActiveException { | |
163 | throw new Error("Not implemented"); | |
164 | } | |
165 | ||
d74732f5 | 166 | private void buildMethodHash(Class cls, boolean build) { |
83e7315b TT |
167 | Method[] meths = cls.getMethods(); |
168 | for (int i = 0; i < meths.length; i++) { | |
169 | /* Don't need to include any java.xxx related stuff */ | |
170 | if (meths[i].getDeclaringClass().getName().startsWith("java.")) { | |
171 | continue; | |
172 | } | |
173 | long hash = RMIHashes.getMethodHash(meths[i]); | |
d74732f5 TT |
174 | if(build) |
175 | methods.put(new Long (hash), meths[i]); | |
176 | else | |
177 | methods.remove(new Long (hash)); | |
83e7315b TT |
178 | //System.out.println("meth = " + meths[i] + ", hash = " + hash); |
179 | } | |
180 | } | |
181 | ||
d74732f5 TT |
182 | Class getMethodReturnType(int method, long hash) throws Exception |
183 | { | |
184 | if (method == -1) { | |
185 | Method meth = (Method)methods.get(new Long (hash)); | |
186 | return meth.getReturnType(); | |
187 | }else | |
188 | return null; | |
189 | } | |
190 | ||
83e7315b TT |
191 | public Object incomingMessageCall(UnicastConnection conn, int method, long hash) throws Exception { |
192 | //System.out.println("method = " + method + ", hash = " + hash); | |
193 | // If method is -1 then this is JDK 1.2 RMI - so use the hash | |
194 | // to locate the method | |
195 | if (method == -1) { | |
196 | Method meth = (Method)methods.get(new Long (hash)); | |
197 | //System.out.println("class = " + myself.getClass() + ", meth = " + meth); | |
198 | if (meth == null) { | |
199 | throw new NoSuchMethodException(); | |
200 | } | |
201 | ||
202 | ObjectInputStream in = conn.getObjectInputStream(); | |
203 | int nrargs = meth.getParameterTypes().length; | |
204 | Object[] args = new Object[nrargs]; | |
205 | for (int i = 0; i < nrargs; i++) { | |
206 | /** | |
207 | * For debugging purposes - we don't handle CodeBases | |
208 | * quite right so we don't always find the stubs. This | |
209 | * lets us know that. | |
210 | */ | |
211 | try { | |
212 | args[i] = in.readObject(); | |
213 | } | |
214 | catch (Exception t) { | |
215 | t.printStackTrace(); | |
216 | throw t; | |
217 | } | |
218 | } | |
d74732f5 TT |
219 | //We must reinterpret the exception thrown by meth.invoke() |
220 | //return (meth.invoke(myself, args)); | |
221 | Object ret = null; | |
222 | try{ | |
223 | ret = meth.invoke(myself, args); | |
224 | }catch(InvocationTargetException e){ | |
225 | throw (Exception)(e.getTargetException()); | |
226 | } | |
227 | return ret; | |
83e7315b TT |
228 | } |
229 | // Otherwise this is JDK 1.1 style RMI - we find the skeleton | |
230 | // and invoke it using the method number. We wrap up our | |
231 | // connection system in a UnicastRemoteCall so it appears in a | |
232 | // way the Skeleton can handle. | |
233 | else { | |
234 | if (skel == null) { | |
235 | throw new NoSuchMethodException(); | |
236 | } | |
237 | UnicastRemoteCall call = new UnicastRemoteCall(conn); | |
238 | skel.dispatch(myself, call, method, hash); | |
239 | return (call.returnValue()); | |
240 | } | |
241 | } | |
242 | ||
243 | } |