1 /*
   2  * Copyright (c) 1999, 2001, 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  * COMPONENT_NAME: idl.toJava
  27  *
  28  * ORIGINS: 27
  29  *
  30  * Licensed Materials - Property of IBM
  31  * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
  32  * RMI-IIOP v1.0
  33  *
  34  */
  35 
  36 package com.sun.tools.corba.se.idl.toJavaPortable;
  37 
  38 // NOTES:
  39 // -The ctor should really throw an exception, but then it must have a
  40 //  throws clause. How much of a ripple effect is this?
  41 // -F46082.51<daz> Remove -stateful feature.
  42 // -D60929   <klr> Update for RTF2.4 changes
  43 // -D61056   <klr> Use Util.helperName
  44 // -D62014   <klr> Move const definitions from signature to operations interf.
  45 // -D62310   <klr> Fix declaration of interfaces extending abstract intf.
  46 // -D62023   <klr> Move const definitions back from operations to signature.
  47 
  48 import java.io.PrintWriter;
  49 import java.util.Enumeration;
  50 import java.util.Hashtable;
  51 import java.util.Vector;
  52 
  53 import com.sun.tools.corba.se.idl.GenFileStream;
  54 import com.sun.tools.corba.se.idl.ConstEntry;
  55 import com.sun.tools.corba.se.idl.InterfaceEntry;
  56 import com.sun.tools.corba.se.idl.InterfaceState;
  57 import com.sun.tools.corba.se.idl.MethodEntry;
  58 import com.sun.tools.corba.se.idl.PrimitiveEntry;
  59 import com.sun.tools.corba.se.idl.SequenceEntry;
  60 import com.sun.tools.corba.se.idl.StringEntry;
  61 import com.sun.tools.corba.se.idl.SymtabEntry;
  62 import com.sun.tools.corba.se.idl.TypedefEntry;
  63 
  64 /**
  65  *
  66  **/
  67 public class InterfaceGen implements com.sun.tools.corba.se.idl.InterfaceGen, JavaGenerator
  68 {
  69   /**
  70    * Public zero-argument constructor.
  71    **/
  72   public InterfaceGen ()
  73   {
  74     //emit = ((Arguments)Compile.compiler.arguments).emit;
  75     //factories = (Factories)Compile.compiler.factories ();
  76   } // ctor
  77 
  78   /**
  79    * Generate the interface and all the files associated with it.
  80    * Provides general algorithm for binding generation:
  81    * 1.) Initialize symbol table and symbol table entry members, common to all generators.
  82    * 2.) Generate the skeleton if required by calling generateSkeletn ()
  83    * 3.) Generate the holder by calling generateHolder ()
  84    * 4.) Generate the helper by calling generateHelper ()
  85    * 5.) Generate the stub if required by calling generateStub ()
  86    * 6.) Generate the interface by calling generateInterface ()
  87    **/
  88   public void generate (Hashtable symbolTable, InterfaceEntry i, PrintWriter stream)
  89   {
  90     if (!isPseudo(i))
  91     {
  92       this.symbolTable = symbolTable;
  93       this.i           = i;
  94       init ();
  95 
  96       // for sun_local pragma, just generate the signature and operations interfaces
  97       // for sun_localservant pragma, generate the Local Stubs, and Skel, should not
  98       // have _invoke defined.
  99       // for local (is_local()) case, generate only Helpers and Holder, where they
 100       // have been modified to throw appropriate exceptions for read and write, and
 101       // narrow is modified to not invoke _is_a
 102 
 103       if (! (i.isLocalSignature())) {
 104           // generate the stubs and skeletons for non-local interfaces
 105           if (! (i.isLocal())) {
 106               // for local servant case just generate the skeleton, but
 107               // for others generate the stubs also
 108               generateSkeleton ();
 109 
 110               // _REVISIT_, Whenever there is time restructure the code to
 111               // encapsulate stub and skeleton generation.
 112 
 113               // If the option is -fallTie then generate the Tie class first
 114               // and then generate the ImplBase class to make the generation
 115               // complete for the Hierarchy.
 116               Arguments theArguments = (Arguments)Compile.compiler.arguments;
 117               if( (theArguments.TIEServer == true )
 118                 &&(theArguments.emit == theArguments.All ) )
 119               {
 120                   theArguments.TIEServer = false;
 121                   // Generate the ImplBase class
 122                   generateSkeleton ();
 123                   // Revert in case file contains multiple interfaces
 124                   theArguments.TIEServer = true;
 125               }
 126               generateStub ();
 127           }
 128           generateHolder ();
 129           generateHelper ();
 130       }
 131       intfType = SIGNATURE;
 132       generateInterface ();
 133       intfType = OPERATIONS;
 134       generateInterface ();
 135       intfType = 0;
 136     }
 137   } // generate
 138 
 139   /**
 140    * Initialize members unique to this generator.
 141    **/
 142   protected void init ()
 143   {
 144     emit = ((Arguments)Compile.compiler.arguments).emit;
 145     factories = (Factories)Compile.compiler.factories ();
 146   } // init
 147 
 148   /**
 149    * Generate a Skeleton when the user does not want just the client-side code.
 150    **/
 151   protected void generateSkeleton ()
 152   {
 153     // <f46082.51> Remove -stateful feature.
 154     // The Skeleton is generated only when the user doesn't want
 155     // JUST the client code OR when the interface is stateful
 156     //if (emit != Arguments.Client || i.state () != null)
 157     //  factories.skeleton ().generate (symbolTable, i);
 158     if (emit != Arguments.Client)
 159       factories.skeleton ().generate (symbolTable, i);
 160   } // generateSkeleton
 161 
 162   /**
 163    * Generate a Stub when the user does not want just the server-side code.
 164    **/
 165   protected void generateStub ()
 166   {
 167     // <klr> According to Simon on 10/28/98, we should generate stubs for
 168     // abstract interfaces too.
 169     if (emit != Arguments.Server /* && !i.isAbstract () */)
 170       factories.stub ().generate (symbolTable, i);
 171   } // generateStub
 172 
 173   /**
 174    * Generate a Helper when the user does not want just the server-side code.
 175    **/
 176   protected void generateHelper ()
 177   {
 178     if (emit != Arguments.Server)
 179       factories.helper ().generate (symbolTable, i);
 180   } // generateHelper
 181 
 182   /**
 183    * Generate a Holder when the user does not want just the server-side code.
 184    **/
 185   protected void generateHolder ()
 186   {
 187     if (emit != Arguments.Server)
 188       factories.holder ().generate (symbolTable, i);
 189   } // generateHolder
 190 
 191   /**
 192    * Generate the interface. Provides general algorithm for binding generation:
 193    * 1.) Initialize members unique to this generator. - init ()
 194    * 2.) Open print stream - openStream ()
 195    * 3.) Write class heading (package, prologue, class statement, open curly - writeHeading ()
 196    * 4.) Write class body (member data and methods) - write*Body ()
 197    * 5.) Write class closing (close curly) - writeClosing ()
 198    * 6.) Close the print stream - closeStream ()
 199    *
 200    * For CORBA 2.3, interfaces are mapped to Operations and Signature
 201    * interfaces. The Operations interface contains the method definitions.
 202    * The Signature interface extends the Operations interface and adds
 203    * CORBA::Object. <klr>
 204    **/
 205   protected void generateInterface ()
 206   {
 207     init ();
 208     openStream ();
 209     if (stream == null)
 210       return;
 211     writeHeading ();
 212     if (intfType == OPERATIONS)
 213       writeOperationsBody ();
 214     if (intfType == SIGNATURE)
 215       writeSignatureBody ();
 216     writeClosing ();
 217     closeStream ();
 218   } // generateInterface
 219 
 220   /**
 221    *
 222    **/
 223   protected void openStream ()
 224   {
 225     if (i.isAbstract () || intfType == SIGNATURE)
 226        stream = Util.stream (i, ".java");
 227     else if (intfType == OPERATIONS)
 228        stream = Util.stream (i, "Operations.java");
 229   } // openStream
 230 
 231   /**
 232    *
 233    **/
 234   protected void writeHeading ()
 235   {
 236     Util.writePackage (stream, i, Util.TypeFile);
 237     Util.writeProlog (stream, ((GenFileStream)stream).name ());
 238 
 239     // Transfer interface comment to target <31jul1997>.
 240     if (i.comment () != null)
 241       i.comment ().generate ("", stream);
 242 
 243     String className = i.name ();
 244 //  if (((Arguments)Compile.compiler.arguments).TIEServer)
 245 //  {
 246 //    // For the delegate model, don't make interface a subclass of CORBA.Object
 247 //    stream.print ("public interface " + className);
 248 //    boolean firstTime = true;
 249 //    for (int ii = 0; ii < i.derivedFrom ().size (); ++ii)
 250 //    {
 251 //      SymtabEntry parent = (SymtabEntry)i.derivedFrom ().elementAt (ii);
 252 //      if (!parent.fullName ().equals ("org/omg/CORBA/Object"))
 253 //      {
 254 //        if (firstTime)
 255 //        {
 256 //          firstTime = false;
 257 //          stream.print (" extends ");
 258 //        }
 259 //        else
 260 //          stream.print (", ");
 261 //        stream.print (Util.javaName (parent));
 262 //      }
 263 //    }
 264 //    if (i.derivedFrom ().size () > 0)
 265 //      stream.print (", ");
 266 //    stream.print ("org.omg.CORBA.portable.IDLEntity ");
 267 //  }
 268 //
 269 //  else
 270 //  {
 271       if (intfType == SIGNATURE)
 272          writeSignatureHeading ();
 273       else if (intfType == OPERATIONS)
 274          writeOperationsHeading ();
 275 //  }
 276 
 277     stream.println ();
 278     stream.println ('{');
 279   } // writeHeading
 280 
 281   /**
 282    *
 283    **/
 284   protected void writeSignatureHeading ()
 285   {
 286     String className = i.name ();
 287     stream.print ("public interface " + className + " extends " + className + "Operations, ");
 288     boolean firstTime = true;
 289     boolean hasNonAbstractParent = false; // <d62310-klr>
 290     for (int k = 0; k < i.derivedFrom ().size (); ++k)
 291     {
 292       if (firstTime)
 293         firstTime = false;
 294       else
 295         stream.print (", ");
 296       InterfaceEntry parent = (InterfaceEntry)i.derivedFrom ().elementAt (k);
 297       stream.print (Util.javaName (parent));
 298       if (! parent.isAbstract ()) // <d62310-klr>
 299         hasNonAbstractParent = true; // <d62310-klr>
 300     }
 301     // <d62310-klr> - begin
 302     // If this interface extends only abstract interfaces,
 303     // it should extend both org.omg.CORBA.Object and IDLEntity.
 304     if (!hasNonAbstractParent) {
 305       stream.print (", org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity ");
 306     }
 307     else {
 308     // <d62310-klr> - end
 309         // extends IDLEntity if there's only one default parent - CORBA.Object
 310         if (i.derivedFrom ().size () == 1)
 311           stream.print (", org.omg.CORBA.portable.IDLEntity ");
 312     }
 313   } // writeSignatureHeading
 314 
 315   /**
 316    *
 317    **/
 318   protected void writeOperationsHeading ()
 319   {
 320     stream.print ("public interface " + i.name ());
 321     if ( !i.isAbstract ())
 322       stream.print ("Operations ");
 323     else {
 324         // <d60929> - base abstract interfaces extend AbstractBase
 325         // changed to IDLEntity by SCN per latest spec...
 326         if (i.derivedFrom ().size () == 0)
 327           stream.print (" extends org.omg.CORBA.portable.IDLEntity");
 328     }
 329 
 330     boolean firstTime = true;
 331     for (int k = 0; k < i.derivedFrom ().size (); ++k)
 332     {
 333       InterfaceEntry parent = (InterfaceEntry) i.derivedFrom ().elementAt (k);
 334       String parentName = Util.javaName (parent);
 335 
 336       // ignore the default parent - CORBA.Object
 337       if (parentName.equals ("org.omg.CORBA.Object"))
 338           continue;
 339 
 340       if (firstTime)
 341       {
 342         firstTime = false;
 343         stream.print (" extends ");
 344       }
 345       else
 346         stream.print (", ");
 347 
 348       // Don't append suffix Operations to the parents of abstract interface
 349       // or to the abstract parents of regular interface
 350       if (parent.isAbstract () || i.isAbstract ())
 351         stream.print (parentName);
 352       else
 353         stream.print (parentName + "Operations");
 354     }
 355   } // writeOperationsHeading
 356 
 357 
 358   /**
 359    *
 360    **/
 361   protected void writeOperationsBody ()
 362   {
 363     // Generate everything but constants
 364     Enumeration e = i.contained ().elements ();
 365     while (e.hasMoreElements ())
 366     {
 367       SymtabEntry contained = (SymtabEntry)e.nextElement ();
 368       if (contained instanceof MethodEntry)
 369       {
 370         MethodEntry element = (MethodEntry)contained;
 371         ((MethodGen)element.generator ()).interfaceMethod (symbolTable, element, stream);
 372       }
 373       else
 374         if ( !(contained instanceof ConstEntry))
 375           contained.generate (symbolTable, stream);
 376     }
 377   } // writeOperationsBody
 378 
 379   /**
 380    *
 381    **/
 382   protected void writeSignatureBody ()
 383   {
 384     // Generate only constants
 385     Enumeration e = i.contained ().elements ();
 386     while (e.hasMoreElements ())
 387     {
 388       SymtabEntry contained = (SymtabEntry)e.nextElement ();
 389       if (contained instanceof ConstEntry)
 390         contained.generate (symbolTable, stream);
 391     }
 392   } // writeSignatureBody
 393 
 394   /**
 395    *
 396    **/
 397   protected void writeClosing ()
 398   {
 399     String intfName = i.name ();
 400     if ( !i.isAbstract () && intfType == OPERATIONS)
 401       intfName = intfName + "Operations";
 402     stream.println ("} // interface " + intfName);
 403   } // writeClosing
 404 
 405   /**
 406    *
 407    **/
 408   protected void closeStream ()
 409   {
 410     stream.close ();
 411   } // closeStream
 412 
 413   ///////////////
 414   // From JavaGenerator
 415 
 416   // <f46082.51> Remove -stateful feature.
 417   /*
 418   public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 419   {
 420     InterfaceEntry i = (InterfaceEntry)entry;
 421     if (i.state () != null && i.state ().size () > 0)
 422       index = structHelperType (index, indent, tcoffsets, name, entry, stream);
 423     else
 424     {
 425       tcoffsets.set (entry);
 426       if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 427         stream.println (indent + name
 428             + " = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_objref);");
 429       else
 430         stream.println (indent + name
 431             // <54697>
 432             //+ " = org.omg.CORBA.ORB.init ().create_interface_tc (_id, "
 433             + " = org.omg.CORBA.ORB.init ().create_interface_tc (" + Util.helperName (i, true) + ".id (), " // <d61056>
 434             + '\"' + Util.stripLeadingUnderscores (entry.name ()) + "\");");
 435     }
 436     return index;
 437   } // helperType
 438   */
 439   public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 440   {
 441     InterfaceEntry i = (InterfaceEntry)entry;
 442     tcoffsets.set (entry);
 443     if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 444       stream.println (indent + name
 445           + " = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_objref);");
 446     else
 447       stream.println (indent + name
 448           // <54697>
 449           //+ " = org.omg.CORBA.ORB.init ().create_interface_tc (_id, "
 450           + " = org.omg.CORBA.ORB.init ().create_interface_tc (" + Util.helperName (i, true) + ".id (), " // <d61056>
 451           + '\"' + Util.stripLeadingUnderscores (entry.name ()) + "\");");
 452     return index;
 453   } // helperType
 454 
 455   public int type (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream) {
 456     stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();"); // <d61056>
 457     return index;
 458   } // type
 459 
 460   // <f46082.51> Remove -stateful feature.
 461   /*
 462   public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 463   {
 464     InterfaceEntry i = (InterfaceEntry)entry;
 465     if (i.state () != null)
 466       structHelperRead (entryName, i, stream);
 467     else
 468     {
 469       if (i.isAbstract ())
 470          stream.println ("    return narrow (((org.omg.CORBA_2_3.portable.InputStream)istream).read_abstract_interface (_" + i.name () + "Stub.class));"); // <d60929>
 471       else
 472          stream.println ("    return narrow (istream.read_Object (_" + i.name () + "Stub.class));");
 473     }
 474   } // helperRead
 475 
 476   */
 477   public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 478   {
 479     InterfaceEntry i = (InterfaceEntry)entry;
 480     if (i.isAbstract ())
 481       stream.println ("    return narrow (((org.omg.CORBA_2_3.portable.InputStream)istream).read_abstract_interface (_" + i.name () + "Stub.class));"); // <d60929>
 482     else
 483       stream.println ("    return narrow (istream.read_Object (_" + i.name () + "Stub.class));");
 484   } // helperRead
 485 
 486   // <f46082.51> Remove -stateful feature.
 487   /*
 488   public void helperWrite (SymtabEntry entry, PrintWriter stream)
 489   {
 490     InterfaceEntry i = (InterfaceEntry)entry;
 491     if (i.state () != null)
 492       structHelperWrite (entry, stream);
 493     else
 494       write (0, "    ", "value", entry, stream);
 495   } // helperWrite
 496   */
 497   public void helperWrite (SymtabEntry entry, PrintWriter stream)
 498   {
 499     write (0, "    ", "value", entry, stream);
 500   } // helperWrite
 501 
 502   // <f46082.51> Remove -stateful feature.
 503   /*
 504   public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 505   {
 506     InterfaceEntry i = (InterfaceEntry)entry;
 507     if (i.state () != null)
 508       index = structRead (index, indent, name, i, stream);
 509     else
 510     {
 511       if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 512         stream.println (indent + name + " = istream.read_Object (_" + i.name () + "Stub.class);");
 513       else
 514         stream.println (indent + name + " = " + Util.helperName (entry, false) + ".narrow (istream.read_Object (_" + i.name () + "Stub.class));"); // <d61056>
 515     }
 516     return index;
 517   } // read
 518   */
 519   public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 520   {
 521     InterfaceEntry i = (InterfaceEntry)entry;
 522     if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 523       stream.println (indent + name + " = istream.read_Object (_" + i.name () + "Stub.class);");
 524     else
 525       stream.println (indent + name + " = " + Util.helperName (entry, false) + ".narrow (istream.read_Object (_" + i.name () + "Stub.class));"); // <d61056>
 526     return index;
 527   } // read
 528 
 529   // <f46082.51> Remove -stateful feature.
 530   /*
 531   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 532   {
 533     InterfaceEntry i = (InterfaceEntry)entry;
 534     if (i.state () != null)
 535       index = structWrite (index, indent, name, entry, stream);
 536     else
 537     {
 538       if (i.isAbstract ())
 539          stream.println (indent + "((org.omg.CORBA_2_3.portable.OutputStream)ostream).write_abstract_interface ((java.lang.Object) " + name + ");"); // <d60929>
 540       else
 541          stream.println (indent + "ostream.write_Object ((org.omg.CORBA.Object) " + name + ");");
 542     }
 543     return index;
 544   } // write
 545   */
 546   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 547   {
 548     InterfaceEntry i = (InterfaceEntry)entry;
 549     if (i.isAbstract ())
 550       stream.println (indent + "((org.omg.CORBA_2_3.portable.OutputStream)ostream).write_abstract_interface ((java.lang.Object) " + name + ");"); // <d60929>
 551     else
 552       stream.println (indent + "ostream.write_Object ((org.omg.CORBA.Object) " + name + ");");
 553     return index;
 554   } // write
 555 
 556   // <f46082.51> Remove -stateful feature.
 557   /*
 558   // These methods are cobbled from StructGen.  Stateful interfaces
 559   // are sent across the wire as if they were structs, with the first
 560   // element being a string - the Java name of the class.
 561 
 562   public int structHelperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 563   {
 564     TCOffsets innerOffsets = new TCOffsets ();
 565     innerOffsets.set (entry);
 566     int offsetForStruct = innerOffsets.currentOffset ();
 567     InterfaceEntry i = (InterfaceEntry)entry;
 568     String membersName = "_members" + index++;
 569     Vector state = i.state ();
 570     stream.println (indent + "org.omg.CORBA.StructMember[] " + membersName + " = new org.omg.CORBA.StructMember [" + (state.size () + 1) + "];");
 571     String tcOfMembers = "_tcOf" + membersName;
 572     stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + ';');
 573 
 574     // The name string is the first element of the struct
 575     String memberName = "_name";
 576     StringEntry stringEntry = Compile.compiler.factory.stringEntry ();
 577     index = ((JavaGenerator)stringEntry.generator ()).helperType (index, indent, innerOffsets, tcOfMembers, stringEntry, stream);
 578     stream.println (indent + membersName + "[0] = new org.omg.CORBA.StructMember (");
 579     stream.println (indent + "  \"" + memberName + "\",");
 580     stream.println (indent + "  " + tcOfMembers + ',');
 581     stream.println (indent + "  null);");
 582     int offsetSoFar = innerOffsets.currentOffset ();
 583     innerOffsets = new TCOffsets ();
 584     innerOffsets.set (entry);
 585     innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForStruct);
 586 
 587     for (int idx = 0; idx < state.size (); ++idx)
 588     {
 589       TypedefEntry member = ((InterfaceState)state.elementAt (idx)).entry;
 590       memberName = member.name ();
 591       index = ((JavaGenerator)member.generator ()).helperType (index, indent, innerOffsets, tcOfMembers, member, stream);
 592       stream.println (indent + membersName + '[' + (idx + 1) + "] = new org.omg.CORBA.StructMember (");
 593       stream.println (indent + "  \"" + memberName + "\",");
 594       stream.println (indent + "  " + tcOfMembers + ',');
 595       stream.println (indent + "  null);");
 596       offsetSoFar = innerOffsets.currentOffset ();
 597       innerOffsets = new TCOffsets ();
 598       innerOffsets.set (entry);
 599       innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForStruct);
 600     }
 601     tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
 602     stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_struct_tc (id (), \"" + entry.name () + "\", " + membersName + ");");
 603     return index;
 604   } // structHelperType
 605 
 606   public void structHelperRead (String entryName, InterfaceEntry entry, PrintWriter stream)
 607   {
 608     String impl = implName ((InterfaceEntry)entry);
 609     stream.println ("      " + Util.javaStatefulName (entry) + " value = null;");
 610     structRead (0, "      ", "value", entry, stream);
 611     stream.println ("      return value;");
 612   } // structHelperRead
 613 
 614   private String implName (InterfaceEntry entry)
 615   {
 616     String name;
 617     if (entry.container ().name ().equals (""))
 618       name =  '_' + entry.name () + "Impl";
 619     else
 620       name = Util.containerFullName (entry.container ()) + "._" + entry.name () + "Impl";
 621     return name.replace ('/', '.');
 622   } // implName
 623 
 624   public int structRead (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 625   {
 626     // The first element will be the name of the Java implementation class.
 627     String stringName = "_name" + index++;
 628     stream.println (indent + "String " + stringName + " = istream.read_string ();");
 629     stream.println (indent + "try");
 630     stream.println (indent + "{");
 631     stream.println (indent + "  " + name + " = (" + Util.javaStatefulName (entry) + ")com.sun.CORBA.iiop.ORB.getImpl (" + stringName + ".replace ('/', '.'));");
 632     stream.println (indent + "}");
 633     stream.println (indent + "catch (Exception e)");
 634     stream.println (indent + "{");
 635     stream.println (indent + "  " + name + " = null;");
 636     stream.println (indent + "}");
 637     stream.println (indent + "if (" + name + " == null)");
 638     stream.println (indent + "  throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 639     stream.println ();
 640 
 641     stream.println (indent + "if (!" + stringName + ".equals (\"" + entry.fullName () + "\"))");
 642     stream.println (indent + '{');
 643     stream.println (indent + "  Class _cls = " + name + ".getClass ();");
 644     stream.println (indent + "  boolean _found = false;");
 645     stream.println (indent + "  while (!_found && _cls != null)");
 646     stream.println (indent + "  {");
 647     stream.println (indent + "    Class[] interfaces = _cls.getInterfaces ();");
 648     stream.println (indent + "    for (int i = 0; i < interfaces.length; ++i)");
 649     stream.println (indent + "      if (interfaces[i].getName ().indexOf (\"State\") > 0)");
 650     stream.println (indent + "      {");
 651     stream.println (indent + "        _cls = interfaces[i];");
 652     stream.println (indent + "        _found = true;");
 653     stream.println (indent + "        break;");
 654     stream.println (indent + "      }");
 655     stream.println (indent + "    if (!_found)");
 656     stream.println (indent + "      _cls = _cls.getSuperclass ();");
 657     stream.println (indent + "  }");
 658     stream.println (indent + "  if (_cls == null)");
 659     stream.println (indent + "    throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 660     stream.println ();
 661     stream.println (indent + "  String _className = _cls.getName ();");
 662     stream.println (indent + "  int _index = _className.lastIndexOf ('.');");
 663     stream.println (indent + "  String _helperName = _className.substring (0, _index + 1) + _className.substring (_index + 2, _className.length () - 5) + \"Helper\"; // 5 == \"State\".length");
 664     stream.println (indent + "  try");
 665     stream.println (indent + "  {");
 666     stream.println (indent + "    Class _helperClass = Class.forName (_helperName);");
 667     stream.println (indent + "    Class[] _formalParms = new Class [1];");
 668     stream.println (indent + "    _formalParms[0] = Class.forName (\"org.omg.CORBA.portable.InputStream\");");
 669     stream.println (indent + "    java.lang.reflect.Method _read = _helperClass.getMethod (\"read\", _formalParms);");
 670     stream.println (indent + "    Object[] _actualParms = new Object [1];");
 671     stream.println (indent + "    _actualParms[0] = istream;");
 672     stream.println (indent + "      " + name + " = (" + Util.javaStatefulName (entry) + ")_read.invoke (null, _actualParms);");
 673     stream.println (indent + "  }");
 674     stream.println (indent + "  catch (Exception e)");
 675     stream.println (indent + "  {");
 676     stream.println (indent + "    throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 677     stream.println (indent + "  }");
 678     stream.println (indent + '}');
 679 
 680     // instantiate an implementation
 681     stream.println (indent + "else");
 682     stream.println (indent + '{');
 683 
 684     // Load the state
 685     readState (index, indent, name, (InterfaceEntry)entry, stream);
 686 
 687     stream.println (indent + '}');
 688     return index;
 689   } // structRead
 690 
 691   private void readState (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 692   {
 693     // First write the state from all parents
 694     Enumeration e = entry.derivedFrom ().elements ();
 695     while (e.hasMoreElements ())
 696     {
 697       InterfaceEntry parent = (InterfaceEntry)e.nextElement ();
 698       if (parent.state () != null)
 699       {
 700         if (parent.state ().size () > 0)
 701           readState (index, indent, name, parent, stream);
 702         break;
 703       }
 704     }
 705 
 706     // Now write the state for the local entry
 707     e = entry.state ().elements ();
 708     while (e.hasMoreElements ())
 709     {
 710       TypedefEntry member = ((InterfaceState)e.nextElement ()).entry;
 711       String tmpName = '_' + member.name () + "Tmp";
 712       Util.writeInitializer (indent + "  ", tmpName, "", member, stream);
 713       if (!member.arrayInfo ().isEmpty () || member.type () instanceof SequenceEntry || member.type () instanceof PrimitiveEntry || member.type () instanceof StringEntry)
 714         index = ((JavaGenerator)member.generator ()).read (index, indent + "  ", tmpName, member, stream);
 715       else
 716         stream.println (indent + "  " + tmpName + " = " + Util.helperName (member.type (), true) + ".read (istream);"); // <d61056>
 717       stream.println (indent + "  " + name + '.' + member.name () + " (" + tmpName + ");");
 718     }
 719   } // readState
 720 
 721   public void structHelperWrite (SymtabEntry entry, PrintWriter stream)
 722   {
 723     structWrite (0, "      ", "value", entry, stream);
 724   } // structHelperWrite
 725 
 726   public int structWrite (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 727   {
 728     // The first element of the struct must be the name of the real interface.
 729     stream.println (indent + "Class _cls = " + name + ".getClass ();");
 730     stream.println (indent + "boolean _found = false;");
 731     stream.println (indent + "while (!_found && _cls != null)");
 732     stream.println (indent + "{");
 733     stream.println (indent + "  Class[] interfaces = _cls.getInterfaces ();");
 734     stream.println (indent + "  for (int i = 0; i < interfaces.length; ++i)");
 735     stream.println (indent + "    if (interfaces[i].getName ().indexOf (\"State\") > 0)");
 736     stream.println (indent + "    {");
 737     stream.println (indent + "      _cls = interfaces[i];");
 738     stream.println (indent + "      _found = true;");
 739     stream.println (indent + "      break;");
 740     stream.println (indent + "    }");
 741     stream.println (indent + "  if (!_found)");
 742     stream.println (indent + "    _cls = _cls.getSuperclass ();");
 743     stream.println (indent + '}');
 744     stream.println ();
 745     stream.println (indent + "if (_cls == null)");
 746     stream.println (indent + "  throw new org.omg.CORBA.MARSHAL (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 747     stream.println ();
 748     stream.println (indent + "String _className = _cls.getName ();");
 749     stream.println (indent + "int _index = _className.lastIndexOf ('.');");
 750     stream.println (indent + "String _interfaceName = _className.substring (0, _index + 1) + _className.substring (_index + 2, _className.length () - 5); // 5 == \"State\".length");
 751     stream.println (indent + "ostream.write_string (_interfaceName.replace ('.', '/'));");
 752 
 753     // If _className != Util.javaName (entry), then call that class's helper class.
 754     stream.println ();
 755     stream.println (indent + "if (!_interfaceName.equals (\"" + Util.javaName (entry) + "\"))");
 756     stream.println (indent + '{');
 757     stream.println (indent + "  try");
 758     stream.println (indent + "  {");
 759     stream.println (indent + "    Class _helperClass = Class.forName (_interfaceName + \"Helper\");");
 760     stream.println (indent + "    Class[] _formalParms = new Class [2];");
 761     stream.println (indent + "    _formalParms[0] = Class.forName (\"org.omg.CORBA.portable.OutputStream\");");
 762     stream.println (indent + "    _formalParms[1] = _cls;");
 763     stream.println (indent + "    java.lang.reflect.Method _write = _helperClass.getMethod (\"write\", _formalParms);");
 764     stream.println (indent + "    Object[] _actualParms = new Object [2];");
 765     stream.println (indent + "    _actualParms[0] = ostream;");
 766     stream.println (indent + "    _actualParms[1] = " + name + ';');
 767     stream.println (indent + "    _write.invoke (null, _actualParms);");
 768     stream.println (indent + "  }");
 769     stream.println (indent + "  catch (Exception e)");
 770     stream.println (indent + "  {");
 771     stream.println (indent + "    throw new org.omg.CORBA.MARSHAL (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 772     stream.println (indent + "  }");
 773     stream.println (indent + '}');
 774 
 775     stream.println (indent + "else");
 776     stream.println (indent + '{');
 777 
 778     writeState (index, indent, name, (InterfaceEntry)entry, stream);
 779 
 780     stream.println (indent + '}');
 781     return index;
 782   } // structWrite
 783 
 784   private void writeState (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 785   {
 786     // First write the state from all parents
 787     Enumeration e = entry.derivedFrom ().elements ();
 788     while (e.hasMoreElements ())
 789     {
 790       InterfaceEntry parent = (InterfaceEntry)e.nextElement ();
 791       if (parent.state () != null)
 792       {
 793         if (parent.state ().size () > 0)
 794           writeState (index, indent, name, parent, stream);
 795         break;
 796       }
 797     }
 798 
 799     // Now write the state for the local entry
 800     Vector members = entry.state ();
 801     for (int i = 0; i < members.size (); ++i)
 802     {
 803       TypedefEntry member = ((InterfaceState)members.elementAt (i)).entry;
 804       if (!member.arrayInfo ().isEmpty () || member.type () instanceof SequenceEntry || member.type () instanceof PrimitiveEntry || member.type () instanceof StringEntry)
 805         index = ((JavaGenerator)member.generator ()).write (index, indent + "  ", name + '.' + member.name () + "()", member, stream);
 806       else
 807         stream.println (indent + "  " + Util.helperName (member.type (), true) + ".write (ostream, " + name + '.' + member.name () + " ());"); // <d61056>
 808     }
 809   } // writeState
 810   */
 811 
 812   /**
 813    * @return true if the entry is for a CORBA pseudo-object.
 814    **/
 815   private boolean isPseudo(InterfaceEntry i) {
 816     java.lang.String fullname = i.fullName();
 817     if (fullname.equalsIgnoreCase("CORBA/TypeCode"))
 818         return true;
 819     if (fullname.equalsIgnoreCase("CORBA/Principal"))
 820         return true;
 821     if (fullname.equalsIgnoreCase("CORBA/ORB"))
 822         return true;
 823     if (fullname.equalsIgnoreCase("CORBA/Any"))
 824         return true;
 825     if (fullname.equalsIgnoreCase("CORBA/Context"))
 826         return true;
 827     if (fullname.equalsIgnoreCase("CORBA/ContextList"))
 828         return true;
 829     if (fullname.equalsIgnoreCase("CORBA/DynamicImplementation"))
 830         return true;
 831     if (fullname.equalsIgnoreCase("CORBA/Environment"))
 832         return true;
 833     if (fullname.equalsIgnoreCase("CORBA/ExceptionList"))
 834         return true;
 835     if (fullname.equalsIgnoreCase("CORBA/NVList"))
 836         return true;
 837     if (fullname.equalsIgnoreCase("CORBA/NamedValue"))
 838         return true;
 839     if (fullname.equalsIgnoreCase("CORBA/Request"))
 840         return true;
 841     if (fullname.equalsIgnoreCase("CORBA/ServerRequest"))
 842         return true;
 843     if (fullname.equalsIgnoreCase("CORBA/UserException"))
 844         return true;
 845     return false;
 846   }
 847 
 848   // From JavaGenerator
 849   ///////////////
 850 
 851   protected int            emit        = 0;
 852   protected Factories      factories   = null;
 853 
 854   protected Hashtable      symbolTable = null;
 855   protected InterfaceEntry i           = null;
 856   protected PrintWriter    stream      = null;
 857 
 858   // <f46082.03, f46838.1/.2/.3> Modify access to protected.
 859   protected static final   int SIGNATURE  = 1;
 860   protected static final   int OPERATIONS = 2;
 861   protected                int intfType   = 0;
 862 } // class InterfaceGen