1 /*
   2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * Licensed Materials - Property of IBM
  27  * RMI-IIOP v1.0
  28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  29  *
  30  */
  31 
  32 package com.sun.corba.se.impl.io;
  33 
  34 import org.omg.CORBA.portable.OutputStream;
  35 
  36 import java.security.AccessController ;
  37 import java.security.PrivilegedAction ;
  38 
  39 import java.io.IOException;
  40 import java.io.InvalidClassException;
  41 import java.io.Externalizable;
  42 import java.io.NotSerializableException;
  43 import java.io.NotActiveException;
  44 
  45 import java.lang.reflect.InvocationTargetException;
  46 
  47 import javax.rmi.CORBA.Util;
  48 
  49 import sun.corba.Bridge ;
  50 
  51 import com.sun.corba.se.impl.util.Utility;
  52 import com.sun.corba.se.impl.util.RepositoryId;
  53 
  54 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  55 import com.sun.corba.se.impl.logging.UtilSystemException ;
  56 
  57 /**
  58  * IIOPOutputStream is ...
  59  *
  60  * @author  Stephen Lewallen
  61  * @since   JDK1.1.6
  62  */
  63 
  64 public class IIOPOutputStream
  65     extends com.sun.corba.se.impl.io.OutputStreamHook
  66 {
  67     private UtilSystemException wrapper = UtilSystemException.get(
  68         CORBALogDomains.RPC_ENCODING ) ;
  69 
  70     private static Bridge bridge =
  71         (Bridge)AccessController.doPrivileged(
  72             new PrivilegedAction() {
  73                 public Object run() {
  74                     return Bridge.get() ;
  75                 }
  76             }
  77         ) ;
  78 
  79     private org.omg.CORBA_2_3.portable.OutputStream orbStream;
  80 
  81     private Object currentObject = null;
  82 
  83     private ObjectStreamClass currentClassDesc = null;
  84 
  85     private int recursionDepth = 0;
  86 
  87     private int simpleWriteDepth = 0;
  88 
  89     private IOException abortIOException = null;
  90 
  91     private java.util.Stack classDescStack = new java.util.Stack();
  92 
  93     // Used when calling an object's writeObject method
  94     private Object[] writeObjectArgList = {this};
  95 
  96     public IIOPOutputStream()
  97         throws java.io.IOException
  98    {
  99         super();
 100     }
 101 
 102     // If using RMI-IIOP stream format version 2, this tells
 103     // the ORB stream (which must be a ValueOutputStream) to
 104     // begin a new valuetype to contain the optional data
 105     // of the writeObject method.
 106     protected void beginOptionalCustomData() {
 107 
 108         if (streamFormatVersion == 2) {
 109 
 110             org.omg.CORBA.portable.ValueOutputStream vout
 111                 = (org.omg.CORBA.portable.ValueOutputStream)orbStream;
 112 
 113             vout.start_value(currentClassDesc.getRMIIIOPOptionalDataRepId());
 114         }
 115     }
 116 
 117     final void setOrbStream(org.omg.CORBA_2_3.portable.OutputStream os) {
 118         orbStream = os;
 119     }
 120 
 121     final org.omg.CORBA_2_3.portable.OutputStream getOrbStream() {
 122         return orbStream;
 123     }
 124 
 125     final void increaseRecursionDepth(){
 126         recursionDepth++;
 127     }
 128 
 129     final int decreaseRecursionDepth(){
 130         return --recursionDepth;
 131     }
 132 
 133     /**
 134      * Override the actions of the final method "writeObject()"
 135      * in ObjectOutputStream.
 136      * @since     JDK1.1.6
 137      */
 138     public final void writeObjectOverride(Object obj)
 139         throws IOException
 140     {
 141         writeObjectState.writeData(this);
 142 
 143         Util.writeAbstractObject((OutputStream)orbStream, obj);
 144     }
 145 
 146     /**
 147      * Override the actions of the final method "writeObject()"
 148      * in ObjectOutputStream.
 149      * @since     JDK1.1.6
 150      */
 151     public final void simpleWriteObject(Object obj, byte formatVersion)
 152     /* throws IOException */
 153     {
 154         byte oldStreamFormatVersion = streamFormatVersion;
 155 
 156         streamFormatVersion = formatVersion;
 157 
 158         Object prevObject = currentObject;
 159         ObjectStreamClass prevClassDesc = currentClassDesc;
 160         simpleWriteDepth++;
 161 
 162         try {
 163             // if (!checkSpecialClasses(obj) && !checkSubstitutableSpecialClasses(obj))
 164             outputObject(obj);
 165 
 166         } catch (IOException ee) {
 167             if (abortIOException == null)
 168                 abortIOException = ee;
 169         } finally {
 170             /* Restore state of previous call incase this is a nested call */
 171             streamFormatVersion = oldStreamFormatVersion;
 172             simpleWriteDepth--;
 173             currentObject = prevObject;
 174             currentClassDesc = prevClassDesc;
 175         }
 176 
 177         /* If the recursion depth is 0, test for and clear the pending exception.
 178          * If there is a pending exception throw it.
 179          */
 180         IOException pending = abortIOException;
 181         if (simpleWriteDepth == 0)
 182             abortIOException = null;
 183         if (pending != null) {
 184             bridge.throwException( pending ) ;
 185         }
 186     }
 187 
 188     // Required by the superclass.
 189     ObjectStreamField[] getFieldsNoCopy() {
 190         return currentClassDesc.getFieldsNoCopy();
 191     }
 192 
 193     /**
 194      * Override the actions of the final method "defaultWriteObject()"
 195      * in ObjectOutputStream.
 196      * @since     JDK1.1.6
 197      */
 198     public final void defaultWriteObjectDelegate()
 199     /* throws IOException */
 200     {
 201         try {
 202             if (currentObject == null || currentClassDesc == null)
 203                 // XXX I18N, Logging needed.
 204                 throw new NotActiveException("defaultWriteObjectDelegate");
 205 
 206             ObjectStreamField[] fields =
 207                 currentClassDesc.getFieldsNoCopy();
 208             if (fields.length > 0) {
 209                 outputClassFields(currentObject, currentClassDesc.forClass(),
 210                                   fields);
 211             }
 212         } catch(IOException ioe) {
 213             bridge.throwException(ioe);
 214         }
 215     }
 216 
 217     /**
 218      * Override the actions of the final method "enableReplaceObject()"
 219      * in ObjectOutputStream.
 220      * @since     JDK1.1.6
 221      */
 222     public final boolean enableReplaceObjectDelegate(boolean enable)
 223     /* throws SecurityException */
 224     {
 225         return false;
 226 
 227     }
 228 
 229 
 230     protected final void annotateClass(Class<?> cl) throws IOException{
 231         // XXX I18N, Logging needed.
 232         throw new IOException("Method annotateClass not supported");
 233     }
 234 
 235     public final void close() throws IOException{
 236         // no op
 237     }
 238 
 239     protected final void drain() throws IOException{
 240         // no op
 241     }
 242 
 243     public final void flush() throws IOException{
 244         try{
 245             orbStream.flush();
 246         } catch(Error e) {
 247             IOException ioexc = new IOException(e.getMessage());
 248             ioexc.initCause(e) ;
 249             throw ioexc ;
 250         }
 251     }
 252 
 253     protected final Object replaceObject(Object obj) throws IOException{
 254         // XXX I18N, Logging needed.
 255         throw new IOException("Method replaceObject not supported");
 256     }
 257 
 258     /**
 259      * Reset will disregard the state of any objects already written
 260      * to the stream.  The state is reset to be the same as a new
 261      * ObjectOutputStream.  The current point in the stream is marked
 262      * as reset so the corresponding ObjectInputStream will be reset
 263      * at the same point.  Objects previously written to the stream
 264      * will not be refered to as already being in the stream.  They
 265      * will be written to the stream again.
 266      * @since     JDK1.1
 267      */
 268     public final void reset() throws IOException{
 269         try{
 270             //orbStream.reset();
 271 
 272             if (currentObject != null || currentClassDesc != null)
 273                 // XXX I18N, Logging needed.
 274                 throw new IOException("Illegal call to reset");
 275 
 276             abortIOException = null;
 277 
 278             if (classDescStack == null)
 279                 classDescStack = new java.util.Stack();
 280             else
 281                 classDescStack.setSize(0);
 282 
 283         } catch(Error e) {
 284             IOException ioexc = new IOException(e.getMessage());
 285             ioexc.initCause(e) ;
 286             throw ioexc ;
 287         }
 288     }
 289 
 290     public final void write(byte b[]) throws IOException{
 291         try{
 292             writeObjectState.writeData(this);
 293 
 294             orbStream.write_octet_array(b, 0, b.length);
 295         } catch(Error e) {
 296             IOException ioexc = new IOException(e.getMessage());
 297             ioexc.initCause(e) ;
 298             throw ioexc ;
 299         }
 300     }
 301 
 302     public final void write(byte b[], int off, int len) throws IOException{
 303         try{
 304             writeObjectState.writeData(this);
 305 
 306             orbStream.write_octet_array(b, off, len);
 307         } catch(Error e) {
 308             IOException ioexc = new IOException(e.getMessage());
 309             ioexc.initCause(e) ;
 310             throw ioexc ;
 311         }
 312     }
 313 
 314     public final void write(int data) throws IOException{
 315         try{
 316             writeObjectState.writeData(this);
 317 
 318             orbStream.write_octet((byte)(data & 0xFF));
 319         } catch(Error e) {
 320             IOException ioexc = new IOException(e.getMessage());
 321             ioexc.initCause(e) ;
 322             throw ioexc ;
 323         }
 324     }
 325 
 326     public final void writeBoolean(boolean data) throws IOException{
 327         try{
 328             writeObjectState.writeData(this);
 329 
 330             orbStream.write_boolean(data);
 331         } catch(Error e) {
 332             IOException ioexc = new IOException(e.getMessage());
 333             ioexc.initCause(e) ;
 334             throw ioexc ;
 335         }
 336     }
 337 
 338     public final void writeByte(int data) throws IOException{
 339         try{
 340             writeObjectState.writeData(this);
 341 
 342             orbStream.write_octet((byte)data);
 343         } catch(Error e) {
 344             IOException ioexc = new IOException(e.getMessage());
 345             ioexc.initCause(e) ;
 346             throw ioexc ;
 347         }
 348     }
 349 
 350     public final void writeBytes(String data) throws IOException{
 351         try{
 352             writeObjectState.writeData(this);
 353 
 354             byte buf[] = data.getBytes();
 355             orbStream.write_octet_array(buf, 0, buf.length);
 356         } catch(Error e) {
 357             IOException ioexc = new IOException(e.getMessage());
 358             ioexc.initCause(e) ;
 359             throw ioexc ;
 360         }
 361     }
 362 
 363     public final void writeChar(int data) throws IOException{
 364         try{
 365             writeObjectState.writeData(this);
 366 
 367             orbStream.write_wchar((char)data);
 368         } catch(Error e) {
 369             IOException ioexc = new IOException(e.getMessage());
 370             ioexc.initCause(e) ;
 371             throw ioexc ;
 372         }
 373     }
 374 
 375     public final void writeChars(String data) throws IOException{
 376         try{
 377             writeObjectState.writeData(this);
 378 
 379             char buf[] = data.toCharArray();
 380             orbStream.write_wchar_array(buf, 0, buf.length);
 381         } catch(Error e) {
 382             IOException ioexc = new IOException(e.getMessage());
 383             ioexc.initCause(e) ;
 384             throw ioexc ;
 385         }
 386     }
 387 
 388     public final void writeDouble(double data) throws IOException{
 389         try{
 390             writeObjectState.writeData(this);
 391 
 392             orbStream.write_double(data);
 393         } catch(Error e) {
 394             IOException ioexc = new IOException(e.getMessage());
 395             ioexc.initCause(e) ;
 396             throw ioexc ;
 397         }
 398     }
 399 
 400     public final void writeFloat(float data) throws IOException{
 401         try{
 402             writeObjectState.writeData(this);
 403 
 404             orbStream.write_float(data);
 405         } catch(Error e) {
 406             IOException ioexc = new IOException(e.getMessage());
 407             ioexc.initCause(e) ;
 408             throw ioexc ;
 409         }
 410     }
 411 
 412     public final void writeInt(int data) throws IOException{
 413         try{
 414             writeObjectState.writeData(this);
 415 
 416             orbStream.write_long(data);
 417         } catch(Error e) {
 418             IOException ioexc = new IOException(e.getMessage());
 419             ioexc.initCause(e) ;
 420             throw ioexc ;
 421         }
 422     }
 423 
 424     public final void writeLong(long data) throws IOException{
 425         try{
 426             writeObjectState.writeData(this);
 427 
 428             orbStream.write_longlong(data);
 429         } catch(Error e) {
 430             IOException ioexc = new IOException(e.getMessage());
 431             ioexc.initCause(e) ;
 432             throw ioexc ;
 433         }
 434     }
 435 
 436     public final void writeShort(int data) throws IOException{
 437         try{
 438             writeObjectState.writeData(this);
 439 
 440             orbStream.write_short((short)data);
 441         } catch(Error e) {
 442             IOException ioexc = new IOException(e.getMessage());
 443             ioexc.initCause(e) ;
 444             throw ioexc ;
 445         }
 446     }
 447 
 448     protected final void writeStreamHeader() throws IOException{
 449         // no op
 450     }
 451 
 452     /**
 453      * Helper method for correcting the Kestrel bug 4367783 (dealing
 454      * with larger than 8-bit chars).  The old behavior is preserved
 455      * in orbutil.IIOPInputStream_1_3 in order to interoperate with
 456      * our legacy ORBs.
 457      */
 458     protected void internalWriteUTF(org.omg.CORBA.portable.OutputStream stream,
 459                                     String data)
 460     {
 461         stream.write_wstring(data);
 462     }
 463 
 464     public final void writeUTF(String data) throws IOException{
 465         try{
 466             writeObjectState.writeData(this);
 467 
 468             internalWriteUTF(orbStream, data);
 469         } catch(Error e) {
 470             IOException ioexc = new IOException(e.getMessage());
 471             ioexc.initCause(e) ;
 472             throw ioexc ;
 473         }
 474     }
 475 
 476     // INTERNAL UTILITY METHODS
 477     /*
 478      * Check for special cases of serializing objects.
 479      * These objects are not subject to replacement.
 480      */
 481     private boolean checkSpecialClasses(Object obj) throws IOException {
 482 
 483         /*
 484          * If this is a class, don't allow substitution
 485          */
 486         //if (obj instanceof Class) {
 487         //    throw new IOException("Serialization of Class not supported");
 488         //}
 489 
 490         if (obj instanceof ObjectStreamClass) {
 491             // XXX I18N, Logging needed.
 492             throw new IOException("Serialization of ObjectStreamClass not supported");
 493         }
 494 
 495         return false;
 496     }
 497 
 498     /*
 499      * Check for special cases of substitutable serializing objects.
 500      * These classes are replaceable.
 501      */
 502     private boolean checkSubstitutableSpecialClasses(Object obj)
 503         throws IOException
 504     {
 505         if (obj instanceof String) {
 506             orbStream.write_value((java.io.Serializable)obj);
 507             return true;
 508         }
 509 
 510         //if (obj.getClass().isArray()) {
 511         //    outputArray(obj);
 512         //    return true;
 513         //}
 514 
 515         return false;
 516     }
 517 
 518     /*
 519      * Write out the object
 520      */
 521     private void outputObject(final Object obj) throws IOException{
 522 
 523         currentObject = obj;
 524         Class currclass = obj.getClass();
 525 
 526         /* Get the Class descriptor for this class,
 527          * Throw a NotSerializableException if there is none.
 528          */
 529         currentClassDesc = ObjectStreamClass.lookup(currclass);
 530         if (currentClassDesc == null) {
 531             // XXX I18N, Logging needed.
 532             throw new NotSerializableException(currclass.getName());
 533         }
 534 
 535         /* If the object is externalizable,
 536          * call writeExternal.
 537          * else do Serializable processing.
 538          */
 539         if (currentClassDesc.isExternalizable()) {
 540             // Write format version
 541             orbStream.write_octet(streamFormatVersion);
 542 
 543             Externalizable ext = (Externalizable)obj;
 544             ext.writeExternal(this);
 545 
 546         } else {
 547 
 548             /* The object's classes should be processed from supertype to subtype
 549              * Push all the clases of the current object onto a stack.
 550              * Remember the stack pointer where this set of classes is being pushed.
 551              */
 552             if (currentClassDesc.forClass().getName().equals("java.lang.String")) {
 553                     this.writeUTF((String)obj);
 554                     return;
 555             }
 556             int stackMark = classDescStack.size();
 557             try {
 558                 ObjectStreamClass next;
 559                 while ((next = currentClassDesc.getSuperclass()) != null) {
 560                     classDescStack.push(currentClassDesc);
 561                     currentClassDesc = next;
 562                 }
 563 
 564                 /*
 565                  * For currentClassDesc and all the pushed class descriptors
 566                  *    If the class is writing its own data
 567                  *                set blockData = true; call the class writeObject method
 568                  *    If not
 569                  *     invoke either the defaultWriteObject method.
 570                  */
 571                 do {
 572 
 573                     WriteObjectState oldState = writeObjectState;
 574 
 575                     try {
 576 
 577                         setState(NOT_IN_WRITE_OBJECT);
 578 
 579                         if (currentClassDesc.hasWriteObject()) {
 580                             invokeObjectWriter(currentClassDesc, obj );
 581                         } else {
 582                             defaultWriteObjectDelegate();
 583                         }
 584                     } finally {
 585                         setState(oldState);
 586                     }
 587 
 588                 } while (classDescStack.size() > stackMark &&
 589                          (currentClassDesc = (ObjectStreamClass)classDescStack.pop()) != null);
 590             } finally {
 591                 classDescStack.setSize(stackMark);
 592             }
 593         }
 594     }
 595 
 596     /*
 597      * Invoke writer.
 598      * _REVISIT_ invokeObjectWriter and invokeObjectReader behave inconsistently with each other since
 599      * the reader returns a boolean...fix later
 600      */
 601     private void invokeObjectWriter(ObjectStreamClass osc, Object obj)
 602         throws IOException
 603     {
 604         Class c = osc.forClass() ;
 605 
 606         try {
 607 
 608             // Write format version
 609             orbStream.write_octet(streamFormatVersion);
 610 
 611             writeObjectState.enterWriteObject(this);
 612 
 613             // writeObject(obj, c, this);
 614             osc.invokeWriteObject( obj, this ) ;
 615 
 616             writeObjectState.exitWriteObject(this);
 617 
 618         } catch (InvocationTargetException e) {
 619             Throwable t = e.getTargetException();
 620             if (t instanceof IOException)
 621                 throw (IOException)t;
 622             else if (t instanceof RuntimeException)
 623                 throw (RuntimeException) t;
 624             else if (t instanceof Error)
 625                 throw (Error) t;
 626             else
 627                 // XXX I18N, Logging needed.
 628                 throw new Error("invokeObjectWriter internal error",e);
 629         }
 630     }
 631 
 632     void writeField(ObjectStreamField field, Object value) throws IOException {
 633         switch (field.getTypeCode()) {
 634             case 'B':
 635                 if (value == null)
 636                     orbStream.write_octet((byte)0);
 637                 else
 638                     orbStream.write_octet(((Byte)value).byteValue());
 639                 break;
 640             case 'C':
 641                 if (value == null)
 642                     orbStream.write_wchar((char)0);
 643                 else
 644                     orbStream.write_wchar(((Character)value).charValue());
 645                 break;
 646             case 'F':
 647                 if (value == null)
 648                     orbStream.write_float((float)0);
 649                 else
 650                     orbStream.write_float(((Float)value).floatValue());
 651                 break;
 652             case 'D':
 653                 if (value == null)
 654                     orbStream.write_double((double)0);
 655                 else
 656                     orbStream.write_double(((Double)value).doubleValue());
 657                 break;
 658             case 'I':
 659                 if (value == null)
 660                     orbStream.write_long((int)0);
 661                 else
 662                     orbStream.write_long(((Integer)value).intValue());
 663                 break;
 664             case 'J':
 665                 if (value == null)
 666                     orbStream.write_longlong((long)0);
 667                 else
 668                     orbStream.write_longlong(((Long)value).longValue());
 669                 break;
 670             case 'S':
 671                 if (value == null)
 672                     orbStream.write_short((short)0);
 673                 else
 674                     orbStream.write_short(((Short)value).shortValue());
 675                 break;
 676             case 'Z':
 677                 if (value == null)
 678                     orbStream.write_boolean(false);
 679                 else
 680                     orbStream.write_boolean(((Boolean)value).booleanValue());
 681                 break;
 682             case '[':
 683             case 'L':
 684                 // What to do if it's null?
 685                 writeObjectField(field, value);
 686                 break;
 687             default:
 688                 // XXX I18N, Logging needed.
 689                 throw new InvalidClassException(currentClassDesc.getName());
 690             }
 691     }
 692 
 693     private void writeObjectField(ObjectStreamField field,
 694                                   Object objectValue) throws IOException {
 695 
 696         if (ObjectStreamClassCorbaExt.isAny(field.getTypeString())) {
 697             javax.rmi.CORBA.Util.writeAny(orbStream, objectValue);
 698         }
 699         else {
 700             Class type = field.getType();
 701             int callType = ValueHandlerImpl.kValueType;
 702 
 703             if (type.isInterface()) {
 704                 String className = type.getName();
 705 
 706                 if (java.rmi.Remote.class.isAssignableFrom(type)) {
 707 
 708                     // RMI Object reference...
 709 
 710                     callType = ValueHandlerImpl.kRemoteType;
 711 
 712 
 713                 } else if (org.omg.CORBA.Object.class.isAssignableFrom(type)){
 714 
 715                     // IDL Object reference...
 716                     callType = ValueHandlerImpl.kRemoteType;
 717 
 718                 } else if (RepositoryId.isAbstractBase(type)) {
 719                     // IDL Abstract Object reference...
 720                     callType = ValueHandlerImpl.kAbstractType;
 721                 } else if (ObjectStreamClassCorbaExt.isAbstractInterface(type)) {
 722                     callType = ValueHandlerImpl.kAbstractType;
 723                 }
 724             }
 725 
 726             switch (callType) {
 727             case ValueHandlerImpl.kRemoteType:
 728                 Util.writeRemoteObject(orbStream, objectValue);
 729                 break;
 730             case ValueHandlerImpl.kAbstractType:
 731                 Util.writeAbstractObject(orbStream, objectValue);
 732                 break;
 733             case ValueHandlerImpl.kValueType:
 734                 try{
 735                     orbStream.write_value((java.io.Serializable)objectValue, type);
 736                 }
 737                 catch(ClassCastException cce){
 738                     if (objectValue instanceof java.io.Serializable)
 739                         throw cce;
 740                     else
 741                         Utility.throwNotSerializableForCorba(objectValue.getClass().getName());
 742                 }
 743             }
 744         }
 745     }
 746 
 747     /* Write the fields of the specified class by invoking the appropriate
 748      * write* method on this class.
 749      */
 750     private void outputClassFields(Object o, Class cl,
 751                                    ObjectStreamField[] fields)
 752         throws IOException {
 753 
 754         for (int i = 0; i < fields.length; i++) {
 755             if (fields[i].getField() == null)
 756                 throw new InvalidClassException(cl.getName(),
 757                                                 "Nonexistent field " + fields[i].getName());
 758             switch (fields[i].getTypeCode()) {
 759                 case 'B':
 760                     byte byteValue = bridge.getByte(o, fields[i].getFieldID()) ;
 761                     orbStream.write_octet(byteValue);
 762                     break;
 763                 case 'C':
 764                     char charValue = bridge.getChar(o, fields[i].getFieldID()) ;
 765                     orbStream.write_wchar(charValue);
 766                     break;
 767                 case 'F':
 768                     float floatValue = bridge.getFloat(o, fields[i].getFieldID()) ;
 769                     orbStream.write_float(floatValue);
 770                     break;
 771                 case 'D' :
 772                     double doubleValue = bridge.getDouble(o, fields[i].getFieldID()) ;
 773                     orbStream.write_double(doubleValue);
 774                     break;
 775                 case 'I':
 776                     int intValue = bridge.getInt(o, fields[i].getFieldID()) ;
 777                     orbStream.write_long(intValue);
 778                     break;
 779                 case 'J':
 780                     long longValue = bridge.getLong(o, fields[i].getFieldID()) ;
 781                     orbStream.write_longlong(longValue);
 782                     break;
 783                 case 'S':
 784                     short shortValue = bridge.getShort(o, fields[i].getFieldID()) ;
 785                     orbStream.write_short(shortValue);
 786                     break;
 787                 case 'Z':
 788                     boolean booleanValue = bridge.getBoolean(o, fields[i].getFieldID()) ;
 789                     orbStream.write_boolean(booleanValue);
 790                     break;
 791                 case '[':
 792                 case 'L':
 793                     Object objectValue = bridge.getObject(o, fields[i].getFieldID()) ;
 794                     writeObjectField(fields[i], objectValue);
 795                     break;
 796                 default:
 797                     throw new InvalidClassException(cl.getName());
 798             }
 799         }
 800     }
 801 }