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    * <ol>
 194    * <li> Initialize members unique to this generator - init()</li>
 195    * <li> Open print stream - openStream()</li>
 196    * <li> Write class heading (package, prologue, class statement, open curly - writeHeading()</li>
 197    * <li> Write class body (member data and methods) - write*Body()</li>
 198    * <li> Write class closing (close curly) - writeClosing()</li>
 199    * <li> Close the print stream - closeStream ()</li>
 200    * </ol>
 201    *
 202    * For CORBA 2.3, interfaces are mapped to Operations and Signature
 203    * interfaces. The Operations interface contains the method definitions.
 204    * The Signature interface extends the Operations interface and adds
 205    * CORBA::Object. (klr)
 206    **/
 207   protected void generateInterface ()
 208   {
 209     init ();
 210     openStream ();
 211     if (stream == null)
 212       return;
 213     writeHeading ();
 214     if (intfType == OPERATIONS)
 215       writeOperationsBody ();
 216     if (intfType == SIGNATURE)
 217       writeSignatureBody ();
 218     writeClosing ();
 219     closeStream ();
 220   } // generateInterface
 221 
 222   /**
 223    *
 224    **/
 225   protected void openStream ()
 226   {
 227     if (i.isAbstract () || intfType == SIGNATURE)
 228        stream = Util.stream (i, ".java");
 229     else if (intfType == OPERATIONS)
 230        stream = Util.stream (i, "Operations.java");
 231   } // openStream
 232 
 233   /**
 234    *
 235    **/
 236   protected void writeHeading ()
 237   {
 238     Util.writePackage (stream, i, Util.TypeFile);
 239     Util.writeProlog (stream, ((GenFileStream)stream).name ());
 240 
 241     // Transfer interface comment to target <31jul1997>.
 242     if (i.comment () != null)
 243       i.comment ().generate ("", stream);
 244 
 245     String className = i.name ();
 246 //  if (((Arguments)Compile.compiler.arguments).TIEServer)
 247 //  {
 248 //    // For the delegate model, don't make interface a subclass of CORBA.Object
 249 //    stream.print ("public interface " + className);
 250 //    boolean firstTime = true;
 251 //    for (int ii = 0; ii < i.derivedFrom ().size (); ++ii)
 252 //    {
 253 //      SymtabEntry parent = (SymtabEntry)i.derivedFrom ().elementAt (ii);
 254 //      if (!parent.fullName ().equals ("org/omg/CORBA/Object"))
 255 //      {
 256 //        if (firstTime)
 257 //        {
 258 //          firstTime = false;
 259 //          stream.print (" extends ");
 260 //        }
 261 //        else
 262 //          stream.print (", ");
 263 //        stream.print (Util.javaName (parent));
 264 //      }
 265 //    }
 266 //    if (i.derivedFrom ().size () > 0)
 267 //      stream.print (", ");
 268 //    stream.print ("org.omg.CORBA.portable.IDLEntity ");
 269 //  }
 270 //
 271 //  else
 272 //  {
 273       if (intfType == SIGNATURE)
 274          writeSignatureHeading ();
 275       else if (intfType == OPERATIONS)
 276          writeOperationsHeading ();
 277 //  }
 278 
 279     stream.println ();
 280     stream.println ('{');
 281   } // writeHeading
 282 
 283   /**
 284    *
 285    **/
 286   protected void writeSignatureHeading ()
 287   {
 288     String className = i.name ();
 289     stream.print ("public interface " + className + " extends " + className + "Operations, ");
 290     boolean firstTime = true;
 291     boolean hasNonAbstractParent = false; // <d62310-klr>
 292     for (int k = 0; k < i.derivedFrom ().size (); ++k)
 293     {
 294       if (firstTime)
 295         firstTime = false;
 296       else
 297         stream.print (", ");
 298       InterfaceEntry parent = (InterfaceEntry)i.derivedFrom ().elementAt (k);
 299       stream.print (Util.javaName (parent));
 300       if (! parent.isAbstract ()) // <d62310-klr>
 301         hasNonAbstractParent = true; // <d62310-klr>
 302     }
 303     // <d62310-klr> - begin
 304     // If this interface extends only abstract interfaces,
 305     // it should extend both org.omg.CORBA.Object and IDLEntity.
 306     if (!hasNonAbstractParent) {
 307       stream.print (", org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity ");
 308     }
 309     else {
 310     // <d62310-klr> - end
 311         // extends IDLEntity if there's only one default parent - CORBA.Object
 312         if (i.derivedFrom ().size () == 1)
 313           stream.print (", org.omg.CORBA.portable.IDLEntity ");
 314     }
 315   } // writeSignatureHeading
 316 
 317   /**
 318    *
 319    **/
 320   protected void writeOperationsHeading ()
 321   {
 322     stream.print ("public interface " + i.name ());
 323     if ( !i.isAbstract ())
 324       stream.print ("Operations ");
 325     else {
 326         // <d60929> - base abstract interfaces extend AbstractBase
 327         // changed to IDLEntity by SCN per latest spec...
 328         if (i.derivedFrom ().size () == 0)
 329           stream.print (" extends org.omg.CORBA.portable.IDLEntity");
 330     }
 331 
 332     boolean firstTime = true;
 333     for (int k = 0; k < i.derivedFrom ().size (); ++k)
 334     {
 335       InterfaceEntry parent = (InterfaceEntry) i.derivedFrom ().elementAt (k);
 336       String parentName = Util.javaName (parent);
 337 
 338       // ignore the default parent - CORBA.Object
 339       if (parentName.equals ("org.omg.CORBA.Object"))
 340           continue;
 341 
 342       if (firstTime)
 343       {
 344         firstTime = false;
 345         stream.print (" extends ");
 346       }
 347       else
 348         stream.print (", ");
 349 
 350       // Don't append suffix Operations to the parents of abstract interface
 351       // or to the abstract parents of regular interface
 352       if (parent.isAbstract () || i.isAbstract ())
 353         stream.print (parentName);
 354       else
 355         stream.print (parentName + "Operations");
 356     }
 357   } // writeOperationsHeading
 358 
 359 
 360   /**
 361    *
 362    **/
 363   protected void writeOperationsBody ()
 364   {
 365     // Generate everything but constants
 366     Enumeration e = i.contained ().elements ();
 367     while (e.hasMoreElements ())
 368     {
 369       SymtabEntry contained = (SymtabEntry)e.nextElement ();
 370       if (contained instanceof MethodEntry)
 371       {
 372         MethodEntry element = (MethodEntry)contained;
 373         ((MethodGen)element.generator ()).interfaceMethod (symbolTable, element, stream);
 374       }
 375       else
 376         if ( !(contained instanceof ConstEntry))
 377           contained.generate (symbolTable, stream);
 378     }
 379   } // writeOperationsBody
 380 
 381   /**
 382    *
 383    **/
 384   protected void writeSignatureBody ()
 385   {
 386     // Generate only constants
 387     Enumeration e = i.contained ().elements ();
 388     while (e.hasMoreElements ())
 389     {
 390       SymtabEntry contained = (SymtabEntry)e.nextElement ();
 391       if (contained instanceof ConstEntry)
 392         contained.generate (symbolTable, stream);
 393     }
 394   } // writeSignatureBody
 395 
 396   /**
 397    *
 398    **/
 399   protected void writeClosing ()
 400   {
 401     String intfName = i.name ();
 402     if ( !i.isAbstract () && intfType == OPERATIONS)
 403       intfName = intfName + "Operations";
 404     stream.println ("} // interface " + intfName);
 405   } // writeClosing
 406 
 407   /**
 408    *
 409    **/
 410   protected void closeStream ()
 411   {
 412     stream.close ();
 413   } // closeStream
 414 
 415   ///////////////
 416   // From JavaGenerator
 417 
 418   // <f46082.51> Remove -stateful feature.
 419   /*
 420   public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 421   {
 422     InterfaceEntry i = (InterfaceEntry)entry;
 423     if (i.state () != null && i.state ().size () > 0)
 424       index = structHelperType (index, indent, tcoffsets, name, entry, stream);
 425     else
 426     {
 427       tcoffsets.set (entry);
 428       if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 429         stream.println (indent + name
 430             + " = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_objref);");
 431       else
 432         stream.println (indent + name
 433             // <54697>
 434             //+ " = org.omg.CORBA.ORB.init ().create_interface_tc (_id, "
 435             + " = org.omg.CORBA.ORB.init ().create_interface_tc (" + Util.helperName (i, true) + ".id (), " // <d61056>
 436             + '\"' + Util.stripLeadingUnderscores (entry.name ()) + "\");");
 437     }
 438     return index;
 439   } // helperType
 440   */
 441   public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 442   {
 443     InterfaceEntry i = (InterfaceEntry)entry;
 444     tcoffsets.set (entry);
 445     if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 446       stream.println (indent + name
 447           + " = org.omg.CORBA.ORB.init ().get_primitive_tc (org.omg.CORBA.TCKind.tk_objref);");
 448     else
 449       stream.println (indent + name
 450           // <54697>
 451           //+ " = org.omg.CORBA.ORB.init ().create_interface_tc (_id, "
 452           + " = org.omg.CORBA.ORB.init ().create_interface_tc (" + Util.helperName (i, true) + ".id (), " // <d61056>
 453           + '\"' + Util.stripLeadingUnderscores (entry.name ()) + "\");");
 454     return index;
 455   } // helperType
 456 
 457   public int type (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream) {
 458     stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();"); // <d61056>
 459     return index;
 460   } // type
 461 
 462   // <f46082.51> Remove -stateful feature.
 463   /*
 464   public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 465   {
 466     InterfaceEntry i = (InterfaceEntry)entry;
 467     if (i.state () != null)
 468       structHelperRead (entryName, i, stream);
 469     else
 470     {
 471       if (i.isAbstract ())
 472          stream.println ("    return narrow (((org.omg.CORBA_2_3.portable.InputStream)istream).read_abstract_interface (_" + i.name () + "Stub.class));"); // <d60929>
 473       else
 474          stream.println ("    return narrow (istream.read_Object (_" + i.name () + "Stub.class));");
 475     }
 476   } // helperRead
 477 
 478   */
 479   public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 480   {
 481     InterfaceEntry i = (InterfaceEntry)entry;
 482     if (i.isAbstract ())
 483       stream.println ("    return narrow (((org.omg.CORBA_2_3.portable.InputStream)istream).read_abstract_interface (_" + i.name () + "Stub.class));"); // <d60929>
 484     else
 485       stream.println ("    return narrow (istream.read_Object (_" + i.name () + "Stub.class));");
 486   } // helperRead
 487 
 488   // <f46082.51> Remove -stateful feature.
 489   /*
 490   public void helperWrite (SymtabEntry entry, PrintWriter stream)
 491   {
 492     InterfaceEntry i = (InterfaceEntry)entry;
 493     if (i.state () != null)
 494       structHelperWrite (entry, stream);
 495     else
 496       write (0, "    ", "value", entry, stream);
 497   } // helperWrite
 498   */
 499   public void helperWrite (SymtabEntry entry, PrintWriter stream)
 500   {
 501     write (0, "    ", "value", entry, stream);
 502   } // helperWrite
 503 
 504   // <f46082.51> Remove -stateful feature.
 505   /*
 506   public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 507   {
 508     InterfaceEntry i = (InterfaceEntry)entry;
 509     if (i.state () != null)
 510       index = structRead (index, indent, name, i, stream);
 511     else
 512     {
 513       if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 514         stream.println (indent + name + " = istream.read_Object (_" + i.name () + "Stub.class);");
 515       else
 516         stream.println (indent + name + " = " + Util.helperName (entry, false) + ".narrow (istream.read_Object (_" + i.name () + "Stub.class));"); // <d61056>
 517     }
 518     return index;
 519   } // read
 520   */
 521   public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 522   {
 523     InterfaceEntry i = (InterfaceEntry)entry;
 524     if (entry.fullName ().equals ("org/omg/CORBA/Object"))
 525       stream.println (indent + name + " = istream.read_Object (_" + i.name () + "Stub.class);");
 526     else
 527       stream.println (indent + name + " = " + Util.helperName (entry, false) + ".narrow (istream.read_Object (_" + i.name () + "Stub.class));"); // <d61056>
 528     return index;
 529   } // read
 530 
 531   // <f46082.51> Remove -stateful feature.
 532   /*
 533   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 534   {
 535     InterfaceEntry i = (InterfaceEntry)entry;
 536     if (i.state () != null)
 537       index = structWrite (index, indent, name, entry, stream);
 538     else
 539     {
 540       if (i.isAbstract ())
 541          stream.println (indent + "((org.omg.CORBA_2_3.portable.OutputStream)ostream).write_abstract_interface ((java.lang.Object) " + name + ");"); // <d60929>
 542       else
 543          stream.println (indent + "ostream.write_Object ((org.omg.CORBA.Object) " + name + ");");
 544     }
 545     return index;
 546   } // write
 547   */
 548   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 549   {
 550     InterfaceEntry i = (InterfaceEntry)entry;
 551     if (i.isAbstract ())
 552       stream.println (indent + "((org.omg.CORBA_2_3.portable.OutputStream)ostream).write_abstract_interface ((java.lang.Object) " + name + ");"); // <d60929>
 553     else
 554       stream.println (indent + "ostream.write_Object ((org.omg.CORBA.Object) " + name + ");");
 555     return index;
 556   } // write
 557 
 558   // <f46082.51> Remove -stateful feature.
 559   /*
 560   // These methods are cobbled from StructGen.  Stateful interfaces
 561   // are sent across the wire as if they were structs, with the first
 562   // element being a string - the Java name of the class.
 563 
 564   public int structHelperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 565   {
 566     TCOffsets innerOffsets = new TCOffsets ();
 567     innerOffsets.set (entry);
 568     int offsetForStruct = innerOffsets.currentOffset ();
 569     InterfaceEntry i = (InterfaceEntry)entry;
 570     String membersName = "_members" + index++;
 571     Vector state = i.state ();
 572     stream.println (indent + "org.omg.CORBA.StructMember[] " + membersName + " = new org.omg.CORBA.StructMember [" + (state.size () + 1) + "];");
 573     String tcOfMembers = "_tcOf" + membersName;
 574     stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + ';');
 575 
 576     // The name string is the first element of the struct
 577     String memberName = "_name";
 578     StringEntry stringEntry = Compile.compiler.factory.stringEntry ();
 579     index = ((JavaGenerator)stringEntry.generator ()).helperType (index, indent, innerOffsets, tcOfMembers, stringEntry, stream);
 580     stream.println (indent + membersName + "[0] = new org.omg.CORBA.StructMember (");
 581     stream.println (indent + "  \"" + memberName + "\",");
 582     stream.println (indent + "  " + tcOfMembers + ',');
 583     stream.println (indent + "  null);");
 584     int offsetSoFar = innerOffsets.currentOffset ();
 585     innerOffsets = new TCOffsets ();
 586     innerOffsets.set (entry);
 587     innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForStruct);
 588 
 589     for (int idx = 0; idx < state.size (); ++idx)
 590     {
 591       TypedefEntry member = ((InterfaceState)state.elementAt (idx)).entry;
 592       memberName = member.name ();
 593       index = ((JavaGenerator)member.generator ()).helperType (index, indent, innerOffsets, tcOfMembers, member, stream);
 594       stream.println (indent + membersName + '[' + (idx + 1) + "] = new org.omg.CORBA.StructMember (");
 595       stream.println (indent + "  \"" + memberName + "\",");
 596       stream.println (indent + "  " + tcOfMembers + ',');
 597       stream.println (indent + "  null);");
 598       offsetSoFar = innerOffsets.currentOffset ();
 599       innerOffsets = new TCOffsets ();
 600       innerOffsets.set (entry);
 601       innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForStruct);
 602     }
 603     tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
 604     stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_struct_tc (id (), \"" + entry.name () + "\", " + membersName + ");");
 605     return index;
 606   } // structHelperType
 607 
 608   public void structHelperRead (String entryName, InterfaceEntry entry, PrintWriter stream)
 609   {
 610     String impl = implName ((InterfaceEntry)entry);
 611     stream.println ("      " + Util.javaStatefulName (entry) + " value = null;");
 612     structRead (0, "      ", "value", entry, stream);
 613     stream.println ("      return value;");
 614   } // structHelperRead
 615 
 616   private String implName (InterfaceEntry entry)
 617   {
 618     String name;
 619     if (entry.container ().name ().equals (""))
 620       name =  '_' + entry.name () + "Impl";
 621     else
 622       name = Util.containerFullName (entry.container ()) + "._" + entry.name () + "Impl";
 623     return name.replace ('/', '.');
 624   } // implName
 625 
 626   public int structRead (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 627   {
 628     // The first element will be the name of the Java implementation class.
 629     String stringName = "_name" + index++;
 630     stream.println (indent + "String " + stringName + " = istream.read_string ();");
 631     stream.println (indent + "try");
 632     stream.println (indent + "{");
 633     stream.println (indent + "  " + name + " = (" + Util.javaStatefulName (entry) + ")com.sun.CORBA.iiop.ORB.getImpl (" + stringName + ".replace ('/', '.'));");
 634     stream.println (indent + "}");
 635     stream.println (indent + "catch (Exception e)");
 636     stream.println (indent + "{");
 637     stream.println (indent + "  " + name + " = null;");
 638     stream.println (indent + "}");
 639     stream.println (indent + "if (" + name + " == null)");
 640     stream.println (indent + "  throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 641     stream.println ();
 642 
 643     stream.println (indent + "if (!" + stringName + ".equals (\"" + entry.fullName () + "\"))");
 644     stream.println (indent + '{');
 645     stream.println (indent + "  Class _cls = " + name + ".getClass ();");
 646     stream.println (indent + "  boolean _found = false;");
 647     stream.println (indent + "  while (!_found && _cls != null)");
 648     stream.println (indent + "  {");
 649     stream.println (indent + "    Class[] interfaces = _cls.getInterfaces ();");
 650     stream.println (indent + "    for (int i = 0; i < interfaces.length; ++i)");
 651     stream.println (indent + "      if (interfaces[i].getName ().indexOf (\"State\") > 0)");
 652     stream.println (indent + "      {");
 653     stream.println (indent + "        _cls = interfaces[i];");
 654     stream.println (indent + "        _found = true;");
 655     stream.println (indent + "        break;");
 656     stream.println (indent + "      }");
 657     stream.println (indent + "    if (!_found)");
 658     stream.println (indent + "      _cls = _cls.getSuperclass ();");
 659     stream.println (indent + "  }");
 660     stream.println (indent + "  if (_cls == null)");
 661     stream.println (indent + "    throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 662     stream.println ();
 663     stream.println (indent + "  String _className = _cls.getName ();");
 664     stream.println (indent + "  int _index = _className.lastIndexOf ('.');");
 665     stream.println (indent + "  String _helperName = _className.substring (0, _index + 1) + _className.substring (_index + 2, _className.length () - 5) + \"Helper\"; // 5 == \"State\".length");
 666     stream.println (indent + "  try");
 667     stream.println (indent + "  {");
 668     stream.println (indent + "    Class _helperClass = Class.forName (_helperName);");
 669     stream.println (indent + "    Class[] _formalParms = new Class [1];");
 670     stream.println (indent + "    _formalParms[0] = Class.forName (\"org.omg.CORBA.portable.InputStream\");");
 671     stream.println (indent + "    java.lang.reflect.Method _read = _helperClass.getMethod (\"read\", _formalParms);");
 672     stream.println (indent + "    Object[] _actualParms = new Object [1];");
 673     stream.println (indent + "    _actualParms[0] = istream;");
 674     stream.println (indent + "      " + name + " = (" + Util.javaStatefulName (entry) + ")_read.invoke (null, _actualParms);");
 675     stream.println (indent + "  }");
 676     stream.println (indent + "  catch (Exception e)");
 677     stream.println (indent + "  {");
 678     stream.println (indent + "    throw new org.omg.CORBA.NO_IMPLEMENT (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 679     stream.println (indent + "  }");
 680     stream.println (indent + '}');
 681 
 682     // instantiate an implementation
 683     stream.println (indent + "else");
 684     stream.println (indent + '{');
 685 
 686     // Load the state
 687     readState (index, indent, name, (InterfaceEntry)entry, stream);
 688 
 689     stream.println (indent + '}');
 690     return index;
 691   } // structRead
 692 
 693   private void readState (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 694   {
 695     // First write the state from all parents
 696     Enumeration e = entry.derivedFrom ().elements ();
 697     while (e.hasMoreElements ())
 698     {
 699       InterfaceEntry parent = (InterfaceEntry)e.nextElement ();
 700       if (parent.state () != null)
 701       {
 702         if (parent.state ().size () > 0)
 703           readState (index, indent, name, parent, stream);
 704         break;
 705       }
 706     }
 707 
 708     // Now write the state for the local entry
 709     e = entry.state ().elements ();
 710     while (e.hasMoreElements ())
 711     {
 712       TypedefEntry member = ((InterfaceState)e.nextElement ()).entry;
 713       String tmpName = '_' + member.name () + "Tmp";
 714       Util.writeInitializer (indent + "  ", tmpName, "", member, stream);
 715       if (!member.arrayInfo ().isEmpty () || member.type () instanceof SequenceEntry || member.type () instanceof PrimitiveEntry || member.type () instanceof StringEntry)
 716         index = ((JavaGenerator)member.generator ()).read (index, indent + "  ", tmpName, member, stream);
 717       else
 718         stream.println (indent + "  " + tmpName + " = " + Util.helperName (member.type (), true) + ".read (istream);"); // <d61056>
 719       stream.println (indent + "  " + name + '.' + member.name () + " (" + tmpName + ");");
 720     }
 721   } // readState
 722 
 723   public void structHelperWrite (SymtabEntry entry, PrintWriter stream)
 724   {
 725     structWrite (0, "      ", "value", entry, stream);
 726   } // structHelperWrite
 727 
 728   public int structWrite (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 729   {
 730     // The first element of the struct must be the name of the real interface.
 731     stream.println (indent + "Class _cls = " + name + ".getClass ();");
 732     stream.println (indent + "boolean _found = false;");
 733     stream.println (indent + "while (!_found && _cls != null)");
 734     stream.println (indent + "{");
 735     stream.println (indent + "  Class[] interfaces = _cls.getInterfaces ();");
 736     stream.println (indent + "  for (int i = 0; i < interfaces.length; ++i)");
 737     stream.println (indent + "    if (interfaces[i].getName ().indexOf (\"State\") > 0)");
 738     stream.println (indent + "    {");
 739     stream.println (indent + "      _cls = interfaces[i];");
 740     stream.println (indent + "      _found = true;");
 741     stream.println (indent + "      break;");
 742     stream.println (indent + "    }");
 743     stream.println (indent + "  if (!_found)");
 744     stream.println (indent + "    _cls = _cls.getSuperclass ();");
 745     stream.println (indent + '}');
 746     stream.println ();
 747     stream.println (indent + "if (_cls == null)");
 748     stream.println (indent + "  throw new org.omg.CORBA.MARSHAL (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 749     stream.println ();
 750     stream.println (indent + "String _className = _cls.getName ();");
 751     stream.println (indent + "int _index = _className.lastIndexOf ('.');");
 752     stream.println (indent + "String _interfaceName = _className.substring (0, _index + 1) + _className.substring (_index + 2, _className.length () - 5); // 5 == \"State\".length");
 753     stream.println (indent + "ostream.write_string (_interfaceName.replace ('.', '/'));");
 754 
 755     // If _className != Util.javaName (entry), then call that class's helper class.
 756     stream.println ();
 757     stream.println (indent + "if (!_interfaceName.equals (\"" + Util.javaName (entry) + "\"))");
 758     stream.println (indent + '{');
 759     stream.println (indent + "  try");
 760     stream.println (indent + "  {");
 761     stream.println (indent + "    Class _helperClass = Class.forName (_interfaceName + \"Helper\");");
 762     stream.println (indent + "    Class[] _formalParms = new Class [2];");
 763     stream.println (indent + "    _formalParms[0] = Class.forName (\"org.omg.CORBA.portable.OutputStream\");");
 764     stream.println (indent + "    _formalParms[1] = _cls;");
 765     stream.println (indent + "    java.lang.reflect.Method _write = _helperClass.getMethod (\"write\", _formalParms);");
 766     stream.println (indent + "    Object[] _actualParms = new Object [2];");
 767     stream.println (indent + "    _actualParms[0] = ostream;");
 768     stream.println (indent + "    _actualParms[1] = " + name + ';');
 769     stream.println (indent + "    _write.invoke (null, _actualParms);");
 770     stream.println (indent + "  }");
 771     stream.println (indent + "  catch (Exception e)");
 772     stream.println (indent + "  {");
 773     stream.println (indent + "    throw new org.omg.CORBA.MARSHAL (0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);");
 774     stream.println (indent + "  }");
 775     stream.println (indent + '}');
 776 
 777     stream.println (indent + "else");
 778     stream.println (indent + '{');
 779 
 780     writeState (index, indent, name, (InterfaceEntry)entry, stream);
 781 
 782     stream.println (indent + '}');
 783     return index;
 784   } // structWrite
 785 
 786   private void writeState (int index, String indent, String name, InterfaceEntry entry, PrintWriter stream)
 787   {
 788     // First write the state from all parents
 789     Enumeration e = entry.derivedFrom ().elements ();
 790     while (e.hasMoreElements ())
 791     {
 792       InterfaceEntry parent = (InterfaceEntry)e.nextElement ();
 793       if (parent.state () != null)
 794       {
 795         if (parent.state ().size () > 0)
 796           writeState (index, indent, name, parent, stream);
 797         break;
 798       }
 799     }
 800 
 801     // Now write the state for the local entry
 802     Vector members = entry.state ();
 803     for (int i = 0; i < members.size (); ++i)
 804     {
 805       TypedefEntry member = ((InterfaceState)members.elementAt (i)).entry;
 806       if (!member.arrayInfo ().isEmpty () || member.type () instanceof SequenceEntry || member.type () instanceof PrimitiveEntry || member.type () instanceof StringEntry)
 807         index = ((JavaGenerator)member.generator ()).write (index, indent + "  ", name + '.' + member.name () + "()", member, stream);
 808       else
 809         stream.println (indent + "  " + Util.helperName (member.type (), true) + ".write (ostream, " + name + '.' + member.name () + " ());"); // <d61056>
 810     }
 811   } // writeState
 812   */
 813 
 814   /**
 815    * @return true if the entry is for a CORBA pseudo-object.
 816    **/
 817   private boolean isPseudo(InterfaceEntry i) {
 818     java.lang.String fullname = i.fullName();
 819     if (fullname.equalsIgnoreCase("CORBA/TypeCode"))
 820         return true;
 821     if (fullname.equalsIgnoreCase("CORBA/Principal"))
 822         return true;
 823     if (fullname.equalsIgnoreCase("CORBA/ORB"))
 824         return true;
 825     if (fullname.equalsIgnoreCase("CORBA/Any"))
 826         return true;
 827     if (fullname.equalsIgnoreCase("CORBA/Context"))
 828         return true;
 829     if (fullname.equalsIgnoreCase("CORBA/ContextList"))
 830         return true;
 831     if (fullname.equalsIgnoreCase("CORBA/DynamicImplementation"))
 832         return true;
 833     if (fullname.equalsIgnoreCase("CORBA/Environment"))
 834         return true;
 835     if (fullname.equalsIgnoreCase("CORBA/ExceptionList"))
 836         return true;
 837     if (fullname.equalsIgnoreCase("CORBA/NVList"))
 838         return true;
 839     if (fullname.equalsIgnoreCase("CORBA/NamedValue"))
 840         return true;
 841     if (fullname.equalsIgnoreCase("CORBA/Request"))
 842         return true;
 843     if (fullname.equalsIgnoreCase("CORBA/ServerRequest"))
 844         return true;
 845     if (fullname.equalsIgnoreCase("CORBA/UserException"))
 846         return true;
 847     return false;
 848   }
 849 
 850   // From JavaGenerator
 851   ///////////////
 852 
 853   protected int            emit        = 0;
 854   protected Factories      factories   = null;
 855 
 856   protected Hashtable      symbolTable = null;
 857   protected InterfaceEntry i           = null;
 858   protected PrintWriter    stream      = null;
 859 
 860   // <f46082.03, f46838.1/.2/.3> Modify access to protected.
 861   protected static final   int SIGNATURE  = 1;
 862   protected static final   int OPERATIONS = 2;
 863   protected                int intfType   = 0;
 864 } // class InterfaceGen