diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/rmi/CORBA')
11 files changed, 3384 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/CorbaInput.java b/libjava/classpath/gnu/javax/rmi/CORBA/CorbaInput.java new file mode 100644 index 000000000..5880c85c5 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/CorbaInput.java @@ -0,0 +1,297 @@ +/* CorbaInput.java -- + Copyright (C) 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.CDR.gnuRuntime; + +import org.omg.CORBA_2_3.portable.InputStream; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.Serializable; + +/** + * Converts calls on java ObjectOutputStream to calls on CORBA OutputStream. A + * class to substitute for objects using readObject method. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class CorbaInput + extends ObjectInputStream + implements ObjectInput +{ + + /** + * The underlying CORBA stream from where the actual input is taken. + */ + public InputStream stream; + + /** + * The utility class to write the object fields in default way. + */ + final RmiUtilities util; + + /** + * The object currently being read. + */ + Object current; + + /** + * The offset of the object currently being read. + */ + int offset; + + /** + * The repository id of the object currently being read. + */ + String rid; + + /** + * The runtime, related to the object currently being read. + */ + gnuRuntime runtime; + + /** + * Create an instance, delegating calls to the given CORBA stream. + */ + public CorbaInput(InputStream an_input, Object firstObject, + RmiUtilities an_util, int an_offset, String a_rid, + gnuRuntime a_runtime) + throws Exception + { + stream = an_input; + current = firstObject; + util = an_util; + + offset = an_offset; + rid = a_rid; + runtime = a_runtime; + } + + /** @inheritDoc */ + public int available() + throws IOException + { + return stream.available(); + } + + /** + * No action. + */ + public void close() + throws IOException + { + } + + /** @inheritDoc */ + public void defaultReadObject() + throws IOException, ClassNotFoundException + { + util.readFields(offset, rid, (Serializable) current, stream, runtime); + } + + /** @inheritDoc */ + public void mark(int readlimit) + { + stream.mark(readlimit); + } + + /** @inheritDoc */ + public boolean markSupported() + { + return stream.markSupported(); + } + + /** @inheritDoc */ + public int read() + throws IOException + { + return stream.read(); + } + + /** @inheritDoc */ + public int read(byte[] buf, int off, int len) + throws IOException + { + return stream.read(buf, off, len); + } + + /** @inheritDoc */ + public int read(byte[] b) + throws IOException + { + return stream.read(b); + } + + /** @inheritDoc */ + public boolean readBoolean() + throws IOException + { + return stream.read_boolean(); + } + + /** @inheritDoc */ + public byte readByte() + throws IOException + { + return (byte) stream.read(); + } + + /** @inheritDoc */ + public char readChar() + throws IOException + { + return stream.read_char(); + } + + /** @inheritDoc */ + public double readDouble() + throws IOException + { + return stream.read_double(); + } + + /** @inheritDoc */ + public float readFloat() + throws IOException + { + return stream.read_float(); + } + + /** @inheritDoc */ + public void readFully(byte[] buf, int off, int len) + throws IOException + { + // This class only reads from the buffered streams. + stream.read(buf, off, len); + } + + /** @inheritDoc */ + public void readFully(byte[] buf) + throws IOException + { + // This class only reads from the buffered streams. + stream.read(buf); + } + + /** @inheritDoc */ + public int readInt() + throws IOException + { + return stream.read_long(); + } + + /** @inheritDoc */ + public String readLine() + throws IOException + { + return new DataInputStream(this).readLine(); + } + + /** @inheritDoc */ + public long readLong() + throws IOException + { + return stream.read_longlong(); + } + + /** @inheritDoc */ + public short read_short() + throws IOException + { + return stream.read_short(); + } + + /** @inheritDoc */ + public int readUnsignedByte() + throws IOException + { + return (stream.read() & 0xFF); + } + + /** @inheritDoc */ + public int readUnsignedShort() + throws IOException + { + return (stream.read_short() & 0xFFFF); + } + + /** + * Read as wide string (not as UTF). + */ + public String readUTF() + throws IOException + { + return stream.read_wstring(); + } + + /** @inheritDoc */ + public void reset() + throws IOException + { + stream.reset(); + } + + /** @inheritDoc */ + public long skip(long n) + throws IOException + { + return stream.skip(n); + } + + /** @inheritDoc */ + public int skipBytes(int len) + throws IOException + { + return (int) stream.skip(len); + } + + /** + * Objects are read as abstract interfaces. + */ + protected Object readObjectOverride() + throws IOException, ClassNotFoundException + { + current = stream.read_abstract_interface(); + return current; + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/CorbaOutput.java b/libjava/classpath/gnu/javax/rmi/CORBA/CorbaOutput.java new file mode 100644 index 000000000..1d1480511 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/CorbaOutput.java @@ -0,0 +1,219 @@ +/* CorbaOutput.java -- + Copyright (C) 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 org.omg.CORBA_2_3.portable.OutputStream; + +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * A class to substitute as an ObjectOutputStream for objects using writeObject + * method. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class CorbaOutput + extends ObjectOutputStream + implements ObjectOutput +{ + /** + * A CORBA stream where the output is forwarded. + */ + final OutputStream stream; + + /** + * The utility class to write the object fields in default way. + */ + final RmiUtilities util; + + /** + * The object currently being written. + */ + Object current; + + /** + * Create an instance, delegating calls to the given CORBA stream. + */ + public CorbaOutput(OutputStream an_output, Object firstObject, + RmiUtilities an_util) + throws Exception + { + stream = an_output; + current = firstObject; + util = an_util; + } + + /** + * No action. + */ + public void close() + throws IOException + { + } + + /** @inheritDoc */ + public void flush() + throws IOException + { + stream.flush(); + } + + /** @inheritDoc */ + public void write(byte[] buf, int off, int len) + throws IOException + { + stream.write(buf, off, len); + } + + /** @inheritDoc */ + public void write(byte[] buf) + throws IOException + { + stream.write(buf); + } + + /** @inheritDoc */ + public void write(int val) + throws IOException + { + stream.write(val); + } + + /** @inheritDoc */ + public void writeBoolean(boolean val) + throws IOException + { + stream.write_boolean(val); + } + + /** @inheritDoc */ + public void writeByte(int val) + throws IOException + { + stream.write(val); + } + + /** @inheritDoc */ + public void writeBytes(String str) + throws IOException + { + stream.write_string(str); + } + + /** @inheritDoc */ + public void writeChar(int val) + throws IOException + { + stream.write_wchar((char) val); + } + + /** @inheritDoc */ + public void writeChars(String str) + throws IOException + { + stream.write_char_array(str.toCharArray(), 0, str.length()); + } + + /** @inheritDoc */ + public void writeDouble(double val) + throws IOException + { + stream.write_double(val); + } + + /** @inheritDoc */ + public void writeFloat(float val) + throws IOException + { + stream.write_float(val); + } + + /** @inheritDoc */ + public void writeInt(int val) + throws IOException + { + stream.write_long(val); + } + + /** @inheritDoc */ + public void writeLong(long val) + throws IOException + { + stream.write_longlong(val); + } + + /** + * Objects are written as abstract interfaces. + */ + protected void writeObjectOverride(Object obj) + throws IOException + { + current = obj; + stream.write_abstract_interface(obj); + } + + /** @inheritDoc */ + public void writeShort(int val) + throws IOException + { + stream.write_short((short) val); + } + + /** + * Such strings are written as wide strings, not as UTF. + */ + public void writeUTF(String str) + throws IOException + { + stream.write_wstring(str); + } + + /** + * @inheritDoc + */ + public void defaultWriteObject() + throws IOException + { + util.writeFields(stream, (Serializable) current); + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/DefaultWriteObjectTester.java b/libjava/classpath/gnu/javax/rmi/CORBA/DefaultWriteObjectTester.java new file mode 100644 index 000000000..b925428b0 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/DefaultWriteObjectTester.java @@ -0,0 +1,85 @@ +/* DefaultWriteObjectTester.java -- + Copyright (C) 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.CDR.BufferedCdrOutput; + +import java.io.IOException; + +/** + * Tests if the defaultWriteObject method has been called. + * This information is required by RMI-IIOP header. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class DefaultWriteObjectTester + extends CorbaOutput +{ + /** + * The flag, indicating, that the defaultWriteObject method was called. + */ + public boolean dwo_called; + + /** + * Create an instance, delegating calls to the given CORBA stream. + */ + public DefaultWriteObjectTester(Object firstObject) + throws Exception + { + super(new BufferedCdrOutput(), firstObject, null); + } + + /** + * Set the flag that defaultWriteObject was called. + */ + public void defaultWriteObject() + throws IOException + { + dwo_called = true; + } + + /** + * Do not write other objects. + */ + protected void writeObjectOverride(Object obj) + throws IOException + { + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/DelegateFactory.java b/libjava/classpath/gnu/javax/rmi/CORBA/DelegateFactory.java new file mode 100644 index 000000000..a12afd51e --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/DelegateFactory.java @@ -0,0 +1,107 @@ +/* DelegateFactory.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.ObjectCreator; + + +/** + * This class produces delegates, using the system properties. If not + * corresponding property is specified, returns default implementations. + * + * @author Wu Gansha (gansha.wu@intel.com) + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class DelegateFactory +{ + /** + * The name to get a stub delegate. + */ + public static final String STUB = "Stub"; + + /** + * The name to get the util delegate. + */ + public static final String UTIL = "Util"; + + /** + * The name to get the ValueHandler delegate. + */ + public static final String VALUEHANDLER = "ValueHandler"; + + /** + * The name to get the PortableRemoteObject delegate. + */ + public static final String PORTABLE_REMOTE_OBJECT = "PortableRemoteObject"; + + /** + * Get an instance of the given delegate. As in all cases the singleton + * instance is used, the caching here would be redundant. + * + * @param type a delegate type. + * + * @return the associated delegate. + * + * @throws InternalError if the delegate class, indicated in the system + * properties, cannot be instantiated. + */ + public static Object getInstance(String type) + throws InternalError + { + String propertyName = "javax.rmi.CORBA." + type + "Class"; + String dcname = System.getProperty(propertyName); + if (dcname == null) + { + // // No javax.rmi.CORBA.XXXClass property sepcified. + dcname = "gnu.javax.rmi.CORBA." + type + "DelegateImpl"; + } + try + { + Class dclass = ObjectCreator.forName(dcname); + return dclass.newInstance(); + } + catch (Exception e) + { + InternalError ierr = new InternalError("Exception when trying to get " + + type + "delegate instance:" + dcname); + ierr.initCause(e); + throw ierr; + } + } +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/GetDelegateInstanceException.java b/libjava/classpath/gnu/javax/rmi/CORBA/GetDelegateInstanceException.java new file mode 100644 index 000000000..f8aca0d47 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/GetDelegateInstanceException.java @@ -0,0 +1,55 @@ +/* GetDelegateInstanceException.java -- + Copyright (C) 2002, 2004 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; + +public class GetDelegateInstanceException + extends Exception +{ + private Throwable next; + + public GetDelegateInstanceException(String msg) + { + super(msg); + } + + public GetDelegateInstanceException(String msg, Throwable next) + { + super(msg, next); + } +} 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); + } + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/RmiUtilities.java b/libjava/classpath/gnu/javax/rmi/CORBA/RmiUtilities.java new file mode 100644 index 000000000..ac6b90705 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/RmiUtilities.java @@ -0,0 +1,949 @@ +/* RmiUtilities.java -- + Copyright (C) 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.OrbFunctional; +import gnu.CORBA.Minor; +import gnu.CORBA.Unexpected; +import gnu.CORBA.CDR.Vio; +import gnu.CORBA.CDR.gnuRuntime; +import gnu.CORBA.CDR.gnuValueStream; +import gnu.CORBA.CDR.HeadlessInput; + +import gnu.java.lang.CPStringBuilder; + +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.StringValueHelper; +import org.omg.CORBA.WStringValueHelper; +import org.omg.CORBA.portable.Delegate; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.ValueBase; +import org.omg.PortableServer.POA; +import org.omg.PortableServer.POAHelper; +import org.omg.PortableServer.Servant; +import org.omg.PortableServer.POAManagerPackage.State; +import org.omg.SendingContext.RunTime; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.rmi.Remote; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.TreeSet; +import java.util.WeakHashMap; + +import javax.rmi.PortableRemoteObject; +import javax.rmi.CORBA.Stub; +import javax.rmi.CORBA.Tie; +import javax.rmi.CORBA.Util; + +/** + * Defines methods that must be accessible in several derived classes. + * + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class RmiUtilities +{ + /** + * The currently used RMI-IIOP version format. + */ + public static byte VERSION = 1; + + /** + * The non - writable class fields. + */ + static final int NON_WRITABLE = Modifier.STATIC | Modifier.TRANSIENT; + + /** + * The standard String repository Id. + */ + public static final String RMI_STRING_ID = StringValueHelper.id(); + + /** + * The standard Class repository Id. + */ + public static final String RMI_CLASS_ID = "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B"; + + /** + * The standard string array repository Id. + */ + public static final String RMI_STRING_ARRAY_ID = "RMI:[Ljava.lang.String;:071DA8BE7F971128:A0F0A4387A3BB342"; + + /** + * An instance of the wide string value helper for writing strings. + */ + static WStringValueHelper wStringValueHelper = new WStringValueHelper(); + + /** + * Set of serializable classes that have .writeObject and .readObject defined. + * Contains weak references to ensure that the classes will be unloadable. + */ + WeakHashMap io_format = new WeakHashMap(); + + /** + * The standard IO format with no .writeObject and .readObject defined. + */ + static final Object STANDARD = new Object(); + + /** + * The custom IO format with .writeObject and .readObject defined, + * defaultWriteObject called. + */ + static final Object CUSTOM_DWO = new Object(); + + /** + * The custom IO format with .writeObject and .readObject defined, + * defaultWriteObject has not been called. + */ + static final Object CUSTOM_NO_DWO = new Object(); + + /** + * The arguments for readObject. + */ + static final Class[] READ_OBJECT_ARGS = new Class[] { ObjectInputStream.class }; + + /** + * The arguments for writeObject. + */ + static final Class[] WRITE_OBJECT_ARGS = new Class[] { ObjectOutputStream.class }; + + /** + * The undocumented field that is heading the Sun's object data, written with + * writeObject. + */ + static final int S_X = 16908034; + + /** + * Write all fields of the passed value. + */ + void writeFields(OutputStream an_output, Serializable object) + { + org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output; + try + { + Class o_class = object.getClass(); + Field[] fields = getWritableFields(o_class); + Field f; + + Class fc; + + for (int i = 0; i < fields.length; i++) + { + f = fields[i]; + fc = f.getType(); + Object v = f.get(object); + + if (fc == String.class) + { + output.write_value((Serializable) v, wStringValueHelper); + } + else if (fc == int.class) + output.write_long(((Integer) v).intValue()); + else if (fc == long.class) + output.write_longlong(((Number) v).longValue()); + else if (fc == double.class) + output.write_double(((Number) v).doubleValue()); + else if (fc == float.class) + output.write_float(((Number) v).floatValue()); + else if (fc == boolean.class) + output.write_boolean(((Boolean) v).booleanValue()); + else if (fc == short.class) + output.write_short(((Number) v).shortValue()); + else if (fc == byte.class) + output.write_octet(((Number) v).byteValue()); + else if (fc == char.class) + output.write_wchar(((Character) v).charValue()); + else + { + if (!fc.isInterface() && Remote.class.isAssignableFrom(fc)) + fc = getExportedInterface(fc); + writeMember(output, v, fc); + } + } + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Cannot write " + object); + m.minor = Minor.ValueFields; + m.initCause(ex); + throw m; + } + } + + /** + * Write a memeber (field) of the data structure. + */ + void writeMember(org.omg.CORBA_2_3.portable.OutputStream output, + Object object, Class xClass) + { + if (output instanceof gnuValueStream) + { + gnuRuntime g = ((gnuValueStream) output).getRunTime(); + // Reset the target as we are already beyond the critical point + // where is must have the value being written. + if (g != null) + g.target = null; + } + if (Serializable.class.isAssignableFrom(xClass) + || Remote.class.isAssignableFrom(xClass)) + { + // Object handles null reference on its own. + if (org.omg.CORBA.Object.class.isAssignableFrom(xClass) + || Remote.class.isAssignableFrom(xClass)) + { + if (object == null) + output.write_Object(null); + else if (isTieRequired(object)) + exportTie(output, object, xClass); + else + writeValue(output, (Serializable) object); + } + else + output.write_value((Serializable) object, xClass); + } + else + { + MARSHAL m = new MARSHAL(xClass + " is not Serializable"); + m.minor = Minor.NonSerializable; + throw m; + } + } + + /** + * Check if the object must be wrapped into Tie, connected to the ORB and then + * the corresponding Stub be written. + */ + public boolean isTieRequired(Object object) + { + return object instanceof Remote && !(object instanceof Stub); + } + + /** + * Get the interface under that the class of this object must be exposed. The + * interface must be derived from Remote. + */ + Class getExportedInterface(Object object) + throws MARSHAL + { + Class fc = null; + Class[] interfaces = object.getClass().getInterfaces(); + for (int i = 0; i < interfaces.length; i++) + { + if (!Remote.class.equals(interfaces[i])) + if (Remote.class.isAssignableFrom(interfaces[i])) + { + if (fc == null) + fc = interfaces[i]; + else + { + MARSHAL m = new MARSHAL("Both " + fc + " and " + interfaces[i] + + " extends Remote"); + m.minor = Minor.TargetConversion; + throw m; + } + } + } + if (fc == null) + { + MARSHAL m = new MARSHAL(object.getClass() + + " does not implement any interface, derived from Remote"); + m.minor = Minor.TargetConversion; + throw m; + } + return fc; + } + + /** + * Get the persistent hash code for the given class, as defined by OMG + * standard. The inheritance, field names and types (but not the visibility) + * are taken into consideration as well as the presence of the writeObject + * method are taken into consideration. The class name and methods, if any, + * are not taken into consideration. + */ + public static long getHashCode(Class c) + { + Class of = c.isArray() ? c.getComponentType() : null; + if (c.isArray() + && ((!Serializable.class.isAssignableFrom(of) || of.isPrimitive() || Remote.class.isAssignableFrom(of)))) + return 0; + if (!Serializable.class.isAssignableFrom(c)) + return 0; + try + { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(bout); + + Class superClass = c.getSuperclass(); + if (superClass != null) + out.writeLong(getHashCode(superClass)); + + int writeObjectPresentCode; + try + { + c.getDeclaredMethod("writeObject", + new Class[] { ObjectOutputStream.class }); + writeObjectPresentCode = 2; // Exists. + } + catch (NoSuchMethodException e) + { + writeObjectPresentCode = 1; // Missing. + } + out.writeInt(writeObjectPresentCode); + + Field[] fields = c.getDeclaredFields(); + + Arrays.sort(fields, new Comparator() + { + public int compare(Object a, Object b) + { + Field fa = (Field) a; + Field fb = (Field) b; + return fa.getName().compareTo(fb.getName()); + } + }); + + Field f; + for (int i = 0; i < fields.length; i++) + { + f = fields[i]; + if ((f.getModifiers() & NON_WRITABLE) == 0) + { + out.writeUTF(f.getName()); + out.writeUTF(getDescriptor(f.getType())); + } + } + + out.flush(); + out.close(); + MessageDigest shaDigest; + try + { + shaDigest = MessageDigest.getInstance("SHA"); + } + catch (Exception ex) + { + throw new InternalError("SHA digesting algorithm is not available"); + } + + // Return the digest value to the calling + // method as an array of bytes. + byte[] sha = shaDigest.digest(bout.toByteArray()); + + long hash = 0; + for (int i = 0; i < Math.min(8, sha.length); i++) + { + hash += (long) (sha[i] & 255) << (i * 8); + } + return hash; + } + catch (IOException ioex) + { + throw new Unexpected(ioex); + } + } + + /** + * Converts to hexadecimal string, supplementing leading zeros. + */ + public static String toHex(long l) + { + CPStringBuilder b = new CPStringBuilder(); + b.append(Long.toHexString(l).toUpperCase()); + while (b.length() < 16) + b.insert(0, '0'); + return b.toString(); + } + + /** + * Returns a <code>String</code> representing the type-encoding of a class. + */ + static String getDescriptor(Class type) + { + if (type.equals(boolean.class)) + return "Z"; + if (type.equals(byte.class)) + return "B"; + if (type.equals(short.class)) + return "S"; + if (type.equals(char.class)) + return "C"; + if (type.equals(int.class)) + return "I"; + if (type.equals(long.class)) + return "J"; + if (type.equals(float.class)) + return "F"; + if (type.equals(double.class)) + return "D"; + if (type.equals(void.class)) + return "V"; + else if (type.isArray()) + { + CPStringBuilder l = new CPStringBuilder("["); + Class component = type.getComponentType(); + + while (component.isArray()) + { + l.append('['); + component = component.getComponentType(); + } + + l.append('L'); + l.append(component.getName().replace('.', '/')); + l.append(';'); + return l.toString(); + } + else + return "L" + type.getName().replace('.', '/') + ';'; + } + + public static Field[] getWritableFields(Class c) + { + TreeSet set = new TreeSet(new Comparator() + { + public int compare(Object a, Object b) + { + return ((Field) a).getName().compareTo(((Field) b).getName()); + } + }); + + while (!c.equals(Object.class)) + { + Field[] f = c.getDeclaredFields(); + for (int i = 0; i < f.length; i++) + { + if ((f[i].getModifiers() & NON_WRITABLE) == 0) + { + f[i].setAccessible(true); + set.add(f[i]); + } + } + c = c.getSuperclass(); + } + + Field[] r = new Field[set.size()]; + int p = 0; + Iterator it = set.iterator(); + while (it.hasNext()) + { + r[p++] = (Field) it.next(); + } + return r; + } + + /** + * The method is called for Remotes that are not Stubs. It is assumed, that + * the Remote is an implementation. The method searches for the suitable tie + * and, if found, exports it by creating and connecting the stub. Such export + * is supported since jdk 1.5. + */ + void exportTie(org.omg.CORBA_2_3.portable.OutputStream output, + Object implementation, Class interfaceClass) + { + try + { + // Remote, but non - stub class (implementation) + // must be replaced by stub. + Tie t = Util.getTie((Remote) implementation); + if (t instanceof Servant) + { + POA rootPoa = POAHelper.narrow(output.orb().resolve_initial_references( + "RootPOA")); + org.omg.CORBA.Object co = rootPoa.servant_to_reference((Servant) t); + Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass); + writeRemoteObject(output, stub); + + if (rootPoa.the_POAManager().get_state().value() == State._HOLDING) + rootPoa.the_POAManager().activate(); + } + else if (t instanceof org.omg.CORBA.Object) + { + org.omg.CORBA.Object co = (org.omg.CORBA.Object) t; + output.orb().connect(co); + + Stub stub = (Stub) PortableRemoteObject.narrow(co, interfaceClass); + writeRemoteObject(output, stub); + } + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Unable to export " + implementation); + m.minor = Minor.TargetConversion; + m.initCause(ex); + throw m; + } + } + + /** + * Start the ORB, if it is not already runnning. + */ + void ensureOrbRunning(org.omg.CORBA_2_3.portable.OutputStream output) + { + // Ensure ORB is running. + if (output.orb() instanceof OrbFunctional) + { + ((OrbFunctional) output.orb()).ensureRunning(); + } + } + + /** + * Write data to the CORBA output stream. Writes the object contents only; the + * header must be already written. For object, containing objects, may be + * called recursively. + * + * @param an_output a stream to write to, must be + * org.omg.CORBA_2_3.portable.OutputStream + * @param object an object to write. + */ + public void writeRemoteObject(OutputStream an_output, Object object) + { + org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output; + + if (isTieRequired(object)) + { + // Find the interface that is implemented by the object and extends + // Remote. + Class fc = getExportedInterface(object); + exportTie(output, object, fc); + } + else if (object instanceof org.omg.CORBA.Object) + { + ensureOrbRunning(output); + an_output.write_Object((org.omg.CORBA.Object) object); + } + else if (object != null && object instanceof Serializable) + writeFields(an_output, (Serializable) object); + } + + /** + * Write data to the CORBA output stream. Writes the object contents only; the + * header must be already written. For object, containing objects, may be + * called recursively. + * + * @param an_output a stream to write to, must be + * org.omg.CORBA_2_3.portable.OutputStream + * @param object an object to write. + */ + public void writeValue(OutputStream an_output, Serializable object) + { + org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output; + + if (isTieRequired(object)) + { + // Find the interface that is implemented by the object and extends + // Remote. + Class fc = getExportedInterface(object); + exportTie(output, object, fc); + } + else if (object instanceof org.omg.CORBA.Object) + { + ensureOrbRunning(output); + an_output.write_Object((org.omg.CORBA.Object) object); + } + else if (object instanceof Externalizable) + { + try + { + ObjectOutputStream stream = new CorbaOutput(output, object, + this); + stream.write(VERSION); + ((Externalizable) object).writeExternal(stream); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("writeExternal failed"); + m.minor = Minor.Value; + m.initCause(ex); + throw m; + } + } + else if (object instanceof Serializable) + { + Object mode = null; + synchronized (io_format) + { + mode = io_format.get(object.getClass()); + if (mode == STANDARD) + { + writeFields(an_output, (Serializable) object); + return; + } + } + try + { + Method m = object.getClass().getDeclaredMethod("writeObject", + WRITE_OBJECT_ARGS); + m.setAccessible(true); // May be private. + + try + { + ObjectOutputStream stream = new CorbaOutput(output, + object, this); + + // Write version. + stream.write(VERSION); + + if (mode == CUSTOM_DWO) + // Write true, supposing that the defaultWriteObject + // has been called. + stream.write(1); + else if (mode == CUSTOM_NO_DWO) + // Write false (has not been called) + stream.write(0); + else + { + // Measure. + DefaultWriteObjectTester tester = new DefaultWriteObjectTester(object); + m.invoke(object, new Object[] { tester }); + + synchronized (io_format) + { + io_format.put(object.getClass(), + tester.dwo_called ? CUSTOM_DWO : CUSTOM_NO_DWO); + stream.write(tester.dwo_called ? 1 : 0); + } + } + + m.invoke(object, new Object[] { stream }); + stream.flush(); + } + catch (Exception ex) + { + MARSHAL mx = new MARSHAL(object.getClass().getName() + + ".writeObject failed"); + mx.initCause(ex); + throw mx; + } + } + catch (NoSuchMethodException e) + { + // Write in a standard way. + writeFields(an_output, (Serializable) object); + synchronized (io_format) + { + io_format.put(object.getClass(), STANDARD); + } + } + } + } + + /** + * Read data from the CDR input stream. Reads the object contents only; the + * header must be already read (the repository id or ids ara passed). For + * object, containing objects, may be called recursively. + * + * @param an_input the stream to read from, must be + * org.omg.CORBA_2_3.portable.InputStream + * @param object the instance of the object being read. + * @param id the repository Id from the stream in the case when single id was + * specified. + * @param ids the repository Ids from the stream in the case when multiple ids + * were specified. + * @param codebase the codebase, if it was included in the header of the value + * type. Null if not codebase was included. + * + * @return the object, extracted from the stream. + */ + /** + * Read value from the input stream in the case when the value is not + * Streamable or CustomMarshalled. + */ + public Serializable readValue(InputStream in, int offset, Class clz, + String repositoryID, RunTime sender) + { + if (in instanceof HeadlessInput) + ((HeadlessInput) in).subsequentCalls = true; + + gnuRuntime g = null; + Serializable object = null; + + try + { + g = (gnuRuntime) sender; + if (sender != null) + object = g.target; + } + catch (ClassCastException e) + { + // Working with the other CORBA implementation. + g = null; + } + + org.omg.CORBA_2_3.portable.InputStream input = (org.omg.CORBA_2_3.portable.InputStream) in; + + if (Remote.class.isAssignableFrom(clz) + || ValueBase.class.isAssignableFrom(clz)) + { + // Interface is narrowed into Stub. + if (clz.isInterface()) + try + { + clz = Util.loadClass( + PortableRemoteObjectDelegateImpl.getStubClassName(clz.getName()), + null, clz.getClassLoader()); + } + catch (ClassNotFoundException e) + { + MARSHAL m = new MARSHAL("Cannot get stub from interface " + + clz.getClass().getName()); + m.minor = Minor.TargetConversion; + m.initCause(e); + throw m; + } + + // Remote needs special handling. + if (ObjectImpl.class.isAssignableFrom(clz)) + { + // First read CORBA object reference. + Object ro = input.read_Object(); + + ObjectImpl obj = (ObjectImpl) ro; + if (obj == null) + return null; + + Delegate delegate = obj._get_delegate(); + object = instantiate(offset, clz, g); + ((ObjectImpl) object)._set_delegate(delegate); + } + // The object - specific data follows. + } + else if (org.omg.CORBA.Object.class.isAssignableFrom(clz)) + object = (Serializable) input.read_Object(); + + if (object == null) + object = instantiate(offset, clz, g); + + // The sentence below prevents attempt to read the internal fields of the + // ObjectImpl (or RMI Stub) that might follow the object definition. + // Sun's jre 1.5 does not write this information. The stubs, generated + // by rmic, does not contain such fields. + if (object instanceof ObjectImpl) + return object; + + if (object instanceof Externalizable) + { + try + { + CorbaInput stream = new CorbaInput(input, object, this, + offset, repositoryID, g); + + byte version = stream.readByte(); + if (version != 1) + throw new MARSHAL("Unsuported RMI-IIOP version " + version); + + ((Externalizable) object).readExternal(stream); + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("readExternal failed"); + m.initCause(ex); + throw m; + } + } + else + { + Object mode = null; + synchronized (io_format) + { + mode = io_format.get(object.getClass()); + } + + if (mode == STANDARD) + { + readFields(offset, repositoryID, object, input, g); + } + else + { + try + { + Method m = object.getClass().getDeclaredMethod("readObject", + READ_OBJECT_ARGS); + try + { + m.setAccessible(true); // May be private. + + CorbaInput stream = new CorbaInput(input, + object, this, offset, repositoryID, g); + + byte version = stream.readByte(); + if (version != 1) + throw new MARSHAL("Unsuported RMI-IIOP version " + + version); + + // This would indicate is defaultWriteObject has been + // called, + // but the readObject method normally takes care about this. + boolean dwo = stream.readByte() != 0; + + m.invoke(object, new Object[] { stream }); + synchronized (io_format) + { + io_format.put(object.getClass(), dwo ? CUSTOM_DWO + : CUSTOM_NO_DWO); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + MARSHAL mx = new MARSHAL(object.getClass().getName() + + ".readObject failed"); + mx.initCause(ex); + throw mx; + } + } + catch (NoSuchMethodException e) + { + // Read in a standard way. + synchronized (io_format) + { + io_format.put(object.getClass(), STANDARD); + readFields(offset, repositoryID, object, input, g); + } + } + } + } + return object; + } + + /** + * Create an instance. + */ + Serializable instantiate(int offset, Class clz, gnuRuntime g) + throws MARSHAL + { + Serializable object; + try + { + object = (Serializable) Vio.instantiateAnyWay(clz); + g.objectWritten(object, offset); + } + catch (Exception e) + { + MARSHAL m = new MARSHAL("Unable to instantiate " + clz); + m.minor = Minor.Instantiation; + m.initCause(e); + throw m; + } + return object; + } + + /** + * Read fields of the object. + */ + void readFields(int offset, String repositoryID, Serializable object, + org.omg.CORBA_2_3.portable.InputStream input, gnuRuntime r) + throws MARSHAL + { + Field f = null; + Class o_class = object.getClass(); + + try + { + // The returned field array must already be in canonical order. + Field[] fields = getWritableFields(o_class); + + Class fc; + + for (int i = 0; i < fields.length; i++) + { + // Full value type header expected ahead. + if (input instanceof HeadlessInput) + ((HeadlessInput) input).subsequentCalls = true; + + f = fields[i]; + fc = f.getType(); + + Object v; + + if (fc == String.class) + { + v = input.read_value(wStringValueHelper); + } + else if (fc == int.class) + v = new Integer(input.read_long()); + else if (fc == long.class) + v = new Long(input.read_longlong()); + else if (fc == double.class) + v = new Double(input.read_double()); + else if (fc == float.class) + v = new Float(input.read_float()); + else if (fc == boolean.class) + v = input.read_boolean() ? Boolean.TRUE : Boolean.FALSE; + else if (fc == short.class) + v = new Short(input.read_short()); + else if (fc == byte.class) + v = new Byte(input.read_octet()); + else if (fc == char.class) + v = new Character(input.read_char()); + else if (org.omg.CORBA.Object.class.isAssignableFrom(fc) + || Remote.class.isAssignableFrom(fc)) + { + v = readValue(input, offset, fc, null, r); + } + else + { + v = Vio.read(input, fc); + } + + f.set(object, v); + } + } + catch (Exception ex) + { + MARSHAL m = new MARSHAL("Cannot read " + o_class.getName() + " field " + + f); + m.initCause(ex); + m.minor = Minor.ValueFields; + throw m; + } + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/StubDelegateImpl.java b/libjava/classpath/gnu/javax/rmi/CORBA/StubDelegateImpl.java new file mode 100644 index 000000000..05c73a709 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/StubDelegateImpl.java @@ -0,0 +1,310 @@ +/* StubDelegateImpl.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.ObjectCreator; +import gnu.CORBA.Unexpected; +import gnu.CORBA.CDR.BufferredCdrInput; +import gnu.CORBA.CDR.BufferedCdrOutput; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.rmi.Remote; +import java.rmi.RemoteException; + +import javax.rmi.PortableRemoteObject; +import javax.rmi.CORBA.Stub; +import javax.rmi.CORBA.StubDelegate; +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; + +/** + * The default stub delegate. + * + * @author Wu Gansha (gansha.wu@intel.com) (stub) + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation) + */ +public class StubDelegateImpl + implements StubDelegate +{ + /** + * <p> + * Finds the suitable {@link Tie} for this Stub and connects it to the given + * ORB. The tie is found by the name pattern. If the found tie is derived from + * {@link org.omg.CORBA.PortableServer.Servant}, it is connected to the root + * POA, also activating it (if not already active). + * </p> + * <p> + * This method does not allow to specify, to which POA the found Tie must be + * connected and requires to use the deprecated method {@link ORB#connect}. + * Many useful POA features remain unaccessible. A better alternative it might + * be to generate a {@link org.omg.CORBA.PortableServer.Servant} - derived Tie + * (-poa key in rmic) and connect it to POA in one of the many ways, listed in + * the description of the {@link orb.omg.PortableServer} package). The + * obtained CORBA object can be narrowed into stub using + * {@link PortableRemoteObject#narrow}. + * </p> + * + * @param orb the ORB where the Stub must be connected. + * + * @throws RemoteException if the stub is already connected to some other ORB. + * If the stub is already connected to the ORB that was passed as parameter, + * the method returns without action. + * + * @throws BAD_PARAM if the name of this stub does not match the stub name + * pattern, "_*_Stub" or if the Tie class, "_*Impl_Tie", does not exists or an + * instance of this class cannot be instantiated. + */ + public void connect(Stub self, ORB orb) + throws RemoteException + { + connect(self, orb, null); + } + + /** + * Connect when the POA is specified. + */ + public static void connect(Stub self, ORB orb, POA poa) + throws RemoteException + { + ORB oorb = null; + try + { + Delegate d = self._get_delegate(); + if (d != null) + oorb = d.orb(self); + } + catch (Exception e) + { + // Failed to get Delegate or ORB. + // (possible ony for user-written Stubs). + } + + if (oorb != null) + { + if (!oorb.equals(orb)) + throw new RemoteException("Stub " + self + + " is connected to another ORB, " + orb); + else + return; + } + + Tie t = null; + if (self instanceof Remote) + t = Util.getTie((Remote) self); + + // Find by name pattern. + if (t == null) + t = getTieFromStub(self); + + Delegate delegate; + + if (t 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(); + } + + ObjectImpl obj = (ObjectImpl) poa.servant_to_reference((Servant) t); + delegate = obj._get_delegate(); + } + catch (Exception ex) + { + throw new Unexpected(ex); + } + } + else if (t instanceof ObjectImpl) + { + ObjectImpl o = (ObjectImpl) t; + orb.connect(o); + delegate = o._get_delegate(); + } + else + throw new BAD_PARAM("The Tie must be either Servant or ObjectImpl"); + + self._set_delegate(delegate); + } + + /** + * Locate a tie class, appropriate to the given stub class, by the name + * pattern. + */ + public static Tie getTieFromStub(java.lang.Object self) + { + Tie t; + String sn = self.getClass().getName(); + if (!sn.endsWith("_Stub")) + throw new BAD_PARAM("The stub name, " + sn + + ", does not match _*_Stub pattern"); + + String tn = sn.substring(0, sn.length() - "_Stub".length()) + "Impl_Tie"; + Class tieClass = null; + + try + { + tieClass = ObjectCreator.forName(tn); + t = (Tie) tieClass.newInstance(); + if (self instanceof Remote) + Util.registerTarget(t, (Remote) self); + } + catch (Exception e) + { + BAD_PARAM bad = new BAD_PARAM("Unable to instantiate '" + tn + "'"); + bad.initCause(e); + throw bad; + } + return t; + } + + /** + * Compare two stubs for equality. + */ + public boolean equals(Stub self, java.lang.Object obj) + { + if (obj instanceof ObjectImpl) + { + ObjectImpl other = (ObjectImpl) obj; + Delegate d1 = other._get_delegate(); + Delegate d2 = self._get_delegate(); + if (d1 == null || d2 == null) + return d1 == d2; + else + return d1.equals(d2); + } + else return false; + } + + /** + * Get the hash code (from IOR reference). + */ + public int hashCode(Stub self) + { + Delegate d = self._get_delegate(); + return d==null?0:d.hashCode(); + } + + /** + * Returns the IOR reference of the connected ORB. + * + * @see ORB#object_to_string(org.omg.CORBA.Object); + */ + public String toString(Stub self) + { + try + { + return self._orb().object_to_string(self); + } + catch (Exception ex) + { + return null; + } + } + + /** + * This should never be called. The ORB must be supplied. + * + * @see #connect + */ + public void readObject(Stub self, ObjectInputStream input) + throws IOException, ClassNotFoundException + { + readObject(self, input, null); + } + + /** + * Read as CORBA object when the ORB is known. The ORB must be set under the + * previous call of Stub.connect. The Stub is automatically registered with + * this ORB. + */ + public void readObject(Stub self, ObjectInputStream input, ORB orb) + throws IOException, ClassNotFoundException + { + byte[] b = (byte[]) input.readObject(); + BufferredCdrInput in = new BufferredCdrInput(b); + + if (orb != null) + in.setOrb(orb); + + ObjectImpl r = (ObjectImpl) in.read_Object(); + + self._set_delegate(r._get_delegate()); + } + + /** + * Write as CORBA object. The ORB is taken from the + * org.omg.CORBA.portable.Delegate. The Stub is automatically registered with + * this ORB (if not already done). + */ + public void writeObject(Stub self, ObjectOutputStream output) + throws IOException + { + writeObject(self, output, null); + } + + /** + * Write as CORBA object. The ORB must be either set under the previous call + * of Stub.connect or it is taken from the org.omg.CORBA.portable.Delegate. + * The Stub is automatically registered with this ORB (if not already done). + */ + public void writeObject(Stub self, ObjectOutputStream output, ORB orb) + throws IOException + { + BufferedCdrOutput out = new BufferedCdrOutput(); + out.setOrb(orb == null ? self._orb() : orb); + out.write_Object(self); + + output.writeObject(out.buffer.toByteArray()); + } +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/TieTargetRecord.java b/libjava/classpath/gnu/javax/rmi/CORBA/TieTargetRecord.java new file mode 100644 index 000000000..f39441e38 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/TieTargetRecord.java @@ -0,0 +1,93 @@ +/* TieTargetRecord.java -- + Copyright (C) 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 java.util.HashSet; + +import javax.rmi.CORBA.Tie; + +/** + * Represents a Tie, connected to possibly multiple invocation targets. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class TieTargetRecord +{ + /** + * The associated Tie. + */ + public final Tie tie; + + /** + * The objects, exposing the tie. + */ + public HashSet targets = new HashSet(); + + /** + * Create a new record. + */ + public TieTargetRecord(Tie a_tie) + { + tie = a_tie; + } + + /** + * Add a target. + */ + public void add(Object target) + { + targets.add(target); + } + + /** + * Remove target. + */ + public void remove(Object target) + { + targets.remove(target); + } + + /** + * Return true if the tie has no associated invocation targets. + */ + public boolean unused() + { + return targets.size() == 0; + } +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/UtilDelegateImpl.java b/libjava/classpath/gnu/javax/rmi/CORBA/UtilDelegateImpl.java new file mode 100644 index 000000000..dd4e347f2 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/UtilDelegateImpl.java @@ -0,0 +1,744 @@ +/* UtilDelegateImpl.java -- + Copyright (C) 2002, 2005, 2006 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.classpath.VMStackWalker; + +import gnu.CORBA.Minor; +import gnu.CORBA.ObjectCreator; +import gnu.CORBA.Poa.ORB_1_4; +import gnu.CORBA.Poa.AOM; +import gnu.CORBA.Poa.gnuPOA; +import gnu.CORBA.typecodes.GeneralTypeCode; + +import org.omg.CORBA.Any; +import org.omg.CORBA.BAD_PARAM; +import org.omg.CORBA.COMM_FAILURE; +import org.omg.CORBA.CompletionStatus; +import org.omg.CORBA.INVALID_TRANSACTION; +import org.omg.CORBA.INV_OBJREF; +import org.omg.CORBA.MARSHAL; +import org.omg.CORBA.NO_PERMISSION; +import org.omg.CORBA.OBJECT_NOT_EXIST; +import org.omg.CORBA.OMGVMCID; +import org.omg.CORBA.ORB; +import org.omg.CORBA.SystemException; +import org.omg.CORBA.TCKind; +import org.omg.CORBA.TRANSACTION_REQUIRED; +import org.omg.CORBA.TRANSACTION_ROLLEDBACK; +import org.omg.CORBA.TypeCode; +import org.omg.CORBA.UNKNOWN; +import org.omg.CORBA.portable.InputStream; +import org.omg.CORBA.portable.OutputStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.rmi.AccessException; +import java.rmi.MarshalException; +import java.rmi.NoSuchObjectException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.ServerError; +import java.rmi.ServerException; +import java.rmi.UnexpectedException; +import java.rmi.server.RMIClassLoader; +import java.util.Hashtable; + +import javax.rmi.CORBA.Stub; +import javax.rmi.CORBA.Tie; +import javax.rmi.CORBA.Util; +import javax.rmi.CORBA.UtilDelegate; +import javax.rmi.CORBA.ValueHandler; +import javax.transaction.InvalidTransactionException; +import javax.transaction.TransactionRequiredException; +import javax.transaction.TransactionRolledbackException; + +/** + * The implementation of UtilDelegate. + * + * @author Wu Gansha (gansha.wu@intel.com) (stub) + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation) + */ +public class UtilDelegateImpl + extends RmiUtilities + implements UtilDelegate +{ + /** + * The instance of the value handler, requested once. + */ + static ValueHandler m_ValueHandler; + + /** + * The global map of all ties to they records. + */ + static Hashtable m_Ties = new Hashtable(); + + /** + * The global map of all targets to they records. + */ + static Hashtable m_Targets = new Hashtable(); + + /** + * The standard package for that the exception names are omitted. + */ + static final String m_StandardPackage = "org.omg.CORBA."; + + /** + * Make a deep copy of the object. + */ + public Object copyObject(Object obj, ORB orb) + throws RemoteException + { + // Strings are immutable, can be shared. + if (obj instanceof String) + return obj; + else if (obj == null) + return null; + else if (obj instanceof String[] || obj instanceof String[][] + || obj instanceof String[][][]) + { + // String arrays can be just cloned. + return ((Object[]) obj).clone(); + } + else if (obj instanceof Serializable) + { + try + { + ByteArrayOutputStream a = new ByteArrayOutputStream(); + ObjectOutputStream ou = new ObjectOutputStream(a); + ou.writeObject(obj); + ou.close(); + ObjectInputStream input = new ObjectInputStream( + new ByteArrayInputStream(a.toByteArray())); + return input.readObject(); + } + catch (Exception ex) + { + RemoteException rex = new RemoteException("Cannot copy " + obj); + throw rex; + } + } + else + return obj; + } + + /** + * Make a deep copy of the object array. + */ + public Object[] copyObjects(Object[] obj, ORB orb) + throws RemoteException + { + return (Object[]) copyObject(obj, orb); + } + + public ValueHandler createValueHandler() + { + if (m_ValueHandler == null) + m_ValueHandler = (ValueHandler) DelegateFactory.getInstance(DelegateFactory.VALUEHANDLER); + return m_ValueHandler; + } + + /** + * Returns the codebase of the given class. + */ + public String getCodebase(Class clz) + { + return RMIClassLoader.getClassAnnotation(clz); + } + + /** + * Get the Tie that handles invocations on the given target. If the target/Tie + * pair has not been previously registered using {@link #registerTarget}, + * this method tries to locate a tie class by the name pattern. If this + * succeeds, the tie-target pair is also registered. + * + * @return the Tie. + */ + public Tie getTie(Remote target) + { + synchronized (m_Targets) + { + Tie tie; + TieTargetRecord r = ((TieTargetRecord) m_Targets.get(target)); + if (r == null) + { + if (target instanceof Stub) + { + tie = StubDelegateImpl.getTieFromStub(target); + registerTarget(tie, target); + } + else + { + // Treat this as implementation. + String tieClassName = getTieClassName(target.getClass().getName()); + try + { + Class tieClass = Util.loadClass(tieClassName, null, + target.getClass().getClassLoader()); + tie = (Tie) tieClass.newInstance(); + } + catch (Exception e) + { + MARSHAL m = new MARSHAL("Unable to instantiate " + + tieClassName); + m.minor = Minor.TargetConversion; + m.initCause(e); + throw m; + } + tie.setTarget(target); + registerTarget(tie, target); + } + } + else + tie = r.tie; + return tie; + } + } + + /** + * Get the Stub class name for the name, representing the given interface. + */ + private String getTieClassName(String interf) + { + String stubClassName; + int p = interf.lastIndexOf('.'); + + if (p < 0) + // The interface is defined in the default package. + stubClassName = "_" + interf + "_Tie"; + else + stubClassName = interf.substring(0, p + 1) + "_" + + interf.substring(p + 1) + "_Tie"; + return stubClassName; + } + + /** + * Register the Tie-target pair. As the Tie is a Servant, it can potentially + * be connected to several objects and hence may be registered with several + * targets. + */ + public void registerTarget(Tie tie, Remote target) + { + synchronized (m_Ties) + { + synchronized (m_Targets) + { + TieTargetRecord r = (TieTargetRecord) m_Ties.get(tie); + if (r == null) + { + // First registration for this Tie. + r = new TieTargetRecord(tie); + m_Ties.put(tie, r); + } + if (target != null) + { + r.add(target); + m_Targets.put(target, r); + } + } + } + } + + /** + * Deactivate the associated Tie, if it is found and is not connected to other + * registered targets. Independing from the POA policies, the transparent + * reactivation will not be possible. + */ + public void unexportObject(Remote target) + throws NoSuchObjectException + { + synchronized (m_Ties) + { + synchronized (m_Targets) + { + TieTargetRecord r = ((TieTargetRecord) m_Targets.get(target)); + if (r != null) + { + if (target instanceof org.omg.CORBA.Object) + r.tie.orb().disconnect((org.omg.CORBA.Object) target); + + if (r.unused()) + { + m_Targets.remove(target); + m_Ties.remove(r.tie); + r.tie.deactivate(); + + if (r.tie.orb() instanceof ORB_1_4) + { + // Standard case, when more deep cleanup is possible. + // Independing from the POA policies, the object will + // not be activable transparently. + ORB_1_4 orb = (ORB_1_4) r.tie.orb(); + + if (target instanceof org.omg.CORBA.Object) + { + AOM.Obj record = orb.rootPOA.findObject((org.omg.CORBA.Object) target); + + if (record != null && record.servant == r.tie + && record.poa instanceof gnuPOA) + { + ((gnuPOA) record.poa).aom.remove(record.key); + record.deactivated = true; + record.servant = null; + } + } + } + } + } + } + } + } + + /** + * Checks if the given stub is local. + * + * @param stub a stub to check. + * @return true if the stub is local, false otherwise. + */ + public boolean isLocal(Stub stub) + throws RemoteException + { + try + { + return stub._is_local(); + } + catch (SystemException e) + { + RemoteException rex = new RemoteException(); + rex.initCause(e); + throw rex; + } + } + + /** + * Load the class. The method uses class loaders from the call stact first. If + * this fails, the further behaviour depends on the System Property + * "java.rmi.server.useCodebaseOnly" with default value "false". + * + * <ul> + * <li>Try the current thread context class loader first.</li> + * <li>If remoteCodebase is non-null and useCodebaseOnly is "false" then call + * java.rmi.server.RMIClassLoader.loadClass (remoteCodebase, className)</li> + * <li> If remoteCodebase is null or useCodebaseOnly is true then call + * java.rmi.server.RMIClassLoader.loadClass(className)</li> + * <li>If a class is still not successfully loaded and the loader != null + * then try Class.forName(className, false, loader). </li> + * </ul> + * + * @param className the name of the class. + * @param remoteCodebase the codebase. + * @param loader the class loader. + * @return the loaded class. + * + * @throws ClassNotFoundException of the class cannot be loaded. + */ + public Class loadClass(String className, String remoteCodebase, + ClassLoader loader) + throws ClassNotFoundException + { + if (loader == null) + loader = VMStackWalker.firstNonNullClassLoader(); + + String p_useCodebaseOnly = System.getProperty("java.rmi.server.useCodebaseOnly"); + + boolean useCodebaseOnly = p_useCodebaseOnly != null + && p_useCodebaseOnly.trim().equalsIgnoreCase("true"); + + if (useCodebaseOnly) + remoteCodebase = null; + + try + { + return RMIClassLoader.loadClass(remoteCodebase, className, loader); + } + catch (MalformedURLException x) + { + throw new ClassNotFoundException(className, x); + } + } + + /** + * Converts CORBA {@link SystemException} into RMI {@link RemoteException}. + * The exception is converted as defined in the following table: + * <p> + * <table border = "1"> + * <tr> + * <th>CORBA Exception</th> + * <th>RMI Exception</th> + * </tr> + * <tr> + * <td>{@link COMM_FAILURE}</td> + * <td>{@link MarshalException}</td> + * </tr> + * <tr> + * <td>{@link INV_OBJREF}</td> + * <td>{@link NoSuchObjectException}</td> + * </tr> + * <tr> + * <td>{@link NO_PERMISSION}</td> + * <td>{@link AccessException}</td> + * </tr> + * <tr> + * <td>{@link MARSHAL}</td> + * <td>{@link MarshalException}</td> + * </tr> + * <tr> + * <td>{@link BAD_PARAM} (all other cases)</td> + * <td>{@link MarshalException}</td> + * </tr> + * <tr> + * <td>{@link OBJECT_NOT_EXIST}</td> + * <td>{@link NoSuchObjectException}</td> + * </tr> + * <tr> + * <td>{@link TRANSACTION_REQUIRED}</td> + * <td>{@link TransactionRequiredException}</td> + * </tr> + * <tr> + * <td>{@link TRANSACTION_ROLLEDBACK}</td> + * <td>{@link TransactionRolledbackException}</td> + * </tr> + * <tr> + * <td>{@link INVALID_TRANSACTION}</td> + * <td>{@link InvalidTransactionException}</td> + * </tr> + * <tr> + * <td bgcolor="lightgray">Any other {@link SystemException}</td> + * <td bgcolor="lightgray">{@link RemoteException}</td> + * </tr> + * </table> + * </p> + * <p> + * The exception detailed message always consists of + * <ol> + * <li>the string "CORBA "</li> + * <li>the CORBA name of the system exception</li> + * <li>single space</li> + * <li>the hexadecimal value of the system exception's minor code, preceeded + * by 0x (higher bits contain {@link OMGVMCID}).</li> + * <li>single space</li> + * <li>the {@link CompletionStatus} of the exception: "Yes", "No" or "Maybe".</li> + * </ol> + * <p> + * For instance, if the Internet connection was refused: + * </p> + * <p> + * <pre> + * <code>CORBA COMM_FAILURE 0x535500C9 No</code> + * </p> + * <p> + * The original CORBA exception is set as the cause of the RemoteException + * being created. + * </p> + */ + public RemoteException mapSystemException(SystemException ex) + { + RemoteException rex; + + String status; + + switch (ex.completed.value()) + { + case CompletionStatus._COMPLETED_MAYBE: + status = "Maybe"; + break; + + case CompletionStatus._COMPLETED_NO: + status = "No"; + break; + + case CompletionStatus._COMPLETED_YES: + status = "Yes"; + break; + + default: + status = "Unexpected completion status " + ex.completed.value(); + } + + String name = ex.getClass().getName(); + + if (name.startsWith(m_StandardPackage)) + name = name.substring(m_StandardPackage.length()); + + String message = "CORBA " + name + " 0x" + Integer.toHexString(ex.minor) + + " " + status; + + if (ex instanceof COMM_FAILURE) + rex = new MarshalException(message, ex); + else if (ex instanceof INV_OBJREF) + { + rex = new NoSuchObjectException(message); + rex.detail = ex; + } + else if (ex instanceof NO_PERMISSION) + rex = new AccessException(message, ex); + else if (ex instanceof MARSHAL) + rex = new MarshalException(message, ex); + else if (ex instanceof BAD_PARAM) + rex = new MarshalException(message, ex); + else if (ex instanceof OBJECT_NOT_EXIST) + { + rex = new NoSuchObjectException(message); + rex.detail = ex; + } + else if (ex instanceof TRANSACTION_REQUIRED) + { + rex = new TransactionRequiredException(message); + rex.detail = ex; + } + else if (ex instanceof TRANSACTION_ROLLEDBACK) + { + rex = new TransactionRolledbackException(message); + rex.detail = ex; + } + else if (ex instanceof INVALID_TRANSACTION) + { + rex = new InvalidTransactionException(message); + rex.detail = ex; + } + else if (ex instanceof UNKNOWN) + rex = wrapException(ex.getCause()); + else + rex = new RemoteException(message, ex); + + return rex; + } + + /** + * Converts the exception that was thrown by the implementation method on a + * server side into RemoteException that can be transferred and re-thrown on a + * client side. The method converts exceptions as defined in the following + * table: <table border = "1"> + * <tr> + * <th>Exception to map (or subclass)</th> + * <th>Maps into</th> + * </tr> + * <tr> + * <td>{@link Error}</td> + * <td>{@link ServerError}</td> + * </tr> + * <tr> + * <td>{@link RemoteException}</td> + * <td>{@link ServerException}</td> + * </tr> + * <tr> + * <td>{@link SystemException}</td> + * <td>wrapException({@link #mapSystemException})</td> + * </tr> + * <tr> + * <td>{@link RuntimeException}</td> + * <td><b>rethrows</b></td> + * </tr> + * <tr> + * <td>Any other exception</td> + * <td>{@link UnexpectedException}</td> + * </tr> + * </table> + * + * @param ex an exception that was thrown on a server side implementation. + * + * @return the corresponding RemoteException unless it is a RuntimeException. + * + * @throws RuntimeException the passed exception if it is an instance of + * RuntimeException. + * + * @specnote It is the same behavior, as in Suns implementations 1.4.0-1.5.0. + */ + public RemoteException wrapException(Throwable ex) + throws RuntimeException + { + if (ex instanceof RuntimeException) + throw (RuntimeException) ex; + else if (ex instanceof Error) + return new ServerError(ex.getMessage(), (Error) ex); + else if (ex instanceof RemoteException) + return new ServerException(ex.getMessage(), (Exception) ex); + else if (ex instanceof SystemException) + return wrapException(mapSystemException((SystemException) ex)); + else + return new UnexpectedException("Unexpected", (Exception) ex); + } + + /** + * Write abstract interface to the CORBA output stream. The write format is + * matching CORBA abstract interface. Remotes and CORBA objects are written as + * objects, other classes are supposed to be value types and are written as + * such. {@link Remote}s are processed as defined in + * {@link #writeRemoteObject}. The written data contains discriminator, + * defining, that was written. Another method that writes the same content is + * {@link org.omg.CORBA_2_3.portable.OutputStream#write_abstract_interface(java.lang.Object)}. + * + * @param output a stream to write to, must be + * {@link org.omg.CORBA_2_3.portable.OutputStream}. + * + * @param object an object to write, must be CORBA object, Remote + */ + public void writeAbstractObject(OutputStream output, Object object) + { + ((org.omg.CORBA_2_3.portable.OutputStream) output).write_abstract_interface(object); + } + + /** + * Write the passed java object to the output stream in the form of the CORBA + * {@link Any}. This includes creating an writing the object {@link TypeCode} + * first. Such Any can be later read by a non-RMI-IIOP CORBA implementation + * and manipulated, for instance, by means, provided in + * {@link org.omg.DynamicAny.DynAny}. Depending from the passed value, this + * method writes CORBA object, value type or value box. For value types Null + * is written with the abstract interface, its typecode having repository id + * "IDL:omg.org/CORBA/AbstractBase:1.0" and the empty string name. + * + * @param output the object to write. + * @param object the java object that must be written in the form of the CORBA + * {@link Any}. + */ + public void writeAny(OutputStream output, Object object) + { + Any any = output.orb().create_any(); + if (object == null) + { + GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_abstract_interface); + t.setId("IDL:omg.org/CORBA/AbstractBase:1.0"); + t.setName(""); + any.type(t); + output.write_any(any); + return; + } + else if (object instanceof org.omg.CORBA.Object + && !(object instanceof Remote)) + { + // Write as value type. + boolean inserted = ObjectCreator.insertWithHelper(any, object); + if (inserted) + { + output.write_any(any); + return; + } + } + + if (object instanceof org.omg.CORBA.Object) + writeAnyAsRemote(output, object); + else if (object instanceof Serializable) + { + any.insert_Value((Serializable) object); + output.write_any(any); + } + else + { + MARSHAL m = new MARSHAL(object.getClass().getName() + + " must be CORBA Object, Remote or Serializable"); + m.minor = Minor.NonSerializable; + throw m; + } + } + + /** + * Write Any as for remote object. + */ + void writeAnyAsRemote(OutputStream output, Object object) + { + GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_objref); + t.setId(m_ValueHandler.getRMIRepositoryID(object.getClass())); + t.setName(object.getClass().getName()); + + // Writing Any (typecode, followed by value). + output.write_TypeCode(t); + writeRemoteObject(output, object); + } + + /** + * Get the class name excluding the package name. + */ + String getName(String n) + { + int p = n.lastIndexOf('.'); + if (p < 0) + return n; + else + return n.substring(p + 1); + } + + /** + * Read Any from the input stream. + */ + public Object readAny(InputStream input) + { + return input.read_any(); + } + + /** + * Write the passed parameter to the output stream as CORBA object. If the + * parameter is an instance of Remote and not an instance of Stub, the method + * instantiates a suitable Tie, connects the parameter to this Tie and then + * connects that Tie to the ORB that is requested from the output stream. Then + * the object reference is written to the stream, making remote invocations + * possible. This method is used in write_value(..) method group in + * {@link org.omg.CORBA_2_3.portable.OutputStream} and also may be called + * directly from generated Stubs and Ties. + * + * @param output a stream to write to, must be + * org.omg.CORBA_2_3.portable.OutputStream + * @param object an object to write. + */ + public void writeRemoteObject(OutputStream an_output, Object object) + { + org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output; + if (object == null) + an_output.write_Object(null); + else if (isTieRequired(object)) + { + // Find the interface that is implemented by the object and extends + // Remote. + Class fc = getExportedInterface(object); + exportTie(output, object, fc); + } + else if (object instanceof org.omg.CORBA.Object) + { + ensureOrbRunning(output); + an_output.write_Object((org.omg.CORBA.Object) object); + } + else if (object != null && object instanceof Serializable) + writeFields(an_output, (Serializable) object); + } + +} diff --git a/libjava/classpath/gnu/javax/rmi/CORBA/ValueHandlerDelegateImpl.java b/libjava/classpath/gnu/javax/rmi/CORBA/ValueHandlerDelegateImpl.java new file mode 100644 index 000000000..33fff16e5 --- /dev/null +++ b/libjava/classpath/gnu/javax/rmi/CORBA/ValueHandlerDelegateImpl.java @@ -0,0 +1,163 @@ +/* ValueHandlerDelegateImpl.java -- + Copyright (C) 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.CDR.gnuRuntime; + +import org.omg.CORBA.BAD_PARAM; +import org.omg.CORBA.CustomMarshal; +import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.Streamable; +import org.omg.SendingContext.RunTime; + +import java.io.Externalizable; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.rmi.Remote; + +import javax.rmi.CORBA.ValueHandler; +import javax.rmi.CORBA.ValueHandlerMultiFormat; + +/** + * Implementation of the ValueHandler. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation) + */ +public class ValueHandlerDelegateImpl + extends RmiUtilities + implements ValueHandler, ValueHandlerMultiFormat +{ + /** + * Return the maximal supported stream format version. We currently + * support the version 1. + * + * TODO Support the version 2. + */ + public byte getMaximumStreamFormatVersion() + { + return 1; + } + + /** + * Write value using the given stream format version. + */ + public void writeValue(OutputStream output, Serializable value, byte version) + { + if (version!=1) + throw new BAD_PARAM("Unsupported stream format version "+version); + else + writeValue(output, value); + } + + /** + * This implementation associates RunTime with stream rather than with the + * value handler and this method is not used in the implementation. It is + * implemented just for the sake of compatibility. + */ + public RunTime getRunTimeCodeBase() + { + return new gnuRuntime(null, null); + } + + /** + * Checks if an instance of this class can write its fields itself. + */ + public boolean isCustomMarshaled(Class clz) + { + return CustomMarshal.class.isAssignableFrom(clz) + || Streamable.class.isAssignableFrom(clz); + } + + /** + * No replacement, returns the passed parameter. + */ + public Serializable writeReplace(Serializable value) + { + return value; + } + + /** + * Compute the repository id in the RMI hashed format. + */ + public String getRMIRepositoryID(final Class cx) + { + long hash = 0; + Class of = cx.isArray() ? cx.getComponentType() : null; + + if (cx.equals(String[].class)) + return RMI_STRING_ARRAY_ID; + else if (cx.equals(String.class)) + return RMI_STRING_ID; + else if (cx.equals(Class.class)) + return RMI_CLASS_ID; + else if (Remote.class.isAssignableFrom(cx) + || !Serializable.class.isAssignableFrom(cx) + || cx.isInterface() + || (cx.isArray() && (!Serializable.class.isAssignableFrom(of) + || of.isPrimitive() || Remote.class.isAssignableFrom(of))) + + ) + // Some classes that have zero hash code and serial no version id + // included. + return "RMI:" + cx.getName() + ":" + toHex(hash); + else if (cx.isArray()) + // Arrays have the same hashcode and uid as they components. + return "RMI:" + cx.getName() + ":" + toHex(getHashCode(of)) + ":" + + toHex(getSid(of)); + else + { + if (Externalizable.class.isAssignableFrom(cx)) + hash = 1; + else + hash = getHashCode(cx); + + return "RMI:" + cx.getName() + ":" + toHex(hash) + ":" + + toHex(getSid(cx)); + } + } + + /** + * Get the class serial version UID. + */ + long getSid(Class cx) + { + ObjectStreamClass osc = ObjectStreamClass.lookup(cx); + return osc.getSerialVersionUID(); + } +} |