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 // -F46082.51<daz> Remove -stateful feature; javaStatefulName() obsolete.
  40 // -D57147   <klr> Make _Tie implement org.omg.CORBA.portable.InvokeHandler
  41 // -D58037   <klr> Make _Tie delegate to Operations interface
  42 // -D62739   <klr> no TIE for values that support abstract interfaces, etc.
  43 
  44 import java.io.File;
  45 import java.io.PrintWriter;
  46 
  47 import java.util.Enumeration;
  48 import java.util.Hashtable;
  49 import java.util.Vector;
  50 
  51 import com.sun.tools.corba.se.idl.AttributeEntry;
  52 import com.sun.tools.corba.se.idl.GenFileStream;
  53 
  54 import com.sun.tools.corba.se.idl.InterfaceEntry;
  55 import com.sun.tools.corba.se.idl.InterfaceState;
  56 import com.sun.tools.corba.se.idl.MethodEntry;
  57 import com.sun.tools.corba.se.idl.SymtabEntry;
  58 import com.sun.tools.corba.se.idl.TypedefEntry;
  59 import com.sun.tools.corba.se.idl.ValueEntry;
  60 
  61 /**
  62  *
  63  **/
  64 public class Skeleton implements AuxGen
  65 {
  66   private NameModifier skeletonNameModifier ;
  67   private NameModifier tieNameModifier ;
  68 
  69   public Skeleton ()
  70   {
  71   }
  72 
  73   public void generate (Hashtable symbolTable, SymtabEntry entry)
  74   {
  75     // <d62739-begin>
  76     // Per Simon, 5-12-99, don't generate TIE or Skeleton for
  77     //
  78     // 1) valuetypes supporting abstract interfaces
  79     // 2) valuetypes with no supports.
  80     // 3) abstract interfaces
  81     //
  82     if (entry instanceof ValueEntry)
  83     {
  84       ValueEntry v = (ValueEntry) entry;
  85       if ((v.supports ().size () == 0) ||
  86           ((InterfaceEntry) v.supports ().elementAt (0)).isAbstract ()) {
  87         return;
  88         }
  89     }
  90     if (((InterfaceEntry) entry).isAbstract ()) {
  91         return;
  92     }
  93     // <d62739-end>
  94 
  95     this.symbolTable = symbolTable;
  96 
  97     this.i           = (InterfaceEntry)entry;
  98     init ();
  99     openStream ();
 100     if (stream == null)
 101       return;
 102     writeHeading ();
 103     writeBody ();
 104     writeClosing ();
 105     closeStream ();
 106   } // generate
 107 
 108   /**
 109    * Initialize members unique to this generator.
 110    **/
 111   protected void init ()
 112   {
 113     tie = ((Arguments)Compile.compiler.arguments).TIEServer ;
 114     poa = ((Arguments)Compile.compiler.arguments).POAServer ;
 115 
 116     skeletonNameModifier =
 117         ((Arguments)Compile.compiler.arguments).skeletonNameModifier ;
 118     tieNameModifier =
 119         ((Arguments)Compile.compiler.arguments).tieNameModifier ;
 120 
 121     tieClassName = tieNameModifier.makeName( i.name() ) ;
 122     skeletonClassName = skeletonNameModifier.makeName( i.name() ) ;
 123 
 124     intfName = Util.javaName (i);
 125     // for valuetype, get the name of the interface the valuetype supports
 126     if (i instanceof ValueEntry)
 127     {
 128       ValueEntry v = (ValueEntry) i;
 129       InterfaceEntry intf = (InterfaceEntry) v.supports ().elementAt (0);
 130       intfName = Util.javaName (intf);
 131     }
 132   } // init
 133 
 134   protected void openStream ()
 135   {
 136     if (tie)
 137         stream = Util.stream( i, tieNameModifier, ".java" ) ;
 138     else
 139         stream = Util.stream( i, skeletonNameModifier, ".java" ) ;
 140   } // openStream
 141 
 142   protected void writeHeading ()
 143   {
 144     Util.writePackage (stream, i, Util.StubFile);
 145     Util.writeProlog (stream, ((GenFileStream)stream).name ());
 146     if (i.comment () != null)
 147       i.comment ().generate ("", stream);
 148     writeClassDeclaration ();
 149     stream.println ('{');
 150     stream.println ();
 151   } // writeHeading
 152 
 153   protected void writeClassDeclaration ()
 154   {
 155     if (tie){
 156         stream.println ("public class " + tieClassName +
 157             " extends " + skeletonClassName ) ;
 158     } else {
 159         if (poa) {
 160             stream.println ("public abstract class " + skeletonClassName +
 161                             " extends org.omg.PortableServer.Servant");
 162             stream.print   (" implements " + intfName + "Operations, ");
 163             stream.println ("org.omg.CORBA.portable.InvokeHandler");
 164         } else {
 165             stream.println ("public abstract class " + skeletonClassName +
 166                             " extends org.omg.CORBA.portable.ObjectImpl");
 167             stream.print   ("                implements " + intfName + ", ");
 168             stream.println ("org.omg.CORBA.portable.InvokeHandler");
 169         }
 170     }
 171   } // writeClassDeclaration
 172 
 173   /**
 174    *
 175    **/
 176   protected void writeBody ()
 177   {
 178     // <f46082.51> Remove -stateful feature.  ?????
 179     //if (i.state () != null)
 180     //  writeState ();
 181     writeCtors ();
 182     if (i instanceof ValueEntry)
 183     {
 184       // use the interface the valuetype supports to generate the
 185       // tie class instead of using the valuetype itself
 186       ValueEntry v = (ValueEntry) i;
 187       this.i = (InterfaceEntry) v.supports ().elementAt (0);
 188     }
 189     buildMethodList ();
 190     //DispatchMethod and MethodTable
 191     if (tie){ //Concrete class implementing the remote interface
 192         //The logic is here for future use
 193         if (poa) {
 194             writeMethods ();
 195             stream.println ("  private " + intfName + "Operations _impl;");
 196             stream.println ("  private org.omg.PortableServer.POA _poa;");
 197         } else {
 198             writeMethods ();
 199             stream.println ("  private " + intfName + "Operations _impl;");
 200         }
 201     } else { //Both POA and ImplBase are abstract InvokeHandler
 202         //The logic is here for future use
 203         if (poa) {
 204             writeMethodTable ();
 205             writeDispatchMethod ();
 206             writeCORBAOperations ();
 207         } else {
 208             writeMethodTable ();
 209             writeDispatchMethod ();
 210             writeCORBAOperations ();
 211         }
 212     }
 213     //legacy !!
 214     writeOperations ();
 215   } // writeBody
 216 
 217   /**
 218    * Close the skeleton class. The singleton ORB member is
 219    * necessary only for portable skeletons.
 220    **/
 221   protected void writeClosing ()
 222   {
 223     stream.println ();
 224     if (tie){
 225         stream.println ("} // class " + tieClassName);
 226     } else {
 227         stream.println ("} // class " + skeletonClassName);
 228     }
 229   } // writeClosing
 230 
 231   /**
 232    * Close the print stream, which flushes the stream to file.
 233    **/
 234   protected void closeStream ()
 235   {
 236     stream.close ();
 237   } // closeStream
 238 
 239   protected void writeCtors ()
 240   {
 241     stream.println ("  // Constructors");
 242     // Empty argument constructors
 243     if (!poa) {
 244         if (tie){
 245             stream.println ("  public " + tieClassName + " ()");
 246             stream.println ("  {");
 247             stream.println ("  }");
 248         } else {
 249             stream.println ("  public " + skeletonClassName + " ()");
 250             stream.println ("  {");
 251             stream.println ("  }");
 252         }
 253     }
 254     stream.println ();
 255     // Argumented constructors
 256     if (tie){
 257         if (poa) {
 258             //Write constructors
 259             writePOATieCtors();
 260             //Write state setters and getters
 261             writePOATieFieldAccessMethods();
 262         } else {
 263             stream.println ("  public " + tieClassName +
 264                             " (" + intfName + "Operations impl)");
 265             stream.println ("  {");
 266             // Does it derive from a interface having state, e.g., valuetype?
 267             if (((InterfaceEntry)i.derivedFrom ().firstElement ()).state () != null)
 268                 stream.println ("    super (impl);");
 269             else
 270                 stream.println ("    super ();");
 271             stream.println ("    _impl = impl;");
 272             stream.println ("  }");
 273             stream.println ();
 274         }
 275     } else { //Skeleton is not Tie so it has no constructors.
 276         if (poa) {
 277         } else {
 278         }
 279     }
 280 
 281   } // writeCtors
 282 
 283 
 284   private void writePOATieCtors(){
 285     //First constructor
 286     stream.println ("  public " + tieClassName + " ( " + intfName + "Operations delegate ) {");
 287     stream.println ("      this._impl = delegate;");
 288     stream.println ("  }");
 289     //Second constructor specifying default poa.
 290     stream.println ("  public " + tieClassName + " ( " + intfName +
 291                     "Operations delegate , org.omg.PortableServer.POA poa ) {");
 292     stream.println ("      this._impl = delegate;");
 293     stream.println ("      this._poa      = poa;");
 294     stream.println ("  }");
 295   }
 296 
 297   private void writePOATieFieldAccessMethods(){
 298     //Getting delegate
 299     stream.println ("  public " + intfName+ "Operations _delegate() {");
 300     stream.println ("      return this._impl;");
 301     stream.println ("  }");
 302     //Setting delegate
 303     stream.println ("  public void _delegate (" + intfName + "Operations delegate ) {");
 304     stream.println ("      this._impl = delegate;");
 305     stream.println ("  }");
 306     //Overriding default poa
 307     stream.println ("  public org.omg.PortableServer.POA _default_POA() {");
 308     stream.println ("      if(_poa != null) {");
 309     stream.println ("          return _poa;");
 310     stream.println ("      }");
 311     stream.println ("      else {");
 312     stream.println ("          return super._default_POA();");
 313     stream.println ("      }");
 314     stream.println ("  }");
 315   }
 316 
 317   /**
 318    * Build a list of all of the methods, keeping out duplicates.
 319    **/
 320   protected void buildMethodList ()
 321   {
 322     // Start from scratch
 323     methodList = new Vector ();
 324 
 325     buildMethodList (i);
 326   } // buildMethodList
 327 
 328   /**
 329    *
 330    **/
 331   private void buildMethodList (InterfaceEntry entry)
 332   {
 333     // Add the local methods
 334     Enumeration locals = entry.methods ().elements ();
 335     while (locals.hasMoreElements ())
 336       addMethod ((MethodEntry)locals.nextElement ());
 337 
 338     // Add the inherited methods
 339     Enumeration parents = entry.derivedFrom ().elements ();
 340     while (parents.hasMoreElements ())
 341     {
 342       InterfaceEntry parent = (InterfaceEntry)parents.nextElement ();
 343       if (!parent.name ().equals ("Object"))
 344         buildMethodList (parent);
 345     }
 346   } // buildMethodList
 347 
 348   /**
 349    *
 350    **/
 351   private void addMethod (MethodEntry method)
 352   {
 353     if (!methodList.contains (method))
 354       methodList.addElement (method);
 355   } // addMethod
 356 
 357   /**
 358    *
 359    **/
 360   protected void writeDispatchMethod ()
 361   {
 362     String indent = "                                ";
 363     stream.println ("  public org.omg.CORBA.portable.OutputStream _invoke (String $method,");
 364     stream.println (indent + "org.omg.CORBA.portable.InputStream in,");
 365     stream.println (indent + "org.omg.CORBA.portable.ResponseHandler $rh)");
 366     stream.println ("  {");
 367 
 368     // this is a special case code generation for cases servantLocator and
 369     // servantActivator, where OMG is taking too long to define them
 370     // as local objects
 371 
 372     boolean isLocalInterface = false;
 373     if (i instanceof InterfaceEntry) {
 374         isLocalInterface = i.isLocalServant();
 375     }
 376 
 377     if (!isLocalInterface) {
 378         // Per Simon 8/26/98, create and return reply stream for all methods - KLR
 379         stream.println ("    org.omg.CORBA.portable.OutputStream out = null;");
 380         stream.println ("    java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);");
 381         stream.println ("    if (__method == null)");
 382         stream.println ("      throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);");
 383         stream.println ();
 384         if (methodList.size () > 0)
 385         {
 386           stream.println ("    switch (__method.intValue ())");
 387           stream.println ("    {");
 388 
 389           // Write the method case statements
 390           int realI = 0;
 391           for (int i = 0; i < methodList.size (); ++i)
 392           {
 393             MethodEntry method = (MethodEntry)methodList.elementAt (i);
 394             ((MethodGen)method.generator ()).dispatchSkeleton (symbolTable, method, stream, realI);
 395             if (method instanceof AttributeEntry && !((AttributeEntry)method).readOnly ())
 396               realI += 2;
 397             else
 398               ++realI;
 399           }
 400 
 401           indent = "       ";
 402           stream.println (indent + "default:");
 403           stream.println (indent + "  throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);");
 404           stream.println ("    }");
 405           stream.println ();
 406         }
 407         stream.println ("    return out;");
 408     } else {
 409         stream.println("    throw new org.omg.CORBA.BAD_OPERATION();");
 410     }
 411     stream.println ("  } // _invoke");
 412     stream.println ();
 413   } // writeDispatchMethod
 414 
 415   /**
 416    *
 417    **/
 418   protected void writeMethodTable ()
 419   {
 420     // Write the methods hashtable
 421     stream.println ("  private static java.util.Hashtable _methods = new java.util.Hashtable ();");
 422     stream.println ("  static");
 423     stream.println ("  {");
 424 
 425     int count = -1;
 426     Enumeration e = methodList.elements ();
 427     while (e.hasMoreElements ())
 428     {
 429       MethodEntry method = (MethodEntry)e.nextElement ();
 430       if (method instanceof AttributeEntry)
 431       {
 432         stream.println ("    _methods.put (\"_get_" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
 433         if (!((AttributeEntry)method).readOnly ())
 434           stream.println ("    _methods.put (\"_set_" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
 435       }
 436       else
 437         stream.println ("    _methods.put (\"" + Util.stripLeadingUnderscores (method.name ()) + "\", new java.lang.Integer (" + (++count) + "));");
 438     }
 439     stream.println ("  }");
 440     stream.println ();
 441   } // writeMethodTable
 442 
 443   /**
 444    *
 445    **/
 446   protected void writeMethods ()
 447   {
 448       int realI = 0;
 449       for (int i = 0; i < methodList.size (); ++i)
 450           {
 451               MethodEntry method = (MethodEntry)methodList.elementAt (i);
 452               ((MethodGen)method.generator ()).skeleton
 453                   (symbolTable, method, stream, realI);
 454               if (method instanceof AttributeEntry &&
 455                   !((AttributeEntry)method).readOnly ())
 456                   realI += 2;
 457               else
 458                   ++realI;
 459               stream.println ();
 460           }
 461   } // writeMethods
 462 
 463   /**
 464    *
 465    **/
 466   private void writeIDs ()
 467   {
 468     Vector list = new Vector ();
 469     buildIDList (i, list);
 470     Enumeration e = list.elements ();
 471     boolean first = true;
 472     while (e.hasMoreElements ())
 473     {
 474       if (first)
 475         first = false;
 476       else
 477         stream.println (", ");
 478       stream.print ("    \"" + (String)e.nextElement () + '"');
 479     }
 480   } // writeIDs
 481 
 482   /**
 483    *
 484    **/
 485   private void buildIDList (InterfaceEntry entry, Vector list)
 486   {
 487     if (!entry.fullName ().equals ("org/omg/CORBA/Object"))
 488     {
 489       String id = Util.stripLeadingUnderscoresFromID (entry.repositoryID ().ID ());
 490       if (!list.contains (id))
 491         list.addElement (id);
 492       Enumeration e = entry.derivedFrom ().elements ();
 493       while (e.hasMoreElements ())
 494         buildIDList ((InterfaceEntry)e.nextElement (), list);
 495     }
 496   } // buildIDList
 497 
 498   /**
 499    *
 500    **/
 501   protected void writeCORBAOperations ()
 502   {
 503     stream.println ("  // Type-specific CORBA::Object operations");
 504 
 505     stream.println ("  private static String[] __ids = {");
 506     writeIDs ();
 507     stream.println ("};");
 508     stream.println ();
 509     if (poa)
 510         writePOACORBAOperations();
 511     else
 512         writeNonPOACORBAOperations();
 513 
 514   } // writeCORBAOperations
 515 
 516   protected void writePOACORBAOperations(){
 517       stream.println ("  public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)");
 518       //Right now, with our POA implementation, the same
 519       //implementation of _ids() type methods seem to work for both non-POA
 520       //as well as POA servers. We need to REVISIT since the equivalent
 521       //POA interface, i.e. _all_interfaces, has parameters which are not being
 522       //used in the _ids() implementation.
 523       stream.println ("  {");
 524       stream.println ("    return (String[])__ids.clone ();");
 525       stream.println ("  }");
 526       stream.println ();
 527       //_this()
 528       stream.println ("  public "+ i.name() +" _this() ");
 529       stream.println ("  {");
 530       stream.println ("    return "+ i.name() +"Helper.narrow(" );
 531       stream.println ("    super._this_object());");
 532       stream.println ("  }");
 533       stream.println ();
 534       //_this(org.omg.CORBA.ORB orb)
 535       stream.println ("  public "+ i.name() +" _this(org.omg.CORBA.ORB orb) ");
 536       stream.println ("  {");
 537       stream.println ("    return "+ i.name() +"Helper.narrow(" );
 538       stream.println ("    super._this_object(orb));");
 539       stream.println ("  }");
 540       stream.println ();
 541   }
 542   protected void writeNonPOACORBAOperations(){
 543       stream.println ("  public String[] _ids ()");
 544       stream.println ("  {");
 545       stream.println ("    return (String[])__ids.clone ();");
 546       stream.println ("  }");
 547       stream.println ();
 548   }
 549   /**
 550    *
 551    **/
 552   protected void writeOperations ()
 553   {
 554     // _get_ids removed at Simon's request 8/26/98 - KLR
 555   } // writeOperations
 556 
 557   protected Hashtable      symbolTable = null;
 558   protected InterfaceEntry i           = null;
 559   protected PrintWriter    stream      = null;
 560 
 561   // Unique to this generator
 562   protected String         tieClassName   = null;
 563   protected String         skeletonClassName   = null;
 564   protected boolean        tie         = false;
 565   protected boolean        poa         = false;
 566   protected Vector         methodList  = null;
 567   protected String         intfName    = "";
 568 } // class Skeleton