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