1 |
/* PortableRemoteObjectDelegateImpl.java -- |
/* PortableRemoteObjectDelegateImpl.java -- |
2 |
Copyright (C) 2002, 2004 Free Software Foundation, Inc. |
Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
38 |
|
|
39 |
package gnu.javax.rmi.CORBA; |
package gnu.javax.rmi.CORBA; |
40 |
|
|
41 |
import gnu.javax.rmi.PortableServer; |
import gnu.CORBA.SimpleDelegate; |
42 |
|
import gnu.CORBA.Unexpected; |
43 |
|
import gnu.CORBA.Poa.LocalDelegate; |
44 |
|
import gnu.CORBA.Poa.ORB_1_4; |
45 |
|
import gnu.CORBA.Poa.AOM; |
46 |
|
|
47 |
import java.rmi.NoSuchObjectException; |
import java.rmi.NoSuchObjectException; |
48 |
import java.rmi.Remote; |
import java.rmi.Remote; |
49 |
import java.rmi.RemoteException; |
import java.rmi.RemoteException; |
50 |
|
import java.rmi.server.RMIClassLoader; |
51 |
|
|
52 |
import javax.rmi.CORBA.PortableRemoteObjectDelegate; |
import javax.rmi.CORBA.PortableRemoteObjectDelegate; |
53 |
|
import javax.rmi.CORBA.Stub; |
54 |
|
import javax.rmi.CORBA.Tie; |
55 |
|
import javax.rmi.CORBA.Util; |
56 |
|
|
57 |
|
import org.omg.CORBA.BAD_PARAM; |
58 |
|
import org.omg.CORBA.ORB; |
59 |
|
import org.omg.CORBA.portable.Delegate; |
60 |
|
import org.omg.CORBA.portable.ObjectImpl; |
61 |
|
import org.omg.PortableServer.POA; |
62 |
|
import org.omg.PortableServer.POAHelper; |
63 |
|
import org.omg.PortableServer.Servant; |
64 |
|
import org.omg.PortableServer.POAManagerPackage.State; |
65 |
|
|
66 |
|
/** |
67 |
|
* Implements PortableRemoteObjectDelegate. |
68 |
|
* |
69 |
|
* @author Wu Gansha (gansha.wu@intel.com) (stub) |
70 |
|
* @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation) |
71 |
|
*/ |
72 |
public class PortableRemoteObjectDelegateImpl |
public class PortableRemoteObjectDelegateImpl |
73 |
implements PortableRemoteObjectDelegate |
implements PortableRemoteObjectDelegate |
74 |
{ |
{ |
75 |
|
/** |
76 |
public PortableRemoteObjectDelegateImpl() |
* <p> |
77 |
{ |
* Makes the remote object <code>a_target</code> ready for remote |
78 |
} |
* communication using the same communications runtime as for the passed |
79 |
|
* <code>a_source</code> parameter. The a_target is connected to the same |
80 |
public void connect(Remote remote, Remote remote1) |
* ORB (and, if applicable, to the same POA) as the a_source. |
81 |
throws RemoteException |
* |
82 |
{ |
* @param a_target the target to connect to ORB, must be an instance of either |
83 |
throw new Error("Not implemented for PortableRemoteObjectDelegateImpl"); |
* {@link ObjectImpl} (Stubs and old-style ties) or {@link Servant} (POA-bases |
84 |
} |
* ties). |
85 |
|
* |
86 |
public void exportObject(Remote obj) |
* @param a_source the object, providing the connection information, must be |
87 |
|
* an instance of either {@link ObjectImpl} (Stubs and old-style ties) or |
88 |
|
* {@link Servant} (POA-bases ties). |
89 |
|
* |
90 |
|
* @throws RemoteException if the target is already connected to another ORB. |
91 |
|
*/ |
92 |
|
public void connect(Remote a_target, Remote a_source) |
93 |
throws RemoteException |
throws RemoteException |
94 |
{ |
{ |
95 |
PortableServer.exportObject(obj); |
ORB orb = null; |
96 |
|
POA poa = null; |
97 |
|
boolean ok = false; |
98 |
|
|
99 |
|
try |
100 |
|
{ |
101 |
|
if (a_source instanceof Servant) |
102 |
|
{ |
103 |
|
Servant s = (Servant) a_source; |
104 |
|
orb = s._orb(); |
105 |
|
poa = s._poa(); |
106 |
|
ok = true; |
107 |
|
} |
108 |
|
|
109 |
|
if (!ok && a_source instanceof ObjectImpl) |
110 |
|
{ |
111 |
|
ObjectImpl o = (ObjectImpl) a_source; |
112 |
|
orb = o._orb(); |
113 |
|
ok = true; |
114 |
|
try |
115 |
|
{ |
116 |
|
if (orb instanceof ORB_1_4) |
117 |
|
{ |
118 |
|
// POA information available. |
119 |
|
ORB_1_4 xorb = (ORB_1_4) orb; |
120 |
|
Delegate d = o._get_delegate(); |
121 |
|
|
122 |
|
if (d instanceof LocalDelegate) |
123 |
|
{ |
124 |
|
LocalDelegate l = (LocalDelegate) d; |
125 |
|
poa = l.poa; |
126 |
|
} |
127 |
|
else if (d instanceof SimpleDelegate) |
128 |
|
{ |
129 |
|
byte[] ior_key = ((SimpleDelegate) d).getIor().key; |
130 |
|
AOM.Obj ref = xorb.rootPOA.findIorKey(ior_key); |
131 |
|
if (ref != null) |
132 |
|
poa = ref.poa; |
133 |
|
} |
134 |
|
} |
135 |
|
} |
136 |
|
catch (Exception ex) |
137 |
|
{ |
138 |
|
// OK, POA info is not available, but as ORB is available, we |
139 |
|
// will connect in a default way. |
140 |
|
} |
141 |
|
} |
142 |
|
} |
143 |
|
catch (Exception ex) |
144 |
|
{ |
145 |
|
RuntimeException rex = new RuntimeException("Unable to get info from " |
146 |
|
+ a_source); |
147 |
|
rex.initCause(ex); |
148 |
|
throw rex; |
149 |
|
} |
150 |
|
|
151 |
|
if (!ok && a_source instanceof Tie) |
152 |
|
{ |
153 |
|
Tie t = (Tie) a_source; |
154 |
|
orb = t.orb(); |
155 |
|
poa = null; |
156 |
|
ok = true; |
157 |
|
} |
158 |
|
|
159 |
|
if (orb == null) |
160 |
|
throw new RemoteException("Unable to determine ORB from " + a_source); |
161 |
|
|
162 |
|
if (a_target instanceof Stub) |
163 |
|
{ |
164 |
|
StubDelegateImpl.connect((Stub) a_target, orb, poa); |
165 |
|
} |
166 |
|
else if (a_target instanceof Servant) |
167 |
|
{ |
168 |
|
try |
169 |
|
{ |
170 |
|
if (poa == null) |
171 |
|
{ |
172 |
|
poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); |
173 |
|
// Activate if not active. |
174 |
|
if (poa.the_POAManager().get_state().value() == State._HOLDING) |
175 |
|
poa.the_POAManager().activate(); |
176 |
|
} |
177 |
|
poa.servant_to_reference((Servant) a_target); |
178 |
|
} |
179 |
|
catch (Exception ex) |
180 |
|
{ |
181 |
|
throw new Unexpected(ex); |
182 |
|
} |
183 |
|
} |
184 |
|
else if (a_target instanceof org.omg.CORBA.Object) |
185 |
|
{ |
186 |
|
// Connect as object. |
187 |
|
orb.connect((org.omg.CORBA.Object) a_target); |
188 |
|
} |
189 |
|
else if (a_target instanceof Tie) |
190 |
|
{ |
191 |
|
// We avoid calling this because it will aways connect to the root poa. |
192 |
|
((Tie) a_target).orb(orb); |
193 |
|
} |
194 |
} |
} |
195 |
|
|
196 |
|
/** |
197 |
|
* Narrow the given object to the instance of the given class. The currently |
198 |
|
* supported narrowing types are: |
199 |
|
* |
200 |
|
* 1. Simple widening conversion.<br> |
201 |
|
* 2. ObjectImpl -> RMI interface.<br> |
202 |
|
* 3. ObjectImpl -> ObjectImpl.<br> |
203 |
|
* 4. Tie -> Remote (implementation)<br> |
204 |
|
* 5. Remote (implementation) -> Tie.<br> |
205 |
|
* |
206 |
|
* The narrowing has sense only for derived classes. |
207 |
|
*/ |
208 |
public Object narrow(Object narrowFrom, Class narrowTo) |
public Object narrow(Object narrowFrom, Class narrowTo) |
209 |
throws ClassCastException |
throws ClassCastException |
210 |
{ |
{ |
211 |
if (narrowTo == null) |
if (narrowTo == null) |
212 |
throw new ClassCastException("Can't narrow to null class"); |
throw new ClassCastException("Can't narrow to null class"); |
213 |
if (narrowFrom == null) |
else if (narrowFrom == null) |
214 |
return null; |
return null; |
215 |
|
else |
216 |
|
// Simple narrowing case. |
217 |
|
if (narrowTo.isAssignableFrom(narrowFrom.getClass())) |
218 |
|
return narrowFrom; |
219 |
|
else if (narrowTo.isInterface() || narrowFrom instanceof ObjectImpl) |
220 |
|
{ |
221 |
|
// Narrow CORBA object to passed interface. |
222 |
|
|
223 |
Class fromClass = narrowFrom.getClass(); |
String interf = narrowTo.getName(); |
224 |
Object result = null; |
String stubClassName; |
225 |
|
|
226 |
|
stubClassName = getStubClassName(interf); |
227 |
|
|
228 |
|
try |
229 |
|
{ |
230 |
|
// Replace the interface class by the stub class. |
231 |
|
narrowTo = Util.loadClass(stubClassName, null, |
232 |
|
narrowTo.getClassLoader()); |
233 |
|
} |
234 |
|
catch (ClassNotFoundException e) |
235 |
|
{ |
236 |
|
ClassCastException cex = new ClassCastException("Class not found: " |
237 |
|
+ stubClassName); |
238 |
|
cex.initCause(e); |
239 |
|
throw cex; |
240 |
|
} |
241 |
|
} |
242 |
|
else if (narrowFrom instanceof Tie) |
243 |
|
{ |
244 |
|
// Try to substitute the return tie target as a return value. |
245 |
|
Remote target = ((Tie) narrowFrom).getTarget(); |
246 |
|
if (target != null && narrowTo.isAssignableFrom(target.getClass())) |
247 |
|
return target; |
248 |
|
} |
249 |
|
|
250 |
|
Object narrowed; |
251 |
try |
try |
252 |
{ |
{ |
253 |
if (narrowTo.isAssignableFrom(fromClass)) |
narrowed = narrowTo.newInstance(); |
254 |
result = narrowFrom; |
} |
255 |
else |
catch (Exception e) |
256 |
{ |
{ |
257 |
System.out.println("We still haven't implement this case: narrow " |
ClassCastException cex = new ClassCastException("Cannot instantiate " |
258 |
+ narrowFrom + " of type " + fromClass + " to " |
+ narrowTo.getName()); |
259 |
+ narrowTo); |
cex.initCause(e); |
260 |
Class[] cs = fromClass.getInterfaces(); |
throw cex; |
261 |
for (int i = 0; i < cs.length; i++) |
} |
262 |
System.out.println(cs[i]); |
|
263 |
Exception e1 = new Exception(); |
if (narrowed instanceof ObjectImpl) |
264 |
try |
{ |
265 |
{ |
// This also works for the instances of the Stub. |
266 |
throw e1; |
ObjectImpl target = (ObjectImpl) narrowed; |
267 |
} |
// Set the delegate, as is done in *Helper.narrow(..). |
268 |
catch(Exception ee) |
target._set_delegate(((ObjectImpl) narrowFrom)._get_delegate()); |
269 |
{ |
} |
270 |
ee.printStackTrace(); |
else if (narrowed instanceof Tie && narrowFrom instanceof Remote) |
271 |
} |
{ |
272 |
System.exit(2); |
// Try to set the narrowing object as a target for the Tie. |
273 |
//throw new Error("We still haven't implement this case: narrow " |
((Tie) narrowed).setTarget((Remote) narrowFrom); |
274 |
// + narrowFrom + " of type " + fromClass + " to " |
} |
275 |
// + narrowTo); |
else |
276 |
/* |
throw new ClassCastException("Narrowing of " + narrowFrom.getClass() |
277 |
ObjectImpl objimpl = (ObjectImpl)narrowFrom; |
+ " to " + narrowTo + " is either not possible or not implemented."); |
278 |
if(objimpl._is_a(PortableServer.getTypeName(narrowTo))) |
|
279 |
result = PortableServer.getStubFromObjectImpl(objimpl, narrowTo); |
return narrowed; |
280 |
*/ |
} |
281 |
} |
|
282 |
} |
/** |
283 |
catch(Exception e) |
* Get the Stub class name for the name, representing the given interface. |
284 |
{ |
*/ |
285 |
result = null; |
static String getStubClassName(String interf) |
286 |
} |
{ |
287 |
|
String stubClassName; |
288 |
if (result == null) |
int p = interf.lastIndexOf('.'); |
289 |
throw new ClassCastException("Can't narrow from " |
|
290 |
+ fromClass + " to " + narrowTo); |
if (p < 0) |
291 |
|
// The interface is defined in the default package. |
292 |
return result; |
stubClassName = "_" + interf + "_Stub"; |
293 |
|
else |
294 |
|
stubClassName = interf.substring(0, p + 1) + "_" |
295 |
|
+ interf.substring(p + 1) + "_Stub"; |
296 |
|
return stubClassName; |
297 |
} |
} |
298 |
|
|
299 |
public Remote toStub(Remote obj) |
/** |
300 |
|
* Get stub for the given implementation, searching by class name pattern. The |
301 |
|
* found stub must implement Remote for this method to succeed. |
302 |
|
*/ |
303 |
|
public Remote toStub(Remote ObjImpl) |
304 |
throws NoSuchObjectException |
throws NoSuchObjectException |
305 |
{ |
{ |
306 |
return PortableServer.toStub(obj); |
String icn = ObjImpl.getClass().getName(); |
307 |
|
if (!icn.endsWith("Impl")) |
308 |
|
throw new BAD_PARAM("Invalid class name '" + icn |
309 |
|
+ "', must end with 'Impl'"); |
310 |
|
|
311 |
|
String sn = "_" + icn.substring(0, icn.length() - "Impl".length()) |
312 |
|
+ "_Stub"; |
313 |
|
|
314 |
|
Class stubClass; |
315 |
|
Object o_stub; |
316 |
|
|
317 |
|
try |
318 |
|
{ |
319 |
|
stubClass = RMIClassLoader.loadClass(sn); |
320 |
|
o_stub = stubClass.newInstance(); |
321 |
|
} |
322 |
|
catch (Exception e) |
323 |
|
{ |
324 |
|
NoSuchObjectException n = new NoSuchObjectException(sn); |
325 |
|
n.initCause(e); |
326 |
|
throw n; |
327 |
|
} |
328 |
|
|
329 |
|
if (!Remote.class.isAssignableFrom(stubClass)) |
330 |
|
throw new ClassCastException(stubClass.getName() |
331 |
|
+ " exists but cannot be returned as it does not inherit from " |
332 |
|
+ Remote.class.getName()); |
333 |
|
|
334 |
|
return (Remote) o_stub; |
335 |
} |
} |
336 |
|
|
337 |
|
/** |
338 |
|
* If the object tie is no longer in use, disconnet it from the orb. |
339 |
|
*/ |
340 |
public void unexportObject(Remote obj) |
public void unexportObject(Remote obj) |
341 |
throws NoSuchObjectException |
throws NoSuchObjectException |
342 |
{ |
{ |
343 |
PortableServer.unexportObject(obj); |
Util.unexportObject(obj); |
344 |
|
} |
345 |
|
|
346 |
|
/** |
347 |
|
* Find or create a tie for this target and mark it as being used by the given |
348 |
|
* object. |
349 |
|
*/ |
350 |
|
public void exportObject(Remote obj) |
351 |
|
throws RemoteException |
352 |
|
{ |
353 |
|
if (obj instanceof Stub) |
354 |
|
Util.registerTarget(StubDelegateImpl.getTieFromStub((Stub) obj), obj); |
355 |
|
else if (obj instanceof Tie) |
356 |
|
{ |
357 |
|
Tie t = (Tie) obj; |
358 |
|
Util.registerTarget(t, null); |
359 |
|
} |
360 |
} |
} |
361 |
|
|
362 |
} |
} |