Skeleton.java revision 608:7e06bf1dcb09
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
36package 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
44import java.io.File;
45import java.io.PrintWriter;
46
47import java.util.Enumeration;
48import java.util.Hashtable;
49import java.util.Vector;
50
51import com.sun.tools.corba.se.idl.AttributeEntry;
52import com.sun.tools.corba.se.idl.GenFileStream;
53
54import com.sun.tools.corba.se.idl.InterfaceEntry;
55import com.sun.tools.corba.se.idl.InterfaceState;
56import com.sun.tools.corba.se.idl.MethodEntry;
57import com.sun.tools.corba.se.idl.SymtabEntry;
58import com.sun.tools.corba.se.idl.TypedefEntry;
59import com.sun.tools.corba.se.idl.ValueEntry;
60
61/**
62 *
63 **/
64public 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
569