1 /* StubDelegateImpl.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.ObjectCreator;
42 import gnu.CORBA.Unexpected;
43 import gnu.CORBA.CDR.BufferredCdrInput;
44 import gnu.CORBA.CDR.BufferedCdrOutput;
45 
46 import java.io.IOException;
47 import java.io.ObjectInputStream;
48 import java.io.ObjectOutputStream;
49 import java.rmi.Remote;
50 import java.rmi.RemoteException;
51 
52 import javax.rmi.PortableRemoteObject;
53 import javax.rmi.CORBA.Stub;
54 import javax.rmi.CORBA.StubDelegate;
55 import javax.rmi.CORBA.Tie;
56 import javax.rmi.CORBA.Util;
57 
58 import org.omg.CORBA.BAD_PARAM;
59 import org.omg.CORBA.ORB;
60 import org.omg.CORBA.portable.Delegate;
61 import org.omg.CORBA.portable.ObjectImpl;
62 import org.omg.PortableServer.POA;
63 import org.omg.PortableServer.POAHelper;
64 import org.omg.PortableServer.Servant;
65 import org.omg.PortableServer.POAManagerPackage.State;
66 
67 /**
68  * The default stub delegate.
69  *
70  * @author Wu Gansha (gansha.wu@intel.com) (stub)
71  * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation)
72  */
73 public class StubDelegateImpl
74   implements StubDelegate
75 {
76   /**
77    * <p>
78    * Finds the suitable {@link Tie} for this Stub and connects it to the given
79    * ORB. The tie is found by the name pattern. If the found tie is derived from
80    * {@link org.omg.CORBA.PortableServer.Servant}, it is connected to the root
81    * POA, also activating it (if not already active).
82    * </p>
83    * <p>
84    * This method does not allow to specify, to which POA the found Tie must be
85    * connected and requires to use the deprecated method {@link ORB#connect}.
86    * Many useful POA features remain unaccessible. A better alternative it might
87    * be to generate a {@link org.omg.CORBA.PortableServer.Servant} - derived Tie
88    * (-poa key in rmic) and connect it to POA in one of the many ways, listed in
89    * the description of the {@link orb.omg.PortableServer} package). The
90    * obtained CORBA object can be narrowed into stub using
91    * {@link PortableRemoteObject#narrow}.
92    * </p>
93    *
94    * @param orb the ORB where the Stub must be connected.
95    *
96    * @throws RemoteException if the stub is already connected to some other ORB.
97    * If the stub is already connected to the ORB that was passed as parameter,
98    * the method returns without action.
99    *
100    * @throws BAD_PARAM if the name of this stub does not match the stub name
101    * pattern, "_*_Stub" or if the Tie class, "_*Impl_Tie", does not exists or an
102    * instance of this class cannot be instantiated.
103    */
connect(Stub self, ORB orb)104   public void connect(Stub self, ORB orb)
105     throws RemoteException
106   {
107     connect(self, orb, null);
108   }
109 
110   /**
111    * Connect when the POA is specified.
112    */
connect(Stub self, ORB orb, POA poa)113   public static void connect(Stub self, ORB orb, POA poa)
114     throws RemoteException
115   {
116     ORB oorb = null;
117     try
118       {
119         Delegate d = self._get_delegate();
120         if (d != null)
121           oorb = d.orb(self);
122       }
123     catch (Exception e)
124       {
125         // Failed to get Delegate or ORB.
126         // (possible ony for user-written Stubs).
127       }
128 
129     if (oorb != null)
130       {
131         if (!oorb.equals(orb))
132           throw new RemoteException("Stub " + self
133             + " is connected to another ORB, " + orb);
134         else
135           return;
136       }
137 
138     Tie t = null;
139     if (self instanceof Remote)
140       t = Util.getTie((Remote) self);
141 
142     // Find by name pattern.
143     if (t == null)
144       t = getTieFromStub(self);
145 
146     Delegate delegate;
147 
148     if (t instanceof Servant)
149       {
150         try
151           {
152             if (poa == null)
153               {
154                 poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
155                 // Activate if not active.
156                 if (poa.the_POAManager().get_state().value() == State._HOLDING)
157                   poa.the_POAManager().activate();
158               }
159 
160             ObjectImpl obj = (ObjectImpl) poa.servant_to_reference((Servant) t);
161             delegate = obj._get_delegate();
162           }
163         catch (Exception ex)
164           {
165             throw new Unexpected(ex);
166           }
167       }
168     else if (t instanceof ObjectImpl)
169       {
170         ObjectImpl o = (ObjectImpl) t;
171         orb.connect(o);
172         delegate = o._get_delegate();
173       }
174     else
175       throw new BAD_PARAM("The Tie must be either Servant or ObjectImpl");
176 
177     self._set_delegate(delegate);
178   }
179 
180   /**
181    * Locate a tie class, appropriate to the given stub class, by the name
182    * pattern.
183    */
getTieFromStub(java.lang.Object self)184   public static Tie getTieFromStub(java.lang.Object self)
185   {
186     Tie t;
187     String sn = self.getClass().getName();
188     if (!sn.endsWith("_Stub"))
189       throw new BAD_PARAM("The stub name, " + sn
190         + ", does not match _*_Stub pattern");
191 
192     String tn = sn.substring(0, sn.length() - "_Stub".length()) + "Impl_Tie";
193     Class tieClass = null;
194 
195     try
196       {
197         tieClass = ObjectCreator.forName(tn);
198         t = (Tie) tieClass.newInstance();
199         if (self instanceof Remote)
200           Util.registerTarget(t, (Remote) self);
201       }
202     catch (Exception e)
203       {
204         BAD_PARAM bad = new BAD_PARAM("Unable to instantiate '" + tn + "'");
205         bad.initCause(e);
206         throw bad;
207       }
208     return t;
209   }
210 
211   /**
212    * Compare two stubs for equality.
213    */
equals(Stub self, java.lang.Object obj)214   public boolean equals(Stub self, java.lang.Object obj)
215   {
216     if (obj instanceof ObjectImpl)
217       {
218         ObjectImpl other = (ObjectImpl) obj;
219         Delegate d1 = other._get_delegate();
220         Delegate d2 = self._get_delegate();
221         if (d1 == null || d2 == null)
222           return d1 == d2;
223         else
224           return d1.equals(d2);
225       }
226     else return false;
227   }
228 
229   /**
230    * Get the hash code (from IOR reference).
231    */
hashCode(Stub self)232   public int hashCode(Stub self)
233   {
234     Delegate d = self._get_delegate();
235     return d==null?0:d.hashCode();
236   }
237 
238   /**
239    * Returns the IOR reference of the connected ORB.
240    *
241    * @see ORB#object_to_string(org.omg.CORBA.Object);
242    */
toString(Stub self)243   public String toString(Stub self)
244   {
245     try
246       {
247         return self._orb().object_to_string(self);
248       }
249     catch (Exception ex)
250       {
251         return null;
252       }
253   }
254 
255   /**
256    * This should never be called. The ORB must be supplied.
257    *
258    * @see #connect
259    */
readObject(Stub self, ObjectInputStream input)260   public void readObject(Stub self, ObjectInputStream input)
261     throws IOException, ClassNotFoundException
262   {
263     readObject(self, input, null);
264   }
265 
266   /**
267    * Read as CORBA object when the ORB is known. The ORB must be set under the
268    * previous call of Stub.connect. The Stub is automatically registered with
269    * this ORB.
270    */
readObject(Stub self, ObjectInputStream input, ORB orb)271   public void readObject(Stub self, ObjectInputStream input, ORB orb)
272     throws IOException, ClassNotFoundException
273   {
274     byte[] b = (byte[]) input.readObject();
275     BufferredCdrInput in = new BufferredCdrInput(b);
276 
277     if (orb != null)
278       in.setOrb(orb);
279 
280     ObjectImpl r = (ObjectImpl) in.read_Object();
281 
282     self._set_delegate(r._get_delegate());
283   }
284 
285   /**
286    * Write as CORBA object. The ORB is taken from the
287    * org.omg.CORBA.portable.Delegate. The Stub is automatically registered with
288    * this ORB (if not already done).
289    */
writeObject(Stub self, ObjectOutputStream output)290   public void writeObject(Stub self, ObjectOutputStream output)
291     throws IOException
292   {
293     writeObject(self, output, null);
294   }
295 
296   /**
297    * Write as CORBA object. The ORB must be either set under the previous call
298    * of Stub.connect or it is taken from the org.omg.CORBA.portable.Delegate.
299    * The Stub is automatically registered with this ORB (if not already done).
300    */
writeObject(Stub self, ObjectOutputStream output, ORB orb)301   public void writeObject(Stub self, ObjectOutputStream output, ORB orb)
302     throws IOException
303   {
304     BufferedCdrOutput out = new BufferedCdrOutput();
305     out.setOrb(orb == null ? self._orb() : orb);
306     out.write_Object(self);
307 
308     output.writeObject(out.buffer.toByteArray());
309   }
310 }
311