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 // - Think about arrays (and sequences?) as members
  40 //   - A sequence must be converted to an array, but a memory of the
  41 //     max size must be retained.
  42 // - After demarshalling an IOR, think about how to deal with the exceptions.
  43 // - The demarshall method should be throwing a ClientException,
  44 //   but should it, really?
  45 // -D60929   <klr> Update for RTF2.4 changes
  46 // -D61056   <klr> Use Util.helperName
  47 // -D62023   <klr> Use corbaLevel in read/write generation
  48 // -D59437   <daz> Modify read() to enit qualified name of value box helper.
  49 
  50 import java.io.File;
  51 import java.io.PrintWriter;
  52 import java.util.Enumeration;
  53 import java.util.Hashtable;
  54 import java.util.Vector;
  55 
  56 import com.sun.tools.corba.se.idl.GenFileStream;
  57 import com.sun.tools.corba.se.idl.EnumEntry;
  58 import com.sun.tools.corba.se.idl.InterfaceEntry;
  59 import com.sun.tools.corba.se.idl.PrimitiveEntry;
  60 import com.sun.tools.corba.se.idl.SequenceEntry;
  61 import com.sun.tools.corba.se.idl.StringEntry;
  62 import com.sun.tools.corba.se.idl.StructEntry;
  63 import com.sun.tools.corba.se.idl.SymtabEntry;
  64 import com.sun.tools.corba.se.idl.TypedefEntry;
  65 import com.sun.tools.corba.se.idl.ValueEntry;
  66 import com.sun.tools.corba.se.idl.ValueBoxEntry;
  67 import com.sun.tools.corba.se.idl.InterfaceState;
  68 
  69 /**
  70  *
  71  **/
  72 public class StructGen implements com.sun.tools.corba.se.idl.StructGen, JavaGenerator
  73 {
  74   /**
  75    * Public zero-argument constructor.
  76    **/
  77   public StructGen ()
  78   {
  79   } // ctor
  80 
  81   /**
  82    * Constructor for ExceptionGen.
  83    **/
  84   protected StructGen (boolean exception)
  85   {
  86     thisIsReallyAnException = exception;
  87   } // ctor
  88 
  89   /**
  90    *
  91    **/
  92   public void generate (Hashtable symbolTable, StructEntry s, PrintWriter str)
  93   {
  94     this.symbolTable = symbolTable;
  95     this.s           = s;
  96     //init ();
  97 
  98     openStream ();
  99     if (stream == null)
 100       return;
 101     generateHelper ();
 102     generateHolder ();
 103     writeHeading ();
 104     writeBody ();
 105     writeClosing ();
 106     closeStream ();
 107     generateContainedTypes ();
 108   } // generate
 109 
 110   /**
 111    * Initialize members unique to this generator.
 112    **/
 113   protected void init ()
 114   {
 115   } // init
 116 
 117   /**
 118    *
 119    **/
 120   protected void openStream ()
 121   {
 122     stream = Util.stream (s, ".java");
 123   } // openStream
 124 
 125   /**
 126    *
 127    **/
 128   protected void generateHelper ()
 129   {
 130     ((Factories)Compile.compiler.factories ()).helper ().generate (symbolTable, s);
 131   } // generateHelper
 132 
 133   /**
 134    *
 135    **/
 136   protected void generateHolder ()
 137   {
 138     ((Factories)Compile.compiler.factories ()).holder ().generate (symbolTable, s);
 139   } // generateHolder
 140 
 141   /**
 142    *
 143    **/
 144   protected void writeHeading ()
 145   {
 146     Util.writePackage (stream, s);
 147     Util.writeProlog (stream, ((GenFileStream)stream).name ());
 148 
 149     if (s.comment () != null)
 150       s.comment ().generate ("", stream);
 151 
 152     stream.print ("public final class " + s.name ());
 153     if (thisIsReallyAnException)
 154       stream.print (" extends org.omg.CORBA.UserException");
 155     else
 156       stream.print(" implements org.omg.CORBA.portable.IDLEntity");
 157     stream.println ();
 158     stream.println ("{");
 159   } // writeHeading
 160 
 161   /**
 162    *
 163    **/
 164   protected void writeBody ()
 165   {
 166     writeMembers ();
 167     writeCtors ();
 168   } // writeBody
 169 
 170   /**
 171    *
 172    **/
 173   protected void writeClosing ()
 174   {
 175    stream.println ("} // class " + s.name ());
 176   } // writeClosing
 177 
 178   /**
 179    *
 180    **/
 181   protected void closeStream ()
 182   {
 183     stream.close ();
 184   } // closeStream
 185 
 186   /**
 187    *
 188    **/
 189   protected void generateContainedTypes ()
 190   {
 191     // Generate all of the contained types
 192     Enumeration e = s.contained ().elements ();
 193     while (e.hasMoreElements ())
 194     {
 195       SymtabEntry entry = (SymtabEntry)e.nextElement ();
 196 
 197       // Don't generate contained entries if they are sequences.
 198       // Sequences are unnamed and since they translate to arrays,
 199       // no classes are generated for them, not even holders in this
 200       // case since they cannot be accessed outside of this struct.
 201 
 202       if (!(entry instanceof SequenceEntry))
 203         entry.generate (symbolTable, stream);
 204     }
 205   } // generateContainedTypes
 206 
 207   /**
 208    *
 209    **/
 210   protected void writeMembers ()
 211   {
 212     // Write members and populate quality arrays
 213     int size = s.members ().size ();
 214     memberIsPrimitive = new boolean [size];
 215     memberIsInterface = new boolean [size];
 216     memberIsTypedef   = new boolean [size];
 217     for (int i = 0; i < s.members ().size (); ++i)
 218     {
 219       SymtabEntry member = (SymtabEntry)s.members ().elementAt (i);
 220       memberIsPrimitive[i] = member.type () instanceof PrimitiveEntry;
 221       memberIsInterface[i] = member.type () instanceof InterfaceEntry;
 222       memberIsTypedef[i]   = member.type () instanceof TypedefEntry;
 223       Util.fillInfo (member);
 224       // Transfer member comment to target <31jul1997>.
 225       if (member.comment () != null)
 226          member.comment ().generate ("  ", stream);
 227       Util.writeInitializer ("  public ", member.name (), "", member, stream);
 228     }
 229   } // writeMembers
 230 
 231   /**
 232    *
 233    **/
 234   protected void writeCtors ()
 235   {
 236     // Write default ctor
 237     stream.println ();
 238     stream.println ("  public " + s.name () + " ()");
 239     stream.println ("  {");
 240     // fixed mapping for exceptions
 241     if (thisIsReallyAnException)
 242         stream.println ("    super(" + s.name() + "Helper.id());");
 243     stream.println ("  } // ctor");
 244     writeInitializationCtor(true);
 245     if (thisIsReallyAnException) {
 246         // for exception according to mapping we should always
 247         // have a full constructor
 248         writeInitializationCtor(false);
 249     }
 250   }
 251 
 252   private void writeInitializationCtor(boolean init)
 253   {
 254     // Write initialization ctor
 255     if (!init || (s.members ().size () > 0))
 256     {
 257       stream.println ();
 258       stream.print ("  public " + s.name () + " (");
 259       boolean firstTime = true;
 260       if (!init) {
 261         stream.print ("String $reason");
 262         firstTime = false;
 263       }
 264 
 265       for (int i = 0; i < s.members ().size (); ++i)
 266       {
 267         SymtabEntry member = (SymtabEntry)s.members ().elementAt (i);
 268         if (firstTime)
 269           firstTime = false;
 270         else
 271           stream.print (", ");
 272         stream.print (Util.javaName (member) + " _" + member.name ());
 273       }
 274       stream.println (")");
 275       stream.println ("  {");
 276       // fixed mapping for exceptions
 277       if (thisIsReallyAnException) {
 278           if (init)
 279               stream.println ("    super(" + s.name() + "Helper.id());");
 280           else
 281               stream.println ("    super(" + s.name() + "Helper.id() + \"  \" + $reason);");
 282       }
 283       for (int i = 0; i < s.members ().size (); ++i)
 284       {
 285         SymtabEntry member = (SymtabEntry)s.members ().elementAt (i);
 286         stream.println ("    " + member.name () + " = _" + member.name () + ";");
 287       }
 288       stream.println ("  } // ctor");
 289     }
 290     stream.println ();
 291   } // writeInitializationCtor
 292 
 293   ///////////////
 294   // From JavaGenerator
 295 
 296   public int helperType (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream)
 297   {
 298     TCOffsets innerOffsets = new TCOffsets ();
 299     innerOffsets.set (entry);
 300     int offsetForStruct = innerOffsets.currentOffset ();
 301     StructEntry s = (StructEntry)entry;
 302     String membersName = "_members" + index++;
 303     stream.println (indent + "org.omg.CORBA.StructMember[] " + membersName + " = new org.omg.CORBA.StructMember [" + s.members ().size () + "];");
 304     String tcOfMembers = "_tcOf" + membersName;
 305     stream.println (indent + "org.omg.CORBA.TypeCode " + tcOfMembers + " = null;");
 306     for (int i = 0; i < s.members ().size (); ++i)
 307     {
 308       TypedefEntry member = (TypedefEntry)s.members ().elementAt (i);
 309       String memberName = member.name ();
 310       // Generate and assign member TypeCode to tcofMembers
 311       index = ((JavaGenerator)member.generator ()).type (index, indent, innerOffsets, tcOfMembers, member, stream);
 312       stream.println (indent + membersName + '[' + i + "] = new org.omg.CORBA.StructMember (");
 313       stream.println (indent + "  \"" + Util.stripLeadingUnderscores (memberName) + "\",");
 314       stream.println (indent + "  " + tcOfMembers + ',');
 315       stream.println (indent + "  null);");
 316       int offsetSoFar = innerOffsets.currentOffset ();
 317       innerOffsets = new TCOffsets ();
 318       innerOffsets.set (entry);
 319       innerOffsets.bumpCurrentOffset (offsetSoFar - offsetForStruct);
 320 
 321     }
 322     tcoffsets.bumpCurrentOffset (innerOffsets.currentOffset ());
 323     // <54697>
 324     //stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_struct_tc (id (), \"" + Util.stripLeadingUnderscores (entry.name ()) + "\", " + membersName + ");");
 325     stream.println (indent + name + " = org.omg.CORBA.ORB.init ().create_" + (thisIsReallyAnException ? "exception" : "struct") + "_tc (" + Util.helperName (s, true) + ".id (), \"" + Util.stripLeadingUnderscores (entry.name ()) + "\", " + membersName + ");"); // <d61056>
 326     return index;
 327   } // helperType
 328 
 329   public int type (int index, String indent, TCOffsets tcoffsets, String name, SymtabEntry entry, PrintWriter stream) {
 330     stream.println (indent + name + " = " + Util.helperName (entry, true) + ".type ();"); // <d61056>
 331     return index;
 332   } // type
 333 
 334   public void helperRead (String entryName, SymtabEntry entry, PrintWriter stream)
 335   {
 336     stream.println ("    " + entryName + " value = new " + entryName + " ();");
 337     read (0, "    ", "value", entry, stream);
 338     stream.println ("    return value;");
 339   } // helperRead
 340 
 341   public int read (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 342   {
 343     if (thisIsReallyAnException)
 344     {
 345       stream.println (indent + "// read and discard the repository ID");
 346       stream.println (indent + "istream.read_string ();");
 347     }
 348 
 349     Enumeration e = ((StructEntry)entry).members ().elements ();
 350     while (e.hasMoreElements ())
 351     {
 352       TypedefEntry member = (TypedefEntry)e.nextElement ();
 353       SymtabEntry  mType = member.type ();
 354 
 355       if (!member.arrayInfo ().isEmpty () || mType instanceof SequenceEntry ||
 356           mType instanceof PrimitiveEntry || mType instanceof StringEntry ||
 357           mType instanceof TypedefEntry)
 358         index = ((JavaGenerator)member.generator ()).read (index, indent, name + '.' + member.name (), member, stream);
 359       else if (mType instanceof ValueBoxEntry)
 360       {
 361         // call read_value instead of Helper.read for the value
 362         Vector st = ((ValueBoxEntry) mType).state ();
 363         TypedefEntry vbMember = ((InterfaceState) st.elementAt (0)).entry;
 364         SymtabEntry vbType = vbMember.type ();
 365 
 366         String jName = null;
 367         String jHelper = null;
 368 
 369         if (vbType instanceof SequenceEntry || vbType instanceof StringEntry ||
 370             !vbMember.arrayInfo ().isEmpty ())
 371         {
 372           jName = Util.javaName (vbType);      // name of mapped Java type
 373           // <d59437> REVISIT.  Typename info. now correct for value boxes, so
 374           // these two cases may be obsolete.  See UnionGen.read().
 375           //jHelper = Util.helperName (vbType, false);  // <d61056>
 376           jHelper = Util.helperName (mType, true);
 377               }
 378         else
 379         {
 380           jName = Util.javaName (mType);       // name of mapped Java class
 381           // <d59437>
 382           //jHelper = Util.helperName (mType, false);  // <d61056>
 383           jHelper = Util.helperName (mType, true);
 384         }
 385         // <d62023> Call xHelper.read() for valueboxes for RTF2.4
 386         if (Util.corbaLevel (2.4f, 99.0f))
 387           stream.println (indent + name + '.' + member.name () + " = (" + jName + ") " + jHelper + ".read (istream);");
 388         else
 389           stream.println (indent + name + '.' + member.name () + " = (" + jName + ") ((org.omg.CORBA_2_3.portable.InputStream)istream).read_value (" + jHelper + ".get_instance ());"); // <d60929> <d61056>
 390       }
 391       // <d62023-klr> for corbaLevel 2.4 and up, use Helper.read like
 392       // everything else
 393       else if ((mType instanceof ValueEntry) &&
 394           !Util.corbaLevel (2.4f, 99.0f)) // <d62023>
 395       {
 396         // call read_value instead of Helper.read for the value
 397         stream.println (indent + name + '.' + member.name () + " = (" + Util.javaName (mType) + ") ((org.omg.CORBA_2_3.portable.InputStream)istream).read_value (" + Util.helperName (mType, false) + ".get_instance ());"); // <d60929> // <d61056>
 398       }
 399       else
 400         stream.println (indent + name + '.' + member.name () + " = " + Util.helperName (member.type (), true) + ".read (istream);"); // <d61056>
 401     }
 402     return index;
 403   } // read
 404 
 405   public void helperWrite (SymtabEntry entry, PrintWriter stream)
 406   {
 407     write (0, "    ", "value", entry, stream);
 408   } // helperWrite
 409 
 410   public int write (int index, String indent, String name, SymtabEntry entry, PrintWriter stream)
 411   {
 412     if (thisIsReallyAnException)
 413     {
 414       stream.println (indent + "// write the repository ID");
 415       stream.println (indent + "ostream.write_string (id ());");
 416     }
 417 
 418     Vector members = ((StructEntry)entry).members ();
 419     for (int i = 0; i < members.size (); ++i)
 420     {
 421       TypedefEntry member = (TypedefEntry)members.elementAt (i);
 422       SymtabEntry  mType = member.type ();
 423 
 424       if (!member.arrayInfo ().isEmpty () || mType instanceof SequenceEntry ||
 425            mType instanceof TypedefEntry || mType instanceof PrimitiveEntry ||
 426            mType instanceof StringEntry)
 427         index = ((JavaGenerator)member.generator ()).write (index, "    ", name + '.' + member.name (), member, stream);
 428 
 429       // <d62023-klr> for corbaLevel 2.4 and up, use Helper.write like
 430       //                everything else
 431       else if ((mType instanceof ValueEntry || mType instanceof ValueBoxEntry)
 432                 && !Util.corbaLevel (2.4f, 99.0f)) { // <d62023>
 433         stream.println (indent + "((org.omg.CORBA_2_3.portable.OutputStream)ostream).write_value ((java.io.Serializable) " // <d60929>
 434                         + name + '.' + member.name () + ", "
 435                         + Util.helperName (member.type (), true) // <d61056>
 436                         + ".get_instance ());"); // <d61056>
 437       }
 438       else
 439         stream.println (indent + Util.helperName (member.type (), true) + ".write (ostream, " + name + '.' + member.name () + ");"); // <d61056>
 440     }
 441     return index;
 442   } // write
 443 
 444   // From JavaGenerator
 445   ///////////////
 446 
 447   protected Hashtable   symbolTable = null;
 448   protected StructEntry s           = null;
 449   protected PrintWriter stream      = null;
 450 
 451   protected boolean     thisIsReallyAnException = false;
 452   private   boolean[]   memberIsPrimitive;
 453   private   boolean[]   memberIsInterface;
 454   private   boolean[]   memberIsTypedef;
 455 } // class StructGen