123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 |
- /* 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;
- }
- }
- }
|