1 /* RmiUtilities.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.javax
.rmi
.CORBA
;
41 import gnu
.CORBA
.OrbFunctional
;
42 import gnu
.CORBA
.Minor
;
43 import gnu
.CORBA
.Unexpected
;
44 import gnu
.CORBA
.CDR
.Vio
;
45 import gnu
.CORBA
.CDR
.gnuRuntime
;
46 import gnu
.CORBA
.CDR
.gnuValueStream
;
47 import gnu
.CORBA
.CDR
.HeadlessInput
;
49 import org
.omg
.CORBA
.MARSHAL
;
50 import org
.omg
.CORBA
.StringValueHelper
;
51 import org
.omg
.CORBA
.WStringValueHelper
;
52 import org
.omg
.CORBA
.portable
.Delegate
;
53 import org
.omg
.CORBA
.portable
.InputStream
;
54 import org
.omg
.CORBA
.portable
.ObjectImpl
;
55 import org
.omg
.CORBA
.portable
.OutputStream
;
56 import org
.omg
.CORBA
.portable
.ValueBase
;
57 import org
.omg
.PortableServer
.POA
;
58 import org
.omg
.PortableServer
.POAHelper
;
59 import org
.omg
.PortableServer
.Servant
;
60 import org
.omg
.PortableServer
.POAManagerPackage
.State
;
61 import org
.omg
.SendingContext
.RunTime
;
63 import java
.io
.ByteArrayOutputStream
;
64 import java
.io
.DataOutputStream
;
65 import java
.io
.Externalizable
;
66 import java
.io
.IOException
;
67 import java
.io
.ObjectInputStream
;
68 import java
.io
.ObjectOutputStream
;
69 import java
.io
.Serializable
;
70 import java
.lang
.reflect
.Field
;
71 import java
.lang
.reflect
.Method
;
72 import java
.lang
.reflect
.Modifier
;
73 import java
.rmi
.Remote
;
74 import java
.security
.MessageDigest
;
75 import java
.util
.Arrays
;
76 import java
.util
.Comparator
;
77 import java
.util
.Iterator
;
78 import java
.util
.TreeSet
;
79 import java
.util
.WeakHashMap
;
81 import javax
.rmi
.PortableRemoteObject
;
82 import javax
.rmi
.CORBA
.Stub
;
83 import javax
.rmi
.CORBA
.Tie
;
84 import javax
.rmi
.CORBA
.Util
;
87 * Defines methods that must be accessible in several derived classes.
89 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
91 public class RmiUtilities
94 * The currently used RMI-IIOP version format.
96 public static byte VERSION
= 1;
99 * The non - writable class fields.
101 static final int NON_WRITABLE
= Modifier
.STATIC
| Modifier
.TRANSIENT
;
104 * The standard String repository Id.
106 public static final String RMI_STRING_ID
= StringValueHelper
.id();
109 * The standard Class repository Id.
111 public static final String RMI_CLASS_ID
= "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B";
114 * The standard string array repository Id.
116 public static final String RMI_STRING_ARRAY_ID
= "RMI:[Ljava.lang.String;:071DA8BE7F971128:A0F0A4387A3BB342";
119 * An instance of the wide string value helper for writing strings.
121 static WStringValueHelper wStringValueHelper
= new WStringValueHelper();
124 * Set of serializable classes that have .writeObject and .readObject defined.
125 * Contains weak references to ensure that the classes will be unloadable.
127 WeakHashMap io_format
= new WeakHashMap();
130 * The standard IO format with no .writeObject and .readObject defined.
132 static final Object STANDARD
= new Object();
135 * The custom IO format with .writeObject and .readObject defined,
136 * defaultWriteObject called.
138 static final Object CUSTOM_DWO
= new Object();
141 * The custom IO format with .writeObject and .readObject defined,
142 * defaultWriteObject has not been called.
144 static final Object CUSTOM_NO_DWO
= new Object();
147 * The arguments for readObject.
149 static final Class
[] READ_OBJECT_ARGS
= new Class
[] { ObjectInputStream
.class };
152 * The arguments for writeObject.
154 static final Class
[] WRITE_OBJECT_ARGS
= new Class
[] { ObjectOutputStream
.class };
157 * The undocumented field that is heading the Sun's object data, written with
160 static final int S_X
= 16908034;
163 * Write all fields of the passed value.
165 void writeFields(OutputStream an_output
, Serializable object
)
167 org
.omg
.CORBA_2_3
.portable
.OutputStream output
= (org
.omg
.CORBA_2_3
.portable
.OutputStream
) an_output
;
170 Class o_class
= object
.getClass();
171 Field
[] fields
= getWritableFields(o_class
);
176 for (int i
= 0; i
< fields
.length
; i
++)
180 Object v
= f
.get(object
);
182 if (fc
== String
.class)
184 output
.write_value((Serializable
) v
, wStringValueHelper
);
186 else if (fc
== int.class)
187 output
.write_long(((Integer
) v
).intValue());
188 else if (fc
== long.class)
189 output
.write_longlong(((Number
) v
).longValue());
190 else if (fc
== double.class)
191 output
.write_double(((Number
) v
).doubleValue());
192 else if (fc
== float.class)
193 output
.write_float(((Number
) v
).floatValue());
194 else if (fc
== boolean.class)
195 output
.write_boolean(((Boolean
) v
).booleanValue());
196 else if (fc
== short.class)
197 output
.write_short(((Number
) v
).shortValue());
198 else if (fc
== byte.class)
199 output
.write_octet(((Number
) v
).byteValue());
200 else if (fc
== char.class)
201 output
.write_wchar(((Character
) v
).charValue());
204 if (!fc
.isInterface() && Remote
.class.isAssignableFrom(fc
))
205 fc
= getExportedInterface(fc
);
206 writeMember(output
, v
, fc
);
212 MARSHAL m
= new MARSHAL("Cannot write " + object
);
213 m
.minor
= Minor
.ValueFields
;
220 * Write a memeber (field) of the data structure.
222 void writeMember(org
.omg
.CORBA_2_3
.portable
.OutputStream output
,
223 Object object
, Class xClass
)
225 if (output
instanceof gnuValueStream
)
227 gnuRuntime g
= ((gnuValueStream
) output
).getRunTime();
228 // Reset the target as we are already beyond the critical point
229 // where is must have the value being written.
233 if (Serializable
.class.isAssignableFrom(xClass
)
234 || Remote
.class.isAssignableFrom(xClass
))
236 // Object handles null reference on its own.
237 if (org
.omg
.CORBA
.Object
.class.isAssignableFrom(xClass
)
238 || Remote
.class.isAssignableFrom(xClass
))
241 output
.write_Object(null);
242 else if (isTieRequired(object
))
243 exportTie(output
, object
, xClass
);
245 writeValue(output
, (Serializable
) object
);
248 output
.write_value((Serializable
) object
, xClass
);
252 MARSHAL m
= new MARSHAL(xClass
+ " is not Serializable");
253 m
.minor
= Minor
.NonSerializable
;
259 * Check if the object must be wrapped into Tie, connected to the ORB and then
260 * the corresponding Stub be written.
262 public boolean isTieRequired(Object object
)
264 return object
instanceof Remote
&& !(object
instanceof Stub
);
268 * Get the interface under that the class of this object must be exposed. The
269 * interface must be derived from Remote.
271 Class
getExportedInterface(Object object
)
275 Class
[] interfaces
= object
.getClass().getInterfaces();
276 for (int i
= 0; i
< interfaces
.length
; i
++)
278 if (!Remote
.class.equals(interfaces
[i
]))
279 if (Remote
.class.isAssignableFrom(interfaces
[i
]))
285 MARSHAL m
= new MARSHAL("Both " + fc
+ " and " + interfaces
[i
]
286 + " extends Remote");
287 m
.minor
= Minor
.TargetConversion
;
294 MARSHAL m
= new MARSHAL(object
.getClass()
295 + " does not implement any interface, derived from Remote");
296 m
.minor
= Minor
.TargetConversion
;
303 * Get the persistent hash code for the given class, as defined by OMG
304 * standard. The inheritance, field names and types (but not the visibility)
305 * are taken into consideration as well as the presence of the writeObject
306 * method are taken into consideration. The class name and methods, if any,
307 * are not taken into consideration.
309 public static long getHashCode(Class c
)
311 Class of
= c
.isArray() ? c
.getComponentType() : null;
313 && ((!Serializable
.class.isAssignableFrom(of
) || of
.isPrimitive() || Remote
.class.isAssignableFrom(of
))))
315 if (!Serializable
.class.isAssignableFrom(c
))
319 ByteArrayOutputStream bout
= new ByteArrayOutputStream();
320 DataOutputStream out
= new DataOutputStream(bout
);
322 Class superClass
= c
.getSuperclass();
323 if (superClass
!= null)
324 out
.writeLong(getHashCode(superClass
));
326 int writeObjectPresentCode
;
329 c
.getDeclaredMethod("writeObject",
330 new Class
[] { ObjectOutputStream
.class });
331 writeObjectPresentCode
= 2; // Exists.
333 catch (NoSuchMethodException e
)
335 writeObjectPresentCode
= 1; // Missing.
337 out
.writeInt(writeObjectPresentCode
);
339 Field
[] fields
= c
.getDeclaredFields();
341 Arrays
.sort(fields
, new Comparator()
343 public int compare(Object a
, Object b
)
345 Field fa
= (Field
) a
;
346 Field fb
= (Field
) b
;
347 return fa
.getName().compareTo(fb
.getName());
352 for (int i
= 0; i
< fields
.length
; i
++)
355 if ((f
.getModifiers() & NON_WRITABLE
) == 0)
357 out
.writeUTF(f
.getName());
358 out
.writeUTF(getDescriptor(f
.getType()));
364 MessageDigest shaDigest
;
367 shaDigest
= MessageDigest
.getInstance("SHA");
371 throw new InternalError("SHA digesting algorithm is not available");
374 // Return the digest value to the calling
375 // method as an array of bytes.
376 byte[] sha
= shaDigest
.digest(bout
.toByteArray());
379 for (int i
= 0; i
< Math
.min(8, sha
.length
); i
++)
381 hash
+= (long) (sha
[i
] & 255) << (i
* 8);
385 catch (IOException ioex
)
387 throw new Unexpected(ioex
);
392 * Converts to hexadecimal string, supplementing leading zeros.
394 public static String
toHex(long l
)
396 StringBuffer b
= new StringBuffer();
397 b
.append(Long
.toHexString(l
).toUpperCase());
398 while (b
.length() < 16)
404 * Returns a <code>String</code> representing the type-encoding of a class.
406 static String
getDescriptor(Class type
)
408 if (type
.equals(boolean.class))
410 if (type
.equals(byte.class))
412 if (type
.equals(short.class))
414 if (type
.equals(char.class))
416 if (type
.equals(int.class))
418 if (type
.equals(long.class))
420 if (type
.equals(float.class))
422 if (type
.equals(double.class))
424 if (type
.equals(void.class))
426 else if (type
.isArray())
428 StringBuffer l
= new StringBuffer("[");
429 Class component
= type
.getComponentType();
431 while (component
.isArray())
434 component
= component
.getComponentType();
438 l
.append(component
.getName().replace('.', '/'));
443 return "L" + type
.getName().replace('.', '/') + ';';
446 public static Field
[] getWritableFields(Class c
)
448 TreeSet set
= new TreeSet(new Comparator()
450 public int compare(Object a
, Object b
)
452 return ((Field
) a
).getName().compareTo(((Field
) b
).getName());
456 while (!c
.equals(Object
.class))
458 Field
[] f
= c
.getDeclaredFields();
459 for (int i
= 0; i
< f
.length
; i
++)
461 if ((f
[i
].getModifiers() & NON_WRITABLE
) == 0)
463 f
[i
].setAccessible(true);
467 c
= c
.getSuperclass();
470 Field
[] r
= new Field
[set
.size()];
472 Iterator it
= set
.iterator();
475 r
[p
++] = (Field
) it
.next();
481 * The method is called for Remotes that are not Stubs. It is assumed, that
482 * the Remote is an implementation. The method searches for the suitable tie
483 * and, if found, exports it by creating and connecting the stub. Such export
484 * is supported since jdk 1.5.
486 void exportTie(org
.omg
.CORBA_2_3
.portable
.OutputStream output
,
487 Object implementation
, Class interfaceClass
)
491 // Remote, but non - stub class (implementation)
492 // must be replaced by stub.
493 Tie t
= Util
.getTie((Remote
) implementation
);
494 if (t
instanceof Servant
)
496 POA rootPoa
= POAHelper
.narrow(output
.orb().resolve_initial_references(
498 org
.omg
.CORBA
.Object co
= rootPoa
.servant_to_reference((Servant
) t
);
499 Stub stub
= (Stub
) PortableRemoteObject
.narrow(co
, interfaceClass
);
500 writeRemoteObject(output
, stub
);
502 if (rootPoa
.the_POAManager().get_state().value() == State
._HOLDING
)
503 rootPoa
.the_POAManager().activate();
505 else if (t
instanceof org
.omg
.CORBA
.Object
)
507 org
.omg
.CORBA
.Object co
= (org
.omg
.CORBA
.Object
) t
;
508 output
.orb().connect(co
);
510 Stub stub
= (Stub
) PortableRemoteObject
.narrow(co
, interfaceClass
);
511 writeRemoteObject(output
, stub
);
516 MARSHAL m
= new MARSHAL("Unable to export " + implementation
);
517 m
.minor
= Minor
.TargetConversion
;
524 * Start the ORB, if it is not already runnning.
526 void ensureOrbRunning(org
.omg
.CORBA_2_3
.portable
.OutputStream output
)
528 // Ensure ORB is running.
529 if (output
.orb() instanceof OrbFunctional
)
531 ((OrbFunctional
) output
.orb()).ensureRunning();
536 * Write data to the CORBA output stream. Writes the object contents only; the
537 * header must be already written. For object, containing objects, may be
538 * called recursively.
540 * @param an_output a stream to write to, must be
541 * org.omg.CORBA_2_3.portable.OutputStream
542 * @param object an object to write.
544 public void writeRemoteObject(OutputStream an_output
, Object object
)
546 org
.omg
.CORBA_2_3
.portable
.OutputStream output
= (org
.omg
.CORBA_2_3
.portable
.OutputStream
) an_output
;
548 if (isTieRequired(object
))
550 // Find the interface that is implemented by the object and extends
552 Class fc
= getExportedInterface(object
);
553 exportTie(output
, object
, fc
);
555 else if (object
instanceof org
.omg
.CORBA
.Object
)
557 ensureOrbRunning(output
);
558 an_output
.write_Object((org
.omg
.CORBA
.Object
) object
);
560 else if (object
!= null && object
instanceof Serializable
)
561 writeFields(an_output
, (Serializable
) object
);
565 * Write data to the CORBA output stream. Writes the object contents only; the
566 * header must be already written. For object, containing objects, may be
567 * called recursively.
569 * @param an_output a stream to write to, must be
570 * org.omg.CORBA_2_3.portable.OutputStream
571 * @param object an object to write.
573 public void writeValue(OutputStream an_output
, Serializable object
)
575 org
.omg
.CORBA_2_3
.portable
.OutputStream output
= (org
.omg
.CORBA_2_3
.portable
.OutputStream
) an_output
;
577 if (isTieRequired(object
))
579 // Find the interface that is implemented by the object and extends
581 Class fc
= getExportedInterface(object
);
582 exportTie(output
, object
, fc
);
584 else if (object
instanceof org
.omg
.CORBA
.Object
)
586 ensureOrbRunning(output
);
587 an_output
.write_Object((org
.omg
.CORBA
.Object
) object
);
589 else if (object
instanceof Externalizable
)
593 ObjectOutputStream stream
= new CorbaOutput(output
, object
,
595 stream
.write(VERSION
);
596 ((Externalizable
) object
).writeExternal(stream
);
600 MARSHAL m
= new MARSHAL("writeExternal failed");
601 m
.minor
= Minor
.Value
;
606 else if (object
instanceof Serializable
)
609 synchronized (io_format
)
611 mode
= io_format
.get(object
.getClass());
612 if (mode
== STANDARD
)
614 writeFields(an_output
, (Serializable
) object
);
620 Method m
= object
.getClass().getDeclaredMethod("writeObject",
622 m
.setAccessible(true); // May be private.
626 ObjectOutputStream stream
= new CorbaOutput(output
,
630 stream
.write(VERSION
);
632 if (mode
== CUSTOM_DWO
)
633 // Write true, supposing that the defaultWriteObject
636 else if (mode
== CUSTOM_NO_DWO
)
637 // Write false (has not been called)
642 DefaultWriteObjectTester tester
= new DefaultWriteObjectTester(object
);
643 m
.invoke(object
, new Object
[] { tester
});
645 synchronized (io_format
)
647 io_format
.put(object
.getClass(),
648 tester
.dwo_called ? CUSTOM_DWO
: CUSTOM_NO_DWO
);
649 stream
.write(tester
.dwo_called ?
1 : 0);
653 m
.invoke(object
, new Object
[] { stream
});
658 MARSHAL mx
= new MARSHAL(object
.getClass().getName()
659 + ".writeObject failed");
664 catch (NoSuchMethodException e
)
666 // Write in a standard way.
667 writeFields(an_output
, (Serializable
) object
);
668 synchronized (io_format
)
670 io_format
.put(object
.getClass(), STANDARD
);
677 * Read data from the CDR input stream. Reads the object contents only; the
678 * header must be already read (the repository id or ids ara passed). For
679 * object, containing objects, may be called recursively.
681 * @param an_input the stream to read from, must be
682 * org.omg.CORBA_2_3.portable.InputStream
683 * @param object the instance of the object being read.
684 * @param id the repository Id from the stream in the case when single id was
686 * @param ids the repository Ids from the stream in the case when multiple ids
688 * @param codebase the codebase, if it was included in the header of the value
689 * type. Null if not codebase was included.
691 * @return the object, extracted from the stream.
694 * Read value from the input stream in the case when the value is not
695 * Streamable or CustomMarshalled.
697 public Serializable
readValue(InputStream in
, int offset
, Class clz
,
698 String repositoryID
, RunTime sender
)
700 if (in
instanceof HeadlessInput
)
701 ((HeadlessInput
) in
).subsequentCalls
= true;
704 Serializable object
= null;
708 g
= (gnuRuntime
) sender
;
711 catch (ClassCastException e
)
713 // Working with the other CORBA implementation.
717 org
.omg
.CORBA_2_3
.portable
.InputStream input
= (org
.omg
.CORBA_2_3
.portable
.InputStream
) in
;
719 if (Remote
.class.isAssignableFrom(clz
)
720 || ValueBase
.class.isAssignableFrom(clz
))
722 // Interface is narrowed into Stub.
723 if (clz
.isInterface())
726 clz
= Util
.loadClass(
727 PortableRemoteObjectDelegateImpl
.getStubClassName(clz
.getName()),
728 null, clz
.getClassLoader());
730 catch (ClassNotFoundException e
)
732 MARSHAL m
= new MARSHAL("Cannot get stub from interface "
733 + clz
.getClass().getName());
734 m
.minor
= Minor
.TargetConversion
;
739 // Remote needs special handling.
740 if (ObjectImpl
.class.isAssignableFrom(clz
))
742 // First read CORBA object reference.
743 Object ro
= input
.read_Object();
745 ObjectImpl obj
= (ObjectImpl
) ro
;
749 Delegate delegate
= obj
._get_delegate();
750 object
= instantiate(offset
, clz
, g
);
751 ((ObjectImpl
) object
)._set_delegate(delegate
);
753 // The object - specific data follows.
755 else if (org
.omg
.CORBA
.Object
.class.isAssignableFrom(clz
))
756 object
= (Serializable
) input
.read_Object();
759 object
= instantiate(offset
, clz
, g
);
761 // The sentence below prevents attempt to read the internal fields of the
762 // ObjectImpl (or RMI Stub) that might follow the object definition.
763 // Sun's jre 1.5 does not write this information. The stubs, generated
764 // by rmic, does not contain such fields.
765 if (object
instanceof ObjectImpl
)
768 if (object
instanceof Externalizable
)
772 CorbaInput stream
= new CorbaInput(input
, object
, this,
773 offset
, repositoryID
, g
);
775 byte version
= stream
.readByte();
777 throw new MARSHAL("Unsuported RMI-IIOP version " + version
);
779 ((Externalizable
) object
).readExternal(stream
);
783 MARSHAL m
= new MARSHAL("readExternal failed");
791 synchronized (io_format
)
793 mode
= io_format
.get(object
.getClass());
796 if (mode
== STANDARD
)
798 readFields(offset
, repositoryID
, object
, input
, g
);
804 Method m
= object
.getClass().getDeclaredMethod("readObject",
808 m
.setAccessible(true); // May be private.
810 CorbaInput stream
= new CorbaInput(input
,
811 object
, this, offset
, repositoryID
, g
);
813 byte version
= stream
.readByte();
815 throw new MARSHAL("Unsuported RMI-IIOP version "
818 // This would indicate is defaultWriteObject has been
820 // but the readObject method normally takes care about this.
821 boolean dwo
= stream
.readByte() != 0;
823 m
.invoke(object
, new Object
[] { stream
});
824 synchronized (io_format
)
826 io_format
.put(object
.getClass(), dwo ? CUSTOM_DWO
832 ex
.printStackTrace();
833 MARSHAL mx
= new MARSHAL(object
.getClass().getName()
834 + ".readObject failed");
839 catch (NoSuchMethodException e
)
841 // Read in a standard way.
842 synchronized (io_format
)
844 io_format
.put(object
.getClass(), STANDARD
);
845 readFields(offset
, repositoryID
, object
, input
, g
);
854 * Create an instance.
856 Serializable
instantiate(int offset
, Class clz
, gnuRuntime g
)
862 object
= (Serializable
) Vio
.instantiateAnyWay(clz
);
863 g
.objectWritten(object
, offset
);
867 MARSHAL m
= new MARSHAL("Unable to instantiate " + clz
);
868 m
.minor
= Minor
.Instantiation
;
876 * Read fields of the object.
878 void readFields(int offset
, String repositoryID
, Serializable object
,
879 org
.omg
.CORBA_2_3
.portable
.InputStream input
, gnuRuntime r
)
883 Class o_class
= object
.getClass();
887 // The returned field array must already be in canonical order.
888 Field
[] fields
= getWritableFields(o_class
);
892 for (int i
= 0; i
< fields
.length
; i
++)
894 // Full value type header expected ahead.
895 if (input
instanceof HeadlessInput
)
896 ((HeadlessInput
) input
).subsequentCalls
= true;
903 if (fc
== String
.class)
905 v
= input
.read_value(wStringValueHelper
);
907 else if (fc
== int.class)
908 v
= new Integer(input
.read_long());
909 else if (fc
== long.class)
910 v
= new Long(input
.read_longlong());
911 else if (fc
== double.class)
912 v
= new Double(input
.read_double());
913 else if (fc
== float.class)
914 v
= new Float(input
.read_float());
915 else if (fc
== boolean.class)
916 v
= input
.read_boolean() ? Boolean
.TRUE
: Boolean
.FALSE
;
917 else if (fc
== short.class)
918 v
= new Short(input
.read_short());
919 else if (fc
== byte.class)
920 v
= new Byte(input
.read_octet());
921 else if (fc
== char.class)
922 v
= new Character(input
.read_char());
923 else if (org
.omg
.CORBA
.Object
.class.isAssignableFrom(fc
)
924 || Remote
.class.isAssignableFrom(fc
))
926 v
= readValue(input
, offset
, fc
, null, r
);
930 v
= Vio
.read(input
, fc
);
938 MARSHAL m
= new MARSHAL("Cannot read " + o_class
.getName() + " field "
941 m
.minor
= Minor
.ValueFields
;