1 /* PortableRemoteObjectDelegateImpl.java --
2    Copyright (C) 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
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. */
37 
38 
39 package gnu.javax.rmi.CORBA;
40 
41 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;
48 import java.rmi.Remote;
49 import java.rmi.RemoteException;
50 import java.rmi.server.RMIClassLoader;
51 
52 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
73   implements PortableRemoteObjectDelegate
74 {
75   /**
76    * <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    * ORB (and, if applicable, to the same POA) as the a_source.
81    *
82    * @param a_target the target to connect to ORB, must be an instance of either
83    * {@link ObjectImpl} (Stubs and old-style ties) or {@link Servant} (POA-bases
84    * ties).
85    *
86    * @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    */
connect(Remote a_target, Remote a_source)92   public void connect(Remote a_target, Remote a_source)
93     throws RemoteException
94   {
95     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    */
narrow(Object narrowFrom, Class narrowTo)208   public Object narrow(Object narrowFrom, Class narrowTo)
209     throws ClassCastException
210   {
211     if (narrowTo == null)
212       throw new ClassCastException("Can't narrow to null class");
213     else if (narrowFrom == null)
214       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         String interf = narrowTo.getName();
224         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
252       {
253         narrowed = narrowTo.newInstance();
254       }
255     catch (Exception e)
256       {
257         ClassCastException cex = new ClassCastException("Cannot instantiate "
258           + narrowTo.getName());
259         cex.initCause(e);
260         throw cex;
261       }
262 
263     if (narrowed instanceof ObjectImpl)
264       {
265         // This also works for the instances of the Stub.
266         ObjectImpl target = (ObjectImpl) narrowed;
267         // Set the delegate, as is done in *Helper.narrow(..).
268         target._set_delegate(((ObjectImpl) narrowFrom)._get_delegate());
269       }
270     else if (narrowed instanceof Tie && narrowFrom instanceof Remote)
271       {
272         // Try to set the narrowing object as a target for the Tie.
273         ((Tie) narrowed).setTarget((Remote) narrowFrom);
274       }
275     else
276       throw new ClassCastException("Narrowing of " + narrowFrom.getClass()
277         + " to " + narrowTo + " is either not possible or not implemented.");
278 
279     return narrowed;
280   }
281 
282   /**
283    * Get the Stub class name for the name, representing the given interface.
284    */
getStubClassName(String interf)285   static String getStubClassName(String interf)
286   {
287     String stubClassName;
288     int p = interf.lastIndexOf('.');
289 
290     if (p < 0)
291       // The interface is defined in the default package.
292       stubClassName = "_" + interf + "_Stub";
293     else
294       stubClassName = interf.substring(0, p + 1) + "_"
295         + interf.substring(p + 1) + "_Stub";
296     return stubClassName;
297   }
298 
299   /**
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    */
toStub(Remote ObjImpl)303   public Remote toStub(Remote ObjImpl)
304     throws NoSuchObjectException
305   {
306     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    */
unexportObject(Remote obj)340   public void unexportObject(Remote obj)
341     throws NoSuchObjectException
342   {
343     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    */
exportObject(Remote obj)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 }
363