diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/rmi/CORBA/PortableRemoteObjectDelegateImpl.java')
-rw-r--r-- | libjava/classpath/gnu/javax/rmi/CORBA/PortableRemoteObjectDelegateImpl.java | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/PortableRemoteObjectDelegateImpl.java b/libjava/classpath/gnu/javax/rmi/CORBA/PortableRemoteObjectDelegateImpl.java new file mode 100644 index 000000000..f430ac123 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/PortableRemoteObjectDelegateImpl.java @@ -0,0 +1,362 @@ +/* PortableRemoteObjectDelegateImpl.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.rmi.CORBA; + +import gnu.CORBA.SimpleDelegate; +import gnu.CORBA.Unexpected; +import gnu.CORBA.Poa.LocalDelegate; +import gnu.CORBA.Poa.ORB_1_4; +import gnu.CORBA.Poa.AOM; + +import java.rmi.NoSuchObjectException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.server.RMIClassLoader; + +import javax.rmi.CORBA.PortableRemoteObjectDelegate; +import javax.rmi.CORBA.Stub; +import javax.rmi.CORBA.Tie; +import javax.rmi.CORBA.Util; + +import org.omg.CORBA.BAD_PARAM; +import org.omg.CORBA.ORB; +import org.omg.CORBA.portable.Delegate; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.PortableServer.POA; +import org.omg.PortableServer.POAHelper; +import org.omg.PortableServer.Servant; +import org.omg.PortableServer.POAManagerPackage.State; + +/** + * Implements PortableRemoteObjectDelegate. + * + * @author Wu Gansha (gansha.wu@intel.com) (stub) + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation) + */ +public class PortableRemoteObjectDelegateImpl + implements PortableRemoteObjectDelegate +{ + /** + * <p> + * Makes the remote object <code>a_target</code> ready for remote + * communication using the same communications runtime as for the passed + * <code>a_source</code> parameter. The a_target is connected to the same + * ORB (and, if applicable, to the same POA) as the a_source. + * + * @param a_target the target to connect to ORB, must be an instance of either + * {@link ObjectImpl} (Stubs and old-style ties) or {@link Servant} (POA-bases + * ties). + * + * @param a_source the object, providing the connection information, must be + * an instance of either {@link ObjectImpl} (Stubs and old-style ties) or + * {@link Servant} (POA-bases ties). + * + * @throws RemoteException if the target is already connected to another ORB. + */ + public void connect(Remote a_target, Remote a_source) + throws RemoteException + { + ORB orb = null; + POA poa = null; + boolean ok = false; + + try + { + if (a_source instanceof Servant) + { + Servant s = (Servant) a_source; + orb = s._orb(); + poa = s._poa(); + ok = true; + } + + if (!ok && a_source instanceof ObjectImpl) + { + ObjectImpl o = (ObjectImpl) a_source; + orb = o._orb(); + ok = true; + try + { + if (orb instanceof ORB_1_4) + { + // POA information available. + ORB_1_4 xorb = (ORB_1_4) orb; + Delegate d = o._get_delegate(); + + if (d instanceof LocalDelegate) + { + LocalDelegate l = (LocalDelegate) d; + poa = l.poa; + } + else if (d instanceof SimpleDelegate) + { + byte[] ior_key = ((SimpleDelegate) d).getIor().key; + AOM.Obj ref = xorb.rootPOA.findIorKey(ior_key); + if (ref != null) + poa = ref.poa; + } + } + } + catch (Exception ex) + { + // OK, POA info is not available, but as ORB is available, we + // will connect in a default way. + } + } + } + catch (Exception ex) + { + RuntimeException rex = new RuntimeException("Unable to get info from " + + a_source); + rex.initCause(ex); + throw rex; + } + + if (!ok && a_source instanceof Tie) + { + Tie t = (Tie) a_source; + orb = t.orb(); + poa = null; + ok = true; + } + + if (orb == null) + throw new RemoteException("Unable to determine ORB from " + a_source); + + if (a_target instanceof Stub) + { + StubDelegateImpl.connect((Stub) a_target, orb, poa); + } + else if (a_target instanceof Servant) + { + try + { + if (poa == null) + { + poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); + // Activate if not active. + if (poa.the_POAManager().get_state().value() == State._HOLDING) + poa.the_POAManager().activate(); + } + poa.servant_to_reference((Servant) a_target); + } + catch (Exception ex) + { + throw new Unexpected(ex); + } + } + else if (a_target instanceof org.omg.CORBA.Object) + { + // Connect as object. + orb.connect((org.omg.CORBA.Object) a_target); + } + else if (a_target instanceof Tie) + { + // We avoid calling this because it will aways connect to the root poa. + ((Tie) a_target).orb(orb); + } + } + + /** + * Narrow the given object to the instance of the given class. The currently + * supported narrowing types are: + * + * 1. Simple widening conversion.<br> + * 2. ObjectImpl -> RMI interface.<br> + * 3. ObjectImpl -> ObjectImpl.<br> + * 4. Tie -> Remote (implementation)<br> + * 5. Remote (implementation) -> Tie.<br> + * + * The narrowing has sense only for derived classes. + */ + public Object narrow(Object narrowFrom, Class narrowTo) + throws ClassCastException + { + if (narrowTo == null) + throw new ClassCastException("Can't narrow to null class"); + else if (narrowFrom == null) + return null; + else + // Simple narrowing case. + if (narrowTo.isAssignableFrom(narrowFrom.getClass())) + return narrowFrom; + else if (narrowTo.isInterface() || narrowFrom instanceof ObjectImpl) + { + // Narrow CORBA object to passed interface. + + String interf = narrowTo.getName(); + String stubClassName; + + stubClassName = getStubClassName(interf); + + try + { + // Replace the interface class by the stub class. + narrowTo = Util.loadClass(stubClassName, null, + narrowTo.getClassLoader()); + } + catch (ClassNotFoundException e) + { + ClassCastException cex = new ClassCastException("Class not found: " + + stubClassName); + cex.initCause(e); + throw cex; + } + } + else if (narrowFrom instanceof Tie) + { + // Try to substitute the return tie target as a return value. + Remote target = ((Tie) narrowFrom).getTarget(); + if (target != null && narrowTo.isAssignableFrom(target.getClass())) + return target; + } + + Object narrowed; + try + { + narrowed = narrowTo.newInstance(); + } + catch (Exception e) + { + ClassCastException cex = new ClassCastException("Cannot instantiate " + + narrowTo.getName()); + cex.initCause(e); + throw cex; + } + + if (narrowed instanceof ObjectImpl) + { + // This also works for the instances of the Stub. + ObjectImpl target = (ObjectImpl) narrowed; + // Set the delegate, as is done in *Helper.narrow(..). + target._set_delegate(((ObjectImpl) narrowFrom)._get_delegate()); + } + else if (narrowed instanceof Tie && narrowFrom instanceof Remote) + { + // Try to set the narrowing object as a target for the Tie. + ((Tie) narrowed).setTarget((Remote) narrowFrom); + } + else + throw new ClassCastException("Narrowing of " + narrowFrom.getClass() + + " to " + narrowTo + " is either not possible or not implemented."); + + return narrowed; + } + + /** + * Get the Stub class name for the name, representing the given interface. + */ + static String getStubClassName(String interf) + { + String stubClassName; + int p = interf.lastIndexOf('.'); + + if (p < 0) + // The interface is defined in the default package. + stubClassName = "_" + interf + "_Stub"; + else + stubClassName = interf.substring(0, p + 1) + "_" + + interf.substring(p + 1) + "_Stub"; + return stubClassName; + } + + /** + * Get stub for the given implementation, searching by class name pattern. The + * found stub must implement Remote for this method to succeed. + */ + public Remote toStub(Remote ObjImpl) + throws NoSuchObjectException + { + String icn = ObjImpl.getClass().getName(); + if (!icn.endsWith("Impl")) + throw new BAD_PARAM("Invalid class name '" + icn + + "', must end with 'Impl'"); + + String sn = "_" + icn.substring(0, icn.length() - "Impl".length()) + + "_Stub"; + + Class stubClass; + Object o_stub; + + try + { + stubClass = RMIClassLoader.loadClass(sn); + o_stub = stubClass.newInstance(); + } + catch (Exception e) + { + NoSuchObjectException n = new NoSuchObjectException(sn); + n.initCause(e); + throw n; + } + + if (!Remote.class.isAssignableFrom(stubClass)) + throw new ClassCastException(stubClass.getName() + + " exists but cannot be returned as it does not inherit from " + + Remote.class.getName()); + + return (Remote) o_stub; + } + + /** + * If the object tie is no longer in use, disconnet it from the orb. + */ + public void unexportObject(Remote obj) + throws NoSuchObjectException + { + Util.unexportObject(obj); + } + + /** + * Find or create a tie for this target and mark it as being used by the given + * object. + */ + public void exportObject(Remote obj) + throws RemoteException + { + if (obj instanceof Stub) + Util.registerTarget(StubDelegateImpl.getTieFromStub((Stub) obj), obj); + else if (obj instanceof Tie) + { + Tie t = (Tie) obj; + Util.registerTarget(t, null); + } + } + +} |