1 /*
   2  * Copyright (c) 1998, 2007, 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  * Licensed Materials - Property of IBM
  27  * RMI-IIOP v1.0
  28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  29  *
  30  */
  31 
  32 package sun.rmi.rmic.iiop;
  33 
  34 import java.io.File;
  35 import java.io.IOException;
  36 import java.text.DateFormat;
  37 import java.util.Date;
  38 import java.util.Enumeration;
  39 import java.util.Hashtable;
  40 import java.util.Locale;
  41 import java.util.StringTokenizer;
  42 import java.util.Vector;
  43 import sun.tools.java.Identifier;
  44 import sun.tools.java.ClassDefinition;
  45 import sun.tools.java.CompilerError;
  46 import sun.rmi.rmic.IndentingWriter;
  47 import java.util.HashSet;
  48 import sun.rmi.rmic.Main;
  49 
  50 /**
  51  * An IDL generator for rmic.
  52  *
  53  * @author  Steve Newberry, Bryan Atsatt
  54  */
  55 public class IDLGenerator extends sun.rmi.rmic.iiop.Generator {
  56 
  57     private boolean valueMethods = true;
  58     private boolean factory = true;                              //init==!factory
  59     private Hashtable ifHash = new Hashtable();              //IDL file Hashtable
  60     private Hashtable imHash = new Hashtable();            //IDL module Hashtable
  61 
  62     private boolean isThrown = true;                      //flag for writeInclude
  63     private boolean isException = true;       //flag for writeBanner, writeIfndef
  64     private boolean isForward = true;                      //flag for writeIfndef
  65     private boolean forValuetype = true;                 //flag for writeInherits
  66 
  67     /**
  68      * Default constructor for Main to use.
  69      */
  70     public IDLGenerator() {
  71     }
  72 
  73 
  74     /**
  75      * Return true if a new instance should be created for each
  76      * class on the command line. Subclasses which return true
  77      * should override newInstance() to return an appropriately
  78      * constructed instance.
  79      */
  80     protected boolean requireNewInstance() {
  81         return false;
  82     }
  83 
  84     /**
  85      * Return true if non-conforming types should be parsed.
  86      * @param stack The context stack.
  87      */
  88     protected boolean parseNonConforming(ContextStack stack) {
  89         return valueMethods;
  90     }
  91 
  92     /**
  93      * Create and return a top-level type.
  94      * @param env The compiler environment.
  95      * @param cdef The top-level class definition.
  96      * @return An RemoteType or null if is non-conforming.
  97      */
  98     protected sun.rmi.rmic.iiop.CompoundType getTopType(ClassDefinition cdef,
  99                                                         ContextStack stack) {
 100         return CompoundType.forCompound(cdef,stack);
 101     }
 102 
 103 
 104     /**
 105      * Return an Identifier which contains the fully-qualified IDL filename
 106      * for the given OutputType.
 107      * The OutputType contains a filename string (not directory) and Type.
 108      * @param ot the OutputType for which directory nesting is to be defined.
 109      * @return the new identifier.
 110      */
 111     protected Identifier getOutputId (
 112                                       OutputType ot ) {
 113         Identifier id = super.getOutputId( ot );
 114 
 115         Type t = ot.getType();
 116         String fName = ot.getName();
 117 
 118         if ( id == idJavaLangClass )                 //java.lang.Class and array of
 119             if ( t.isArray() )
 120                 return Identifier.lookup(
 121                                          "org.omg.boxedRMI.javax.rmi.CORBA." + fName  );
 122             else return idClassDesc;
 123 
 124         if ( id == idJavaLangString &&                  //array of java.lang.String
 125              t.isArray() )
 126             return Identifier.lookup( "org.omg.boxedRMI.CORBA." + fName );
 127 
 128         if ( "org.omg.CORBA.Object".equals( t.getQualifiedName() ) &&
 129              t.isArray() )                          //array of org.omg.CORBA.Object
 130             return Identifier.lookup( "org.omg.boxedRMI." + fName );
 131 
 132         if ( t.isArray()) {                                                 //array
 133             ArrayType at = (ArrayType)t;
 134             Type et = at.getElementType();
 135             if ( et.isCompound() ) {
 136                 CompoundType ct = (CompoundType)et;
 137                 String qName = ct.getQualifiedName();
 138                 if ( ct.isIDLEntity() )
 139                     return Identifier.lookup( getQualifiedName( at ) );
 140             }
 141             return Identifier.lookup( idBoxedRMI,id );
 142         }
 143 
 144         if ( t.isCompound() ) {                                   //boxed IDLEntity
 145             CompoundType ct = (CompoundType)t;
 146             String qName = ct.getQualifiedName();
 147             if ( ct.isBoxed() )
 148                 return Identifier.lookup( getQualifiedName( ct ) );
 149         }
 150 
 151         return id;
 152     }
 153 
 154 
 155 
 156     /**
 157      * Return the file name extension for the given file name (e.g. ".java").
 158      * All files generated with the ".java" extension will be compiled. To
 159      * change this behavior for ".java" files, override the compileJavaSourceFile
 160      * method to return false.
 161      * @param outputType One of the items returned by getOutputTypesFor(...)
 162      */
 163     protected String getFileNameExtensionFor(OutputType outputType) {
 164         return IDL_FILE_EXTENSION;
 165     }
 166 
 167 
 168     /**
 169      * Examine and consume command line arguments.
 170      * @param argv The command line arguments. Ignore null
 171      * and unknown arguments. Set each consumed argument to null.
 172      * @param error Report any errors using the main.error() methods.
 173      * @return true if no errors, false otherwise.
 174      */
 175     public boolean parseArgs(String argv[], Main main) {
 176         boolean result = super.parseArgs(argv,main);
 177         String idlFrom;
 178         String idlTo;
 179         if (result) {
 180         nextArg:
 181             for (int i = 0; i < argv.length; i++) {
 182                 if (argv[i] != null) {
 183                     if (argv[i].equalsIgnoreCase("-idl")) {
 184                         idl = true;
 185                         argv[i] = null;
 186                     }
 187                     else if ( argv[i].equalsIgnoreCase( "-valueMethods" ) ) {
 188                         valueMethods = true;
 189                         argv[i] = null;
 190                     }
 191                     else if ( argv[i].equalsIgnoreCase( "-noValueMethods" ) ) {
 192                         valueMethods = false;
 193                         argv[i] = null;
 194                     }
 195                     else if ( argv[i].equalsIgnoreCase( "-init" ) ) {
 196                         factory = false;
 197                         argv[i] = null;
 198                 }
 199                     else if ( argv[i].equalsIgnoreCase( "-factory" ) ) {
 200                         factory = true;
 201                         argv[i] = null;
 202             }
 203                     else if ( argv[i].equalsIgnoreCase( "-idlfile" ) ) {
 204                         argv[i] = null;
 205                         if ( ++i < argv.length && argv[i] != null && !argv[i].startsWith("-") ) {
 206                             idlFrom = argv[i];
 207                             argv[i] = null;
 208                             if ( ++i < argv.length && argv[i] != null && !argv[i].startsWith("-") ) {
 209                                 idlTo = argv[i];
 210                                 argv[i] = null;
 211                                 ifHash.put( idlFrom,idlTo );
 212                                 continue nextArg;
 213         }
 214                         }
 215                         main.error("rmic.option.requires.argument", "-idlfile");
 216                         result = false;
 217                     }
 218                     else if ( argv[i].equalsIgnoreCase( "-idlmodule" ) ) {
 219                         argv[i] = null;
 220                         if ( ++i < argv.length && argv[i] != null && !argv[i].startsWith("-") ) {
 221                             idlFrom = argv[i];
 222                             argv[i] = null;
 223                             if ( ++i < argv.length && argv[i] != null && !argv[i].startsWith("-") ) {
 224                                 idlTo = argv[i];
 225                                 argv[i] = null;
 226                                 imHash.put( idlFrom,idlTo );
 227                                 continue nextArg;
 228                             }
 229                         }
 230                         main.error("rmic.option.requires.argument", "-idlmodule");
 231                         result = false;
 232                     }
 233 
 234 
 235                 }
 236             }
 237         }
 238         return result;
 239     }
 240 
 241 
 242 
 243     /**
 244      * Return an array of OutputTypes for the IDL files that need to be
 245      * generated for the given top-level type.
 246      * OutputTypes contain filename string (not directory) and Type.
 247      * @param topType The type returned by getTopType().
 248      * @param alreadyChecked A set of Types which have already been checked.
 249      * @return Array of OutputTypes to generate
 250      */
 251     protected OutputType[] getOutputTypesFor(
 252                                              CompoundType topType,
 253                                              HashSet alreadyChecked ) {
 254         Vector refVec = getAllReferencesFor( topType );
 255         Vector outVec = new Vector();
 256         for ( int i1 = 0; i1 < refVec.size(); i1++ ) {          //forall references
 257             Type t = (Type)refVec.elementAt( i1 );
 258             if ( t.isArray() ) {
 259                 ArrayType at = (ArrayType)t;
 260                 int dim = at.getArrayDimension();
 261                 Type et = at.getElementType();
 262                 String fName = unEsc( et.getIDLName() ).replace( ' ','_' );
 263                 for ( int i2 = 0; i2 < dim; i2++ ) {                //foreach dimension
 264                     String fileName = "seq" + ( i2 + 1 ) + "_" + fName;
 265                     outVec.addElement( new OutputType( fileName,at ) );
 266                 }
 267             }
 268             else if ( t.isCompound() ) {
 269                 String fName = unEsc( t.getIDLName() );
 270                 outVec.addElement( new OutputType( fName.replace( ' ','_' ),t ) );
 271             if ( t.isClass() ) {
 272                 ClassType ct = (ClassType)t;
 273                     if ( ct.isException() ) {                            //exception file
 274                         fName = unEsc( ct.getIDLExceptionName() );
 275                         outVec.addElement( new OutputType( fName.replace( ' ','_' ),t ) );
 276             }
 277         }
 278     }
 279     }
 280         OutputType[] outArr = new OutputType[outVec.size()];
 281         outVec.copyInto( outArr );
 282         return outArr;
 283     }
 284 
 285     /**
 286      * Get all referenced types of a given tyoe for which an IDL file needs
 287      * to be generated.
 288      * @param ct The given type.
 289      * @return Vector of Types for which IDL must be generated.
 290      */
 291     protected Vector getAllReferencesFor(
 292                                          CompoundType ct ) {
 293         Hashtable refHash = new Hashtable();
 294         Hashtable spcHash = new Hashtable();
 295         Hashtable arrHash = new Hashtable();
 296         int refSize;
 297         refHash.put( ct.getQualifiedName(),ct );               //put the given type
 298         accumulateReferences( refHash,spcHash,arrHash );
 299         do {
 300             refSize = refHash.size();
 301             accumulateReferences( refHash,spcHash,arrHash );
 302         }
 303         while ( refSize < refHash.size() );        //till hashtable stays same size
 304 
 305         Vector outVec = new Vector();
 306         Enumeration e = refHash.elements();                   //ordinary references
 307         while ( e.hasMoreElements() ) {
 308             CompoundType t = (CompoundType)e.nextElement();
 309             outVec.addElement( t );
 310         }
 311         e = spcHash.elements();                                //special references
 312         while ( e.hasMoreElements() ) {
 313             CompoundType t = (CompoundType)e.nextElement();
 314             outVec.addElement( t );
 315     }
 316         e = arrHash.elements();                                  //array references
 317                                          nextSequence:
 318         while ( e.hasMoreElements() ) {
 319             ArrayType at = (ArrayType)e.nextElement();
 320             int dim = at.getArrayDimension();
 321             Type et = at.getElementType();
 322             Enumeration e2 = arrHash.elements();
 323             while ( e2.hasMoreElements() ) {                   //eliminate duplicates
 324                 ArrayType at2 = (ArrayType)e2.nextElement();
 325                 if ( et == at2.getElementType() &&                //same element type &
 326                      dim < at2.getArrayDimension() )               //smaller dimension?
 327                     continue nextSequence;                              //ignore this one
 328             }
 329             outVec.addElement( at );
 330         }
 331         return outVec;
 332     }
 333 
 334 
 335     /**
 336      * Accumulate and filter all those types that are referenced by the given
 337      * referenced types.
 338      * Keep only those for which IDL is to be generated.
 339      * @param refHash Hashtable containing the given types
 340      * @param spcHash Hashtable containing referenced specials (IDL typedefs)
 341      * @param arrHash Hashtable containing referenced arrays (dimensioned)
 342      */
 343     protected void accumulateReferences(
 344                                         Hashtable refHash,
 345                                         Hashtable spcHash,
 346                                         Hashtable arrHash ) {
 347         Enumeration e = refHash.elements();
 348         while ( e.hasMoreElements() ) {
 349             CompoundType t = (CompoundType)e.nextElement();
 350             Vector datVec = getData( t );                     //collect and sort data
 351             Vector mthVec = getMethods( t );             //collect and filter methods
 352             getInterfaces( t,refHash );                          //collect interfaces
 353             getInheritance( t,refHash );                            //add inheritance
 354             getMethodReferences( mthVec,refHash,spcHash,arrHash,refHash );
 355             getMemberReferences( datVec,refHash,spcHash,arrHash );
 356         }
 357         e = arrHash.elements();                      //add array element references
 358         while ( e.hasMoreElements() ) {
 359             ArrayType at = (ArrayType)e.nextElement();
 360             Type et = at.getElementType();
 361             addReference( et,refHash,spcHash,arrHash );
 362         }
 363         e = refHash.elements();
 364         while ( e.hasMoreElements() ) {
 365             CompoundType t = (CompoundType)e.nextElement();
 366             if ( !isIDLGeneratedFor( t ) )              //remove if no IDL generation
 367                 refHash.remove( t.getQualifiedName() );
 368     }
 369     }
 370 
 371 
 372 
 373     /**
 374      * Determine if IDL should be generated for a referenced type.
 375      * Do not generate IDL for a CORBA Object reference. It gets mapped
 376      * to the original IDL or to Object (if exactly org.omg.CORBA.Object)
 377      * Generate (boxed) IDL for an IDL Entity unless it is an IDL user
 378      * exception, a ValueBase, an AbstractBase (or a CORBA Object).
 379      * Do not generate IDL for Implementation classes..unless they inherit
 380      * from multiple distinct remote interfaces
 381      * @param t The type to check.
 382      * @return true or false
 383      */
 384     protected boolean isIDLGeneratedFor(
 385                                  CompoundType t ) {
 386         if ( t.isCORBAObject() ) return false;
 387         if ( t.isIDLEntity() )
 388             if ( t.isBoxed() ) return true;
 389             else if ( "org.omg.CORBA.portable.IDLEntity"
 390                       .equals( t.getQualifiedName() ) ) return true;
 391             else if ( t.isCORBAUserException() ) return true;
 392             else return false;
 393         Hashtable inhHash = new Hashtable();
 394         getInterfaces( t,inhHash );
 395         if ( t.getTypeCode() == TYPE_IMPLEMENTATION )
 396             if ( inhHash.size() < 2 ) return false;         //no multiple inheritance
 397             else return true;
 398         return true;                                   //generate IDL for this type
 399     }
 400 
 401 
 402     /**
 403      * Write the output for the given OutputFileName into the output stream.
 404      * (The IDL mapping for java.lang.Class is generated from
 405      * javax.rmi.CORBA.ClassDesc in the tools workspace)
 406      * @param OutputType ot One of the items returned by getOutputTypesFor(...)
 407      * @param alreadyChecked A set of Types which have already been checked.
 408      *  Intended to be passed to Type.collectMatching(filter,alreadyChecked).
 409      * @param p The output stream.
 410      */
 411     protected void writeOutputFor(
 412                                   OutputType ot,
 413                                   HashSet alreadyChecked,
 414                                   IndentingWriter p )
 415         throws IOException {
 416         Type t = ot.getType();
 417         if ( t.isArray() ) {                                //specialcase: sequence
 418             writeSequence( ot,p );
 419             return;
 420         }
 421         if ( isSpecialReference( t ) ) {                //specialcase: IDL typecode
 422             writeSpecial( t,p );
 423             return;
 424         }
 425         if ( t.isCompound() ) {                            //specialcase: boxed IDL
 426             CompoundType ct = (CompoundType)t;
 427             if ( ct.isIDLEntity() && ct.isBoxed() ) {
 428                 writeBoxedIDL( ct,p );
 429                 return;
 430             }
 431         }
 432         if ( t.isClass() ) {                               //specialcase: exception
 433             ClassType ct = (ClassType)t;
 434             if ( ct.isException() ) {
 435                 String eName = unEsc( ct.getIDLExceptionName() );
 436                 String fName = ot.getName();
 437                 if ( fName.equals( eName.replace( ' ','_' ) ) ) {
 438                     writeException( ct,p );
 439                     return;
 440                 }
 441             }
 442         }
 443         switch ( t.getTypeCode() ) {                                 //general case
 444         case TYPE_IMPLEMENTATION:
 445             writeImplementation( (ImplementationType)t,p );
 446             break;
 447         case TYPE_NC_CLASS:
 448         case TYPE_NC_INTERFACE:
 449             writeNCType( (CompoundType)t,p );
 450             break;
 451         case TYPE_ABSTRACT:                        //AbstractType is a RemoteType
 452         case TYPE_REMOTE:
 453             writeRemote( (RemoteType)t,p );
 454             break;
 455         case TYPE_VALUE:
 456             writeValue( (ValueType)t,p );
 457             break;
 458         default:
 459             throw new CompilerError(
 460                                     "IDLGenerator got unexpected type code: "
 461                                     + t.getTypeCode());
 462         }
 463     }
 464 
 465 
 466     /**
 467      * Write an IDL interface definition for a Java implementation class
 468      * @param t The current ImplementationType
 469      * @param p The output stream.
 470      */
 471     protected void writeImplementation(
 472                                        ImplementationType t,
 473                                        IndentingWriter p )
 474         throws IOException {
 475         Hashtable inhHash = new Hashtable();
 476         Hashtable refHash = new Hashtable();
 477         getInterfaces( t,inhHash );                            //collect interfaces
 478 
 479         writeBanner( t,0,!isException,p );
 480         writeInheritedIncludes( inhHash,p );
 481         writeIfndef( t,0,!isException,!isForward,p );
 482         writeIncOrb( p );
 483         writeModule1( t,p );
 484         p.pln();p.pI();
 485         p.p( "interface " + t.getIDLName() );
 486         writeInherits( inhHash,!forValuetype,p );
 487 
 488         p.pln( " {" );
 489         p.pln( "};" );
 490 
 491         p.pO();p.pln();
 492         writeModule2( t,p );
 493         writeEpilog( t,refHash,p );
 494     }
 495 
 496 
 497     /**
 498      * Write an IDL valuetype definition for
 499      * 1) a nonconforming Java class
 500      * 2) a nonconforming Java interface (that is not an AbstractType)
 501      * @param t The current NC Type (NCClassType or NCInterfaceType)
 502      * @param p The output stream.
 503      */
 504     protected void writeNCType(
 505                                CompoundType t,
 506                                IndentingWriter p )
 507         throws IOException {
 508         Vector conVec = getConstants( t );                      //collect constants
 509         Vector mthVec = getMethods( t );                          //collect methods
 510         Hashtable inhHash = new Hashtable();
 511         Hashtable refHash = new Hashtable();
 512         Hashtable spcHash = new Hashtable();
 513         Hashtable arrHash = new Hashtable();
 514         Hashtable excHash = new Hashtable();
 515         getInterfaces( t,inhHash );                            //collect interfaces
 516         getInheritance( t,inhHash );                              //add inheritance
 517         getMethodReferences( mthVec,refHash,spcHash,arrHash,excHash );
 518 
 519         writeProlog( t,refHash,spcHash,arrHash,excHash,inhHash,p );
 520         writeModule1( t,p );
 521         p.pln();p.pI();
 522         p.p( "abstract valuetype " + t.getIDLName() );
 523         writeInherits( inhHash,!forValuetype,p );
 524 
 525         p.pln( " {" );
 526         if ( conVec.size() + mthVec.size() > 0 ) {                   //any content?
 527             p.pln();p.pI();
 528             for ( int i1 = 0; i1 < conVec.size(); i1++ )            //write constants
 529                 writeConstant( (CompoundType.Member)conVec.elementAt( i1 ),p );
 530             for ( int i1 = 0; i1 < mthVec.size(); i1++ )              //write methods
 531                 writeMethod( (CompoundType.Method)mthVec.elementAt( i1 ),p );
 532             p.pO();p.pln();
 533         }
 534         p.pln( "};" );
 535 
 536                 p.pO();p.pln();
 537         writeModule2( t,p );
 538         writeEpilog( t,refHash,p );
 539     }
 540 
 541 
 542     /**
 543      * Write an IDL interface definition for either:
 544      * 1) a conforming Java remote interface (RemoteType)..or
 545      * 2) a non-conforming Java interface whose methods all throw
 546      *     java.rmi.RemoteException (AbstractType)
 547      * @param t The current RemoteType
 548      * @param p The output stream.
 549      */
 550     protected void writeRemote(
 551                                RemoteType t,
 552                                IndentingWriter p )
 553         throws IOException {
 554         Vector conVec = getConstants( t );                      //collect constants
 555         Vector mthVec = getMethods( t );                          //collect methods
 556         Hashtable inhHash = new Hashtable();
 557         Hashtable refHash = new Hashtable();
 558         Hashtable spcHash = new Hashtable();
 559         Hashtable arrHash = new Hashtable();
 560         Hashtable excHash = new Hashtable();
 561         getInterfaces( t,inhHash );                            //collect interfaces
 562         getMethodReferences( mthVec,refHash,spcHash,arrHash,excHash );
 563 
 564         writeProlog( t,refHash,spcHash,arrHash,excHash,inhHash,p );
 565         writeModule1( t,p );
 566         p.pln();p.pI();
 567         if ( t.getTypeCode() == TYPE_ABSTRACT ) p.p( "abstract " );
 568         p.p( "interface " + t.getIDLName() );
 569         writeInherits( inhHash,!forValuetype,p );
 570 
 571         p.pln( " {" );
 572         if ( conVec.size() + mthVec.size() > 0 ) {      //any constants or methods?
 573             p.pln();p.pI();
 574             for ( int i1 = 0; i1 < conVec.size(); i1++ )                  //constants
 575                 writeConstant( (CompoundType.Member)conVec.elementAt( i1 ),p );
 576             for ( int i1 = 0; i1 < mthVec.size(); i1++ )        //methods, attributes
 577                 writeMethod( (CompoundType.Method)mthVec.elementAt( i1 ),p );
 578             p.pO();p.pln();
 579         }
 580         p.pln( "};" );
 581 
 582         p.pO();p.pln();
 583         writeRepositoryID ( t,p );
 584         p.pln();
 585         writeModule2( t,p );
 586         writeEpilog( t,refHash,p );
 587     }
 588 
 589 
 590     /**
 591      * Write an IDL valuetype definition for a conforming Java class.
 592      * Methods and constructors are optional..controlled by -valueMethods flag
 593      * @param t The current ValueType
 594      * @param p The output stream.
 595      */
 596     protected void writeValue(
 597                               ValueType t,
 598                               IndentingWriter p )
 599         throws IOException {
 600         Vector datVec = getData( t );                       //collect and sort data
 601         Vector conVec = getConstants( t );                      //collect constants
 602         Vector mthVec = getMethods( t );               //collect and filter methods
 603         Hashtable inhHash = new Hashtable();
 604         Hashtable refHash = new Hashtable();
 605         Hashtable spcHash = new Hashtable();
 606         Hashtable arrHash = new Hashtable();
 607         Hashtable excHash = new Hashtable();
 608         getInterfaces( t,inhHash );                            //collect interfaces
 609         getInheritance( t,inhHash );                              //add inheritance
 610         getMethodReferences( mthVec,refHash,spcHash,arrHash,excHash );
 611         getMemberReferences( datVec,refHash,spcHash,arrHash );
 612 
 613         writeProlog( t,refHash,spcHash,arrHash,excHash,inhHash,p );
 614         writeModule1( t,p );
 615         p.pln();p.pI();
 616         if ( t.isCustom() ) p.p( "custom " );
 617         p.p( "valuetype " + t.getIDLName() );
 618         writeInherits( inhHash,forValuetype,p );
 619 
 620         p.pln( " {" );
 621         if ( conVec.size() + datVec.size() + mthVec.size() > 0 ) {   //any content?
 622             p.pln();p.pI();
 623             for ( int i1 = 0; i1 < conVec.size(); i1++ )            //write constants
 624                 writeConstant( (CompoundType.Member)conVec.elementAt( i1 ),p );
 625             for ( int i1 = 0; i1 < datVec.size(); i1++ ) {
 626                 CompoundType.Member mem = (CompoundType.Member)datVec.elementAt( i1 );
 627                 if ( mem.getType().isPrimitive() )
 628                     writeData( mem,p );                            //write primitive data
 629             }
 630             for ( int i1 = 0; i1 < datVec.size(); i1++ ) {
 631                 CompoundType.Member mem = (CompoundType.Member)datVec.elementAt( i1 );
 632                 if ( !mem.getType().isPrimitive() )
 633                     writeData( mem,p );                        //write non-primitive data
 634             }
 635             for ( int i1 = 0; i1 < mthVec.size(); i1++ )              //write methods
 636                 writeMethod( (CompoundType.Method)mthVec.elementAt( i1 ),p );
 637             p.pO();p.pln();
 638         }
 639         p.pln( "};" );
 640 
 641         p.pO();p.pln();
 642         writeRepositoryID ( t,p );
 643             p.pln();
 644         writeModule2( t,p );
 645         writeEpilog( t,refHash,p );
 646         }
 647 
 648 
 649     /**
 650      * Write IDL prolog for a CompoundType.
 651      * @param t The CompoundType.
 652      * @param refHash Hashtable loaded with type references.
 653      * @param spcHash Hashtable loaded with special type references.
 654      * @param arrHash Hashtable loaded with array references.
 655      * @param excHash Hashtable loaded with exceptions thrown.
 656      * @param inhHash Hashtable loaded with inherited types.
 657      * @param p The output stream.
 658      */
 659     protected void writeProlog(
 660                                CompoundType t,
 661                                Hashtable refHash,
 662                                Hashtable spcHash,
 663                                Hashtable arrHash,
 664                                Hashtable excHash,
 665                                Hashtable inhHash,
 666                                IndentingWriter p )
 667         throws IOException {
 668         writeBanner( t,0,!isException,p );
 669         writeForwardReferences( refHash,p );
 670         writeIncludes( excHash,isThrown,p );      //#includes for exceptions thrown
 671         writeInheritedIncludes( inhHash,p );
 672         writeIncludes( spcHash,!isThrown,p );         //#includes for special types
 673         writeBoxedRMIIncludes( arrHash,p );
 674         writeIDLEntityIncludes( refHash,p );
 675         writeIncOrb( p );
 676         writeIfndef( t,0,!isException,!isForward,p );
 677     }
 678 
 679 
 680     /**
 681      * Write IDL epilog for a CompoundType.
 682      * @param t The CompoundType.
 683      * @param refHash Hashtable loaded with type references.
 684      * @param p The output stream.
 685      */
 686     protected void writeEpilog(
 687                                CompoundType t,
 688                                Hashtable refHash,
 689                                IndentingWriter p )
 690         throws IOException {
 691         writeIncludes( refHash,!isThrown,p );     //#includes for forward dcl types
 692         writeEndif( p );
 693     }
 694 
 695 
 696 
 697     /**
 698      * Write special typedef
 699      * @param t A special Type.
 700      * @param p The output stream.
 701      */
 702     protected void writeSpecial(
 703                                 Type t,
 704                                 IndentingWriter p )
 705         throws IOException {
 706         String spcName = t.getQualifiedName();
 707         if ( "java.io.Serializable".equals( spcName ) )
 708             writeJavaIoSerializable( t,p );
 709         else if ( "java.io.Externalizable".equals( spcName ) )
 710             writeJavaIoExternalizable( t,p );
 711         else if ( "java.lang.Object".equals( spcName) )
 712             writeJavaLangObject( t,p );
 713         else if ( "java.rmi.Remote".equals( spcName) )
 714             writeJavaRmiRemote( t,p );
 715         else if ( "org.omg.CORBA.portable.IDLEntity".equals( spcName) )
 716             writeIDLEntity( t,p );
 717     }
 718 
 719 
 720 
 721     /**
 722      * Write a hard-coded IDL typedef definition for the special case
 723      * java.io.Serializable.
 724      * @param t The current Type
 725      * @param p The output stream.
 726      */
 727     protected void writeJavaIoSerializable(
 728                                            Type t,
 729                                            IndentingWriter p )
 730         throws IOException {
 731         writeBanner( t,0,!isException,p );
 732         writeIfndef( t,0,!isException,!isForward,p );
 733         writeModule1( t,p );
 734         p.pln();p.pI();
 735         p.pln( "typedef any Serializable;" );
 736         p.pO();p.pln();
 737         writeModule2( t,p );
 738         writeEndif( p );
 739     }
 740 
 741 
 742     /**
 743      * Write a hard-coded IDL typedef definition for the special case
 744      * java.io.Externalizable.
 745      * @param t The current Type
 746      * @param p The output stream.
 747      */
 748     protected void writeJavaIoExternalizable(
 749                                              Type t,
 750                                              IndentingWriter p )
 751         throws IOException {
 752         writeBanner( t,0,!isException,p );
 753         writeIfndef( t,0,!isException,!isForward,p );
 754         writeModule1( t,p );
 755         p.pln();p.pI();
 756         p.pln( "typedef any Externalizable;" );
 757         p.pO();p.pln();
 758         writeModule2( t,p );
 759         writeEndif( p );
 760     }
 761 
 762 
 763     /**
 764      * Write a hard-coded IDL typedef definition for the special case
 765      * java.lang.Object.
 766      * @param t The current Type
 767      * @param p The output stream.
 768      */
 769     protected void writeJavaLangObject(
 770                                        Type t,
 771                                        IndentingWriter p )
 772         throws IOException {
 773         writeBanner( t,0,!isException,p );
 774         writeIfndef( t,0,!isException,!isForward,p );
 775         writeModule1( t,p );
 776         p.pln();p.pI();
 777         p.pln( "typedef any _Object;" );
 778         p.pO();p.pln();
 779         writeModule2( t,p );
 780         writeEndif( p );
 781     }
 782 
 783 
 784     /**
 785      * Write a hard-coded IDL typedef definition for the special case
 786      * java.rmi.Remote.
 787      * @param t The current Type
 788      * @param p The output stream.
 789      */
 790     protected void writeJavaRmiRemote(
 791                                       Type t,
 792                                       IndentingWriter p )
 793         throws IOException {
 794         writeBanner( t,0,!isException,p );
 795         writeIfndef( t,0,!isException,!isForward,p );
 796         writeModule1( t,p );
 797         p.pln();p.pI();
 798         p.pln( "typedef Object Remote;" );
 799         p.pO();p.pln();
 800         writeModule2( t,p );
 801         writeEndif( p );
 802     }
 803 
 804 
 805 
 806     /**
 807      * Write a hard-coded IDL typedef definition for the special case
 808      * org.omg.CORBA.portable.IDLEntity
 809      * @param t The current Type
 810      * @param p The output stream.
 811      */
 812     protected void writeIDLEntity(
 813                                   Type t,
 814                                   IndentingWriter p )
 815         throws IOException {
 816         writeBanner( t,0,!isException,p );
 817         writeIfndef( t,0,!isException,!isForward,p );
 818         writeModule1( t,p );
 819         p.pln();p.pI();
 820         p.pln( "typedef any IDLEntity;" );
 821         p.pO();p.pln();
 822         writeModule2( t,p );
 823         writeEndif( p );
 824     }
 825 
 826 
 827     /**
 828      * Filter and collect non-duplicate inherited interfaces for a type
 829      * @param ct The current CompoundType
 830      * @param inhHash Hashtable containing the inherited interfaces
 831      */
 832     protected void getInterfaces(
 833                                  CompoundType ct,
 834                                  Hashtable inhHash ) {
 835         InterfaceType[] infs = ct.getInterfaces();
 836                                  nextInterface:
 837         for ( int i1 = 0; i1 < infs.length; i1++ ) {  //forall inherited interfaces
 838             String inhName = infs[i1].getQualifiedName();
 839             switch ( ct.getTypeCode() ) {
 840             case TYPE_NC_CLASS:
 841             case TYPE_VALUE:                                   //filter for classes
 842                 if ( "java.io.Externalizable".equals( inhName ) ||
 843                      "java.io.Serializable".equals( inhName ) ||
 844                      "org.omg.CORBA.portable.IDLEntity".equals( inhName ) )
 845                     continue nextInterface;
 846                 break;
 847             default:                                        //filter for all others
 848                 if ( "java.rmi.Remote".equals( inhName ) )
 849                     continue nextInterface;
 850                 break;
 851             }
 852             inhHash.put( inhName,infs[i1] );                           //add this one
 853         }
 854     }
 855 
 856 
 857     /**
 858      * Filter and add base class inheritance for a class type
 859      * @param ct The current CompoundType
 860      * @param inhHash Hashtable containing inherited types
 861      */
 862     protected void getInheritance(
 863                                   CompoundType ct,
 864                                   Hashtable inhHash ) {
 865         ClassType par = ct.getSuperclass();                            //get parent
 866         if ( par == null ) return;
 867         String parName = par.getQualifiedName();
 868         switch ( ct.getTypeCode() ) {
 869         case TYPE_NC_CLASS:
 870         case TYPE_VALUE:
 871             if ( "java.lang.Object".equals( parName ) )          //this is implicit
 872                 return;
 873             break;
 874         default: return;                                     //ignore other types
 875         }
 876         inhHash.put( parName,par );                          //add valid base class
 877     }
 878 
 879 
 880     /**
 881      * Collect and filter type and array references from methods
 882      * @param mthVec Given Vector of methods
 883      * @param refHash Hashtable for type references
 884      * @param spcHash Hashtable for special type references
 885      * @param arrHash Hashtable for array references
 886      * @param excHash Hashtable for exceptions thrown
 887      */
 888     protected void getMethodReferences(
 889                                        Vector mthVec,
 890                                        Hashtable refHash,
 891                                        Hashtable spcHash,
 892                                        Hashtable arrHash,
 893                                        Hashtable excHash ) {
 894         for ( int i1 = 0; i1 < mthVec.size(); i1++ ) {             //forall methods
 895             CompoundType.Method mth = (CompoundType.Method)mthVec.elementAt( i1 );
 896             Type[] args = mth.getArguments();
 897             Type ret = mth.getReturnType();
 898             getExceptions( mth,excHash );                 //collect exceptions thrown
 899             for ( int i2 = 0; i2 < args.length; i2++ )             //forall arguments
 900                 addReference( args[i2],refHash,spcHash,arrHash );
 901             addReference( ret,refHash,spcHash,arrHash );
 902         }
 903     }
 904 
 905 
 906     /**
 907      * Collect and filter type and array references from data members
 908      * @param datVec Given Vector of data members
 909      * @param refHash Hashtable for type references
 910      * @param spcHash Hashtable for special type references
 911      * @param arrHash Hashtable for array references
 912      */
 913     protected void getMemberReferences(
 914                                        Vector datVec,
 915                                        Hashtable refHash,
 916                                        Hashtable spcHash,
 917                                        Hashtable arrHash ) {
 918         for ( int i1 = 0; i1 < datVec.size(); i1++ ) {         //forall datamembers
 919             CompoundType.Member mem = (CompoundType.Member)datVec.elementAt( i1 );
 920             Type dat = mem.getType();
 921             addReference( dat,refHash,spcHash,arrHash );
 922         }
 923     }
 924 
 925 
 926     /**
 927      * Add reference for given type avoiding duplication.
 928      * Sort into specials, arrays and regular references.
 929      * Filter out types which are not required.
 930      * @param t Given Type
 931      * @param refHash Hashtable for type references
 932      * @param spcHash Hashtable for special type references
 933      * @param arrHash Hashtable for array references
 934      */
 935     protected void addReference(
 936                                 Type ref,
 937                                 Hashtable refHash,
 938                                 Hashtable spcHash,
 939                                 Hashtable arrHash ) {
 940         String rName = ref.getQualifiedName();
 941         switch ( ref.getTypeCode() ) {
 942         case TYPE_ABSTRACT:
 943         case TYPE_REMOTE:
 944         case TYPE_NC_CLASS:
 945         case TYPE_NC_INTERFACE:
 946         case TYPE_VALUE:
 947             refHash.put( rName,ref );
 948             return;
 949         case TYPE_CORBA_OBJECT:
 950             if ( "org.omg.CORBA.Object".equals( rName ) ) return;      //don't want
 951             refHash.put( rName,ref );
 952             return;
 953         case TYPE_ARRAY:                                                 //array?
 954             arrHash.put( rName + ref.getArrayDimension(),ref );
 955             return;
 956         default:
 957             if ( isSpecialReference( ref ) )                 //special IDL typedef?
 958                 spcHash.put( rName,ref );
 959         }
 960     }
 961 
 962 
 963 
 964     /**
 965      * Determine whether given Type is a special reference.
 966      * Special cases are: java.io.Serializable, java.io.Externalizable,
 967      * java.lang.Object, java.rmi.Remote and org.omg.CORBA.portable.IDLEntity
 968      * They are special because they have a hard-coded typedef defined in the
 969      * spec.
 970      * @param ref A referenced Type
 971      * @return boolean indicating whether it's a special reference
 972      */
 973     protected boolean isSpecialReference(
 974                                          Type ref ) {
 975         String rName = ref.getQualifiedName();
 976         if ( "java.io.Serializable".equals( rName ) ) return true;
 977         if ( "java.io.Externalizable".equals( rName ) ) return true;
 978         if ( "java.lang.Object".equals( rName) ) return true;
 979         if ( "java.rmi.Remote".equals( rName) ) return true;
 980         if ( "org.omg.CORBA.portable.IDLEntity".equals( rName) ) return true;
 981         return false;
 982     }
 983 
 984 
 985     /**
 986      * Collect and filter thrown exceptions for a given pre-filtered method.
 987      * Keep only 'checked' exception classes minus java.rmi.RemoteException
 988      * and its subclasses
 989      * @param method The current method
 990      * @param excHash Hashtable containing non-duplicate thrown exceptions
 991      */
 992     protected void getExceptions(
 993                                       CompoundType.Method mth,
 994                                       Hashtable excHash ) {
 995         ClassType[] excs = mth.getExceptions();
 996         for ( int i1 = 0; i1 < excs.length; i1++ ) {            //forall exceptions
 997             ClassType exc = excs[i1];
 998             if ( exc.isCheckedException() &&
 999                  !exc.isRemoteExceptionOrSubclass() ) {
1000                 excHash.put( exc.getQualifiedName(),exc );
1001         }
1002     }
1003     }
1004 
1005 
1006     /**
1007      * Collect and filter methods for a type.
1008      * Remove any private or inherited methods.
1009      * @param ct The current CompoundType
1010      * @return Vector containing the methods
1011      */
1012     protected Vector getMethods(
1013                                 CompoundType ct ) {
1014         Vector vec = new Vector();
1015         int ctType = ct.getTypeCode();
1016         switch ( ctType ) {
1017         case TYPE_ABSTRACT:
1018         case TYPE_REMOTE:       break;
1019         case TYPE_NC_CLASS:
1020         case TYPE_NC_INTERFACE:
1021         case TYPE_VALUE:        if ( valueMethods ) break;
1022         default: return vec;
1023         }
1024         Identifier ctId = ct.getIdentifier();
1025         CompoundType.Method[] mths = ct.getMethods();
1026                                 nextMethod:
1027         for ( int i1 = 0; i1 < mths.length; i1++ ) {               //forall methods
1028             if ( mths[i1].isPrivate() ||                            //private method?
1029                  mths[i1].isInherited() )                         //inherited method?
1030                 continue nextMethod;                                   //yes..ignore it
1031             if ( ctType == TYPE_VALUE ) {
1032                 String mthName = mths[i1].getName();
1033                 if ( "readObject"  .equals( mthName ) ||
1034                      "writeObject" .equals( mthName ) ||
1035                      "readExternal".equals( mthName ) ||
1036                      "writeExternal".equals( mthName ) )
1037                     continue nextMethod;                                //ignore this one
1038             }
1039             if ( ( ctType == TYPE_NC_CLASS ||
1040                    ctType == TYPE_NC_INTERFACE ) &&
1041                  mths[i1].isConstructor() )   //init not valid for abstract valuetype
1042                 continue nextMethod;                                  //ignore this one
1043             vec.addElement( mths[i1] );                                //add this one
1044         }
1045         return vec;
1046     }
1047 
1048 
1049     /**
1050      * Collect constants for a type.
1051      * A valid constant is a "public final static" field with a compile-time
1052      * constant value for a primitive type or String
1053      * @param ct The current CompoundType
1054      * @return Vector containing the constants
1055      */
1056     protected Vector getConstants(
1057                                   CompoundType ct ) {
1058         Vector vec = new Vector();
1059         CompoundType.Member[] mems = ct.getMembers();
1060         for ( int i1 = 0; i1 < mems.length; i1++ ) {               //forall members
1061             Type   memType  = mems[i1].getType();
1062             String memValue = mems[i1].getValue();
1063             if ( mems[i1].isPublic() &&
1064                  mems[i1].isFinal()  &&
1065                  mems[i1].isStatic() &&
1066                  ( memType.isPrimitive() || "String".equals( memType.getName() ) ) &&
1067                  memValue != null )
1068                 vec.addElement( mems[i1] );                              //add this one
1069         }
1070         return vec;
1071     }
1072 
1073 
1074     /**
1075      * Collect and sort data fields for a ValueType.
1076      * Sort in Java (not IDL) Unicode name string lexicographic increasing
1077      * order.
1078      * Non-static, non-transient fields are mapped.
1079      * If the type is a custom valuetype, only public fields are mapped.
1080      * @param ct The current CompoundType
1081      * @return Vector containing the data fields
1082      */
1083     protected Vector getData(
1084                              CompoundType t ) {
1085         Vector vec = new Vector();
1086         if ( t.getTypeCode() != TYPE_VALUE ) return vec;
1087         ValueType vt = (ValueType)t;
1088         CompoundType.Member[] mems = vt.getMembers();
1089         boolean notCust = !vt.isCustom();
1090         for ( int i1 = 0; i1 < mems.length; i1++ ) {               //forall members
1091             if ( !mems[i1].isStatic()    &&
1092                  !mems[i1].isTransient() &&
1093                  (  mems[i1].isPublic() || notCust ) ) {
1094                 int i2;
1095                 String memName = mems[i1].getName();
1096                 for ( i2 = 0; i2 < vec.size(); i2++ ) {      //insert in java lex order
1097                     CompoundType.Member aMem = (CompoundType.Member)vec.elementAt( i2 );
1098                     if ( memName.compareTo( aMem.getName() ) < 0 ) break;
1099                 }
1100                 vec.insertElementAt( mems[i1],i2 );                   //insert this one
1101             }
1102         }
1103         return vec;
1104     }
1105 
1106 
1107     /**
1108      * Write forward references for referenced interfaces and valuetypes
1109      * ...but not if the reference is to a boxed IDLEntity,
1110      * @param refHash Hashtable loaded with referenced types
1111      * @param p The output stream.
1112      */
1113     protected void writeForwardReferences(
1114                                           Hashtable refHash,
1115                                           IndentingWriter p )
1116         throws IOException {
1117         Enumeration refEnum = refHash.elements();
1118         nextReference:
1119         while ( refEnum.hasMoreElements() ) {
1120             Type t = (Type)refEnum.nextElement();
1121             if ( t.isCompound() ) {
1122                 CompoundType ct = (CompoundType)t;
1123                 if ( ct.isIDLEntity() )
1124                     continue nextReference;                  //ignore IDLEntity reference
1125             }
1126             writeForwardReference( t,p );
1127         }
1128     }
1129 
1130 
1131     /**
1132      * Write forward reference for given type
1133      * @param t Given type
1134      * @param p The output stream.
1135      */
1136     protected void writeForwardReference(
1137                                          Type t,
1138                                          IndentingWriter p )
1139         throws IOException {
1140         String qName = t.getQualifiedName();
1141         if ( "java.lang.String".equals( qName ) ) ;
1142         else if ( "org.omg.CORBA.Object".equals( qName ) ) return ;    //no fwd dcl
1143 
1144         writeIfndef( t,0,!isException,isForward,p );
1145             writeModule1( t,p );
1146             p.pln();p.pI();
1147             switch ( t.getTypeCode() ) {
1148         case TYPE_NC_CLASS:
1149             case TYPE_NC_INTERFACE: p.p( "abstract valuetype " ); break;
1150             case TYPE_ABSTRACT:     p.p( "abstract interface " ); break;
1151             case TYPE_VALUE:        p.p( "valuetype " ); break;
1152         case TYPE_REMOTE:
1153         case TYPE_CORBA_OBJECT: p.p( "interface " ); break;
1154             default: ;                              //all other types were filtered
1155             }
1156             p.pln( t.getIDLName() + ";" );
1157             p.pO();p.pln();
1158             writeModule2( t,p );
1159         writeEndif( p );
1160         }
1161 
1162 
1163     /**
1164      * Write forward reference for boxed valuetype for single dimension of IDL
1165      * sequence.
1166      * If the dimension is <1 and the element is a CompoundType, write a
1167      * forward declare for the element
1168      * @param at ArrayType for forward declare
1169      * @param dim The dimension to write
1170      * @param p The output stream.
1171      */
1172     protected void writeForwardReference(
1173                                          ArrayType at,
1174                                          int dim,
1175                                          IndentingWriter p)
1176         throws IOException {
1177         Type et = at.getElementType();
1178         if ( dim < 1 ) {
1179             if ( et.isCompound() ) {
1180                 CompoundType ct = (CompoundType)et;
1181                 writeForwardReference( et,p);
1182     }
1183             return;
1184         }
1185         String fName = unEsc( et.getIDLName() ).replace( ' ','_' );
1186 
1187         writeIfndef( at,dim,!isException,isForward,p );
1188         writeModule1( at,p );
1189         p.pln();p.pI();
1190         switch ( et.getTypeCode() ) {
1191         case TYPE_NC_CLASS:
1192         case TYPE_NC_INTERFACE: p.p( "abstract valuetype " ); break;
1193         case TYPE_ABSTRACT:     p.p( "abstract interface " ); break;
1194         case TYPE_VALUE:        p.p( "valuetype " ); break;
1195         case TYPE_REMOTE:
1196         case TYPE_CORBA_OBJECT: p.p( "interface " ); break;
1197         default: ;                              //all other types were filtered
1198         }
1199         p.pln( "seq" + dim + "_" + fName + ";" );
1200         p.pO();p.pln();
1201         writeModule2( at,p );
1202         writeEndif( p );
1203     }
1204 
1205 
1206     /**
1207      * Write #includes for boxed IDLEntity references.
1208      * @param refHash Hashtable loaded with referenced types
1209      * @param p The output stream.
1210      */
1211     protected void writeIDLEntityIncludes(
1212                                           Hashtable refHash,
1213                                           IndentingWriter p )
1214         throws IOException {
1215         Enumeration refEnum = refHash.elements();
1216         while ( refEnum.hasMoreElements() ) {
1217             Type t = (Type)refEnum.nextElement();
1218             if ( t.isCompound() ) {
1219                 CompoundType ct = (CompoundType)t;
1220                 if ( ct.isIDLEntity() ) {                          //select IDLEntities
1221                     writeInclude( ct,0,!isThrown,p );
1222                     refHash.remove( ct.getQualifiedName() );     //avoid another #include
1223                 }
1224             }
1225         }
1226     }
1227 
1228 
1229     /**
1230      * Write #includes
1231      * @param incHash Hashtable loaded with Types to include
1232      * @param isThrown true if Types are thrown exceptions
1233      * @param p The output stream.
1234      */
1235     protected void writeIncludes(
1236                                  Hashtable incHash,
1237                                  boolean isThrown,
1238                                  IndentingWriter p )
1239         throws IOException {
1240         Enumeration incEnum = incHash.elements();
1241         while ( incEnum.hasMoreElements() ) {
1242             CompoundType t = (CompoundType)incEnum.nextElement();
1243             writeInclude( t,0,isThrown,p );
1244             }
1245     }
1246 
1247 
1248     /**
1249      * Write includes for boxedRMI valuetypes for IDL sequences.
1250      * Write only the maximum dimension found for an ArrayType.
1251      * @param arrHash Hashtable loaded with array types
1252      * @param p The output stream.
1253      */
1254     protected void writeBoxedRMIIncludes(
1255                                          Hashtable arrHash,
1256                                          IndentingWriter p)
1257         throws IOException {
1258         Enumeration e1 = arrHash.elements();
1259         nextSequence:
1260         while ( e1.hasMoreElements() ) {
1261             ArrayType at = (ArrayType)e1.nextElement();
1262             int dim = at.getArrayDimension();
1263             Type et = at.getElementType();
1264 
1265             Enumeration e2 = arrHash.elements();
1266             while ( e2.hasMoreElements() ) {                   //eliminate duplicates
1267                 ArrayType at2 = (ArrayType)e2.nextElement();
1268                 if ( et == at2.getElementType() &&                //same element type &
1269                      dim < at2.getArrayDimension() )               //smaller dimension?
1270                     continue nextSequence;                              //ignore this one
1271         }
1272             writeInclude( at,dim,!isThrown,p );
1273     }
1274     }
1275 
1276 
1277     /**
1278      * Write #includes
1279      * @param incHash Hashtable loaded with Types to include
1280      * @param p The output stream.
1281      */
1282     protected void writeInheritedIncludes(
1283                                           Hashtable inhHash,
1284                                  IndentingWriter p )
1285         throws IOException {
1286         Enumeration inhEnum = inhHash.elements();
1287         while ( inhEnum.hasMoreElements() ) {
1288             CompoundType t = (CompoundType)inhEnum.nextElement();
1289             writeInclude( t,0,!isThrown,p );
1290         }
1291     }
1292 
1293 
1294     /**
1295      * Write a #include.
1296      * @param t Type to include
1297      * @param dim The dimension to write if t is an array.
1298      * @param isThrown boolean indicating if include is for thrown exception.
1299      * @param p The output stream.
1300      */
1301     protected void writeInclude(
1302                                 Type t,
1303                                 int dim,
1304                                 boolean isThrown,
1305                                   IndentingWriter p)
1306         throws IOException {
1307         CompoundType ct;
1308         String tName;
1309         String[] modNames;
1310         if ( t.isCompound() ) {
1311             ct = (CompoundType)t;
1312             String qName = ct.getQualifiedName();
1313             if ( "java.lang.String".equals( qName ) ) {
1314                 writeIncOrb( p );                         //#include orb.idl for String
1315                 return;
1316             }
1317             if ( "org.omg.CORBA.Object".equals( qName ) )
1318                 return;                                 //Object treated like primitive
1319             modNames = getIDLModuleNames( ct );                   //module name array
1320             tName = unEsc( ct.getIDLName() );                     //file name default
1321 
1322             if ( ct.isException() )
1323                 if ( ct.isIDLEntityException() )
1324                     if ( ct.isCORBAUserException() )
1325                         if ( isThrown ) tName = unEsc( ct.getIDLExceptionName() );
1326                         else ;
1327                     else tName = ct.getName();                    //use original IDL name
1328                 else if ( isThrown )
1329                     tName = unEsc( ct.getIDLExceptionName() );
1330             }
1331         else if ( t.isArray() ) {
1332             Type et = t.getElementType();                    //file name for sequence
1333             if ( dim > 0 ) {
1334                 modNames = getIDLModuleNames( t );                  //module name array
1335                 tName = "seq" + dim + "_" + unEsc( et.getIDLName().replace( ' ','_' ) );
1336             }
1337             else{                                                  //#include element
1338                 if ( !et.isCompound() ) return;       //no include needed for primitive
1339                 ct = (CompoundType) et;
1340                 modNames = getIDLModuleNames( ct );           //no boxedRMI for element
1341                 tName = unEsc( ct.getIDLName() );
1342                 writeInclude( ct,modNames,tName,p );
1343                 return;
1344             }
1345         }
1346         else return;                              //no include needed for primitive
1347         writeInclude( t,modNames,tName,p );
1348     }
1349 
1350 
1351     /**
1352      * Write a #include doing user specified -idlFile translation (if any) for
1353      * IDLEntities.
1354      * @param t Type to include.
1355      * @param modNames Preprocessed module names (default).
1356      * @param tName Preprocessed Type name (default).
1357      * @param p The output stream.
1358      */
1359     protected void writeInclude(
1360                                 Type t,
1361                                 String[] modNames,
1362                                 String tName,
1363                                 IndentingWriter p)
1364         throws IOException {
1365         if ( t.isCompound() ) {
1366             CompoundType it = (CompoundType)t;
1367 
1368             if ( ifHash.size() > 0 &&             //any -idlFile translation to apply
1369                  it.isIDLEntity() ) {                         //..for this IDLEntity?
1370                 String qName = t.getQualifiedName();   //fully qualified orig Java name
1371 
1372                 Enumeration k = ifHash.keys();
1373                 while ( k.hasMoreElements() ) {      //loop thro user-defined -idlFiles
1374                     String from = (String)k.nextElement();
1375                     if ( qName.startsWith( from ) ) {                    //found a match?
1376                         String to = (String)ifHash.get( from );
1377                         p.pln( "#include \"" + to + "\"" );   //user-specified idl filename
1378                         return;                                   //don't look for any more
1379                     }
1380                 }
1381             }
1382         }
1383         else if ( t.isArray() ) ;        //no -idlFile translation needed for array
1384         else return;                             //no #include needed for primitive
1385 
1386         p.p( "#include \"" );                    //no -idlFile translation required
1387         for ( int i1 = 0; i1 < modNames.length; i1++ ) p.p( modNames[i1] + "/" );
1388         p.p( tName + ".idl\"" );
1389         p.pln();
1390     }
1391 
1392 
1393     /**
1394      * Return the fully qualified Java Name for a Type.
1395      * IDLEntity preprocessing done by getIDLModuleNames(t)
1396      * @param t Given Type
1397      * @return Array containing the original module nesting.
1398      */
1399     protected String getQualifiedName(
1400                                       Type t ) {
1401         String[] modNames = getIDLModuleNames( t );
1402         int len = modNames.length;
1403         StringBuffer buf = new StringBuffer();
1404         for ( int i1 = 0; i1 < len; i1++ )
1405             buf.append( modNames[i1] + "." );
1406         buf.append( t.getIDLName() );
1407         return buf.toString();
1408     }
1409 
1410 
1411     /**
1412      * Return the global fully qualified IDL Name for a Type.
1413      * IDLEntity preprocessing done by getIDLModuleNames(t)
1414      * @param t Given Type
1415      * @return Array containing the original module nesting.
1416      */
1417     protected String getQualifiedIDLName(Type t) {
1418         if ( t.isPrimitive() )
1419             return t.getIDLName();
1420         if ( !t.isArray() &&
1421              "org.omg.CORBA.Object".equals( t.getQualifiedName() ) )
1422             return t.getIDLName();
1423 
1424         String[] modNames = getIDLModuleNames( t );
1425         int len = modNames.length;
1426         if (len > 0) {
1427             StringBuffer buf = new StringBuffer();
1428             for ( int i1 = 0; i1 < len; i1++ )
1429                 buf.append( IDL_NAME_SEPARATOR + modNames[i1] );
1430             buf.append( IDL_NAME_SEPARATOR + t.getIDLName() );
1431             return buf.toString();
1432         } else {
1433             return t.getIDLName();
1434         }
1435     }
1436 
1437 
1438     /**
1439      * Return the IDL module nesting of the given Type.
1440      * For IDLEntity CompoundTypes (or their arrays) apply any user specified
1441      * -idlModule translation or, if none applicable, strip any package
1442      * prefix.
1443      * Add boxedIDL or boxedRMI modules if required.
1444      * @param t Given Type
1445      * @return Array containing the original module nesting.
1446      */
1447     protected String[] getIDLModuleNames(Type t) {
1448         String[] modNames = t.getIDLModuleNames();      //default module name array
1449         CompoundType ct;
1450         if ( t.isCompound() ) {
1451             ct = (CompoundType)t;
1452             if ( !ct.isIDLEntity ) return modNames;     //normal (non-IDLEntity) case
1453             if ( "org.omg.CORBA.portable.IDLEntity"
1454                  .equals( t.getQualifiedName() ) )
1455                 return modNames;
1456         }
1457         else if ( t.isArray() ) {
1458             Type et = t.getElementType();
1459             if ( et.isCompound() ) {
1460                 ct = (CompoundType)et;
1461                 if ( !ct.isIDLEntity ) return modNames;   //normal (non-IDLEntity) case
1462                 if ( "org.omg.CORBA.portable.IDLEntity"
1463                      .equals( t.getQualifiedName() ) )
1464                     return modNames;
1465             }
1466             else return modNames;
1467         }
1468         else return modNames;              //no preprocessing needed for primitives
1469 
1470         //it's an IDLEntity or an array of...
1471         Vector mVec = new Vector();
1472         if ( !translateJavaPackage( ct,mVec ) )      //apply -idlModule translation
1473             stripJavaPackage( ct,mVec );             //..or strip prefixes (not both)
1474 
1475         if ( ct.isBoxed() ) {                            //add boxedIDL if required
1476             mVec.insertElementAt( "org",0 );
1477             mVec.insertElementAt( "omg",1 );
1478             mVec.insertElementAt( "boxedIDL",2 );
1479         }
1480         if ( t.isArray() ) {                             //add boxedRMI if required
1481             mVec.insertElementAt( "org",0 );
1482             mVec.insertElementAt( "omg",1 );
1483             mVec.insertElementAt( "boxedRMI",2 );
1484         }
1485         String[] outArr = new String[mVec.size()];
1486         mVec.copyInto( outArr );
1487         return outArr;
1488     }
1489 
1490 
1491     /**
1492      * Apply user specified -idlModule translation to package names of given
1493      * IDLEntity ct. Example:
1494      *   -idlModule foo.bar real::mod::nesting
1495      * @param ct CompoundType containing given IDLEntity.
1496      * @param vec Returned Vector of translated IDL module names.
1497      * @return boolean true if any translation was done.
1498      */
1499     protected boolean translateJavaPackage(
1500                                            CompoundType ct,
1501                                            Vector vec ) {
1502         vec.removeAllElements();
1503         boolean ret = false;
1504         String fc = null;
1505         if ( ! ct.isIDLEntity() ) return ret;
1506 
1507         String pName = ct.getPackageName();         //start from Java package names
1508         if ( pName == null ) return ret;
1509         StringTokenizer pt = new StringTokenizer( pName,"." );
1510         while ( pt.hasMoreTokens() ) vec.addElement( pt.nextToken() );
1511 
1512         if ( imHash.size() > 0 ) {           //any -idlModule translation to apply?
1513             Enumeration k = imHash.keys();
1514 
1515         nextModule:
1516             while ( k.hasMoreElements() ) {      //loop thro user-defined -idlModules
1517                 String from = (String)k.nextElement();                  //from String..
1518                 StringTokenizer ft = new StringTokenizer( from,"." );
1519                 int vecLen = vec.size();
1520                 int ifr;
1521                 for ( ifr = 0; ifr < vecLen && ft.hasMoreTokens(); ifr++ )
1522                     if ( ! vec.elementAt(ifr).equals( ft.nextToken() ) )
1523                         continue nextModule;                                  //..no match
1524 
1525                 if ( ft.hasMoreTokens() ) {                          //matched so far..
1526                     fc = ft.nextToken();                         //a 'from' token remains
1527                     if ( ! ct.getName().equals( fc ) ||             //matches class name?
1528                          ft.hasMoreTokens() )
1529                         continue nextModule;                                   //..no match
1530                 }
1531 
1532                 ret = true;                                             //found a match
1533                 for ( int i4 = 0; i4 < ifr; i4++ )
1534                     vec.removeElementAt( 0 );                     //remove 'from' package
1535 
1536                 String to = (String)imHash.get( from );                   //..to String
1537                 StringTokenizer tt = new StringTokenizer( to,IDL_NAME_SEPARATOR );
1538 
1539                 int itoco = tt.countTokens();
1540                 int ito = 0;
1541                 if ( fc != null ) itoco--;               //user may have given IDL type
1542                 for ( ito = 0; ito < itoco; ito++ )
1543                     vec.insertElementAt( tt.nextToken(),ito );      //insert 'to' modules
1544                 if ( fc != null ) {
1545                     String tc = tt.nextToken();
1546                     if ( ! ct.getName().equals( tc ) )           //not the IDL type, so..
1547                         vec.insertElementAt( tc,ito );           //insert final 'to' module
1548                 }
1549             }
1550         }
1551         return ret;
1552     }
1553 
1554 
1555     /**
1556      * Strip Java #pragma prefix and/or -pkgPrefix prefix package names from
1557      * given IDLEntity ct.
1558      * Strip any package prefix which may have been added by comparing with
1559      * repository id. For example in Java package fake.omega:
1560      *   repid = IDL:phoney.pfix/omega/Juliet:1.0 gives { "omega" }
1561      * @param ct CompoundType containing given IDLEntity.
1562      * @param vec Returned Vector of stripped IDL module names.
1563      */
1564     protected void stripJavaPackage(
1565                                     CompoundType ct,
1566                                     Vector vec ) {
1567         vec.removeAllElements();
1568         if ( ! ct.isIDLEntity() ) return;
1569 
1570         String repID = ct.getRepositoryID().substring( 4 );
1571         StringTokenizer rept = new StringTokenizer( repID,"/" );
1572         if ( rept.countTokens() < 2 ) return;
1573 
1574         while ( rept.hasMoreTokens() )
1575             vec.addElement( rept.nextToken() );
1576         vec.removeElementAt( vec.size() - 1 );
1577 
1578         String pName = ct.getPackageName();         //start from Java package names
1579         if ( pName == null ) return;
1580         Vector pVec = new Vector();
1581         StringTokenizer pt = new StringTokenizer( pName,"." );
1582         while ( pt.hasMoreTokens() ) pVec.addElement( pt.nextToken() );
1583 
1584         int i1 = vec.size() - 1;
1585         int i2 = pVec.size() - 1;
1586         while ( i1 >= 0 && i2 >= 0 ) {                      //go R->L till mismatch
1587             String rep = (String)( vec.elementAt( i1 ) );
1588             String pkg = (String)( pVec.elementAt( i2 ) );
1589             if ( ! pkg.equals( rep ) ) break;
1590             i1--; i2--;
1591         }
1592         for ( int i3 = 0; i3 <= i1; i3++ )
1593             vec.removeElementAt( 0 );                                  //strip prefix
1594     }
1595 
1596 
1597 
1598     /**
1599      * Write boxedRMI valuetype for a single dimension of an IDL sequence
1600      * indicated by the given OutputType.
1601      * The filename for the OutputType is of the form "seqn_elemName" where n
1602      * is the dimension required.
1603      * @param ot Given OutputType.
1604      * @param p The output stream.
1605      */
1606     protected void writeSequence(
1607                                  OutputType ot,
1608                                  IndentingWriter p)
1609         throws IOException {
1610         ArrayType at = (ArrayType)ot.getType();
1611         Type et = at.getElementType();
1612         String fName = ot.getName();
1613         int dim = Integer.parseInt( fName.substring( 3,fName.indexOf( "_" ) ) );
1614         String idlName = unEsc( et.getIDLName() ).replace( ' ','_' );
1615         String qIdlName = getQualifiedIDLName( et );
1616         String qName = et.getQualifiedName();
1617 
1618         String repID = at.getRepositoryID();
1619         int rix1 = repID.indexOf( '[' );                       //edit repository id
1620         int rix2 = repID.lastIndexOf( '[' ) + 1;
1621             StringBuffer rid = new StringBuffer(
1622                                             repID.substring( 0,rix1 ) +
1623                                             repID.substring( rix2 ) );
1624         for ( int i1 = 0; i1 < dim; i1++ ) rid.insert( rix1,'[' );
1625 
1626         String vtName = "seq" + dim + "_" + idlName;
1627         boolean isFromIDL = false;
1628         if ( et.isCompound() ) {
1629             CompoundType ct = (CompoundType)et;
1630             isFromIDL = ct.isIDLEntity() || ct.isCORBAObject();
1631         }
1632         boolean isForwardInclude =
1633             et.isCompound() &&
1634             !isSpecialReference( et ) &&
1635             dim == 1 &&
1636             !isFromIDL &&
1637             !"org.omg.CORBA.Object".equals(qName) &&
1638             !"java.lang.String".equals(qName);
1639 
1640         writeBanner( at,dim,!isException,p );
1641         if ( dim == 1 && "java.lang.String".equals(qName) )          //special case
1642             writeIncOrb( p );
1643         if ( dim == 1 && "org.omg.CORBA.Object".equals(qName) ) ;
1644         else if ( isSpecialReference( et ) || dim > 1 || isFromIDL )
1645             writeInclude( at,dim-1,!isThrown,p );               //"trivial" include
1646         writeIfndef( at,dim,!isException,!isForward,p );
1647         if ( isForwardInclude )
1648             writeForwardReference( at,dim-1,p );                    //forward declare
1649         writeModule1( at,p );
1650                 p.pln();p.pI();
1651                 p.p( "valuetype " + vtName );
1652                 p.p( " sequence<" );
1653         if ( dim == 1 ) p.p( qIdlName );
1654                 else {
1655             p.p( "seq" + ( dim - 1 ) + "_"  );
1656                     p.p( idlName );
1657                 }
1658                 p.pln( ">;" );
1659                 p.pO();p.pln();
1660                 p.pln( "#pragma ID " + vtName + " \"" + rid + "\"" );
1661                 p.pln();
1662         writeModule2( at,p );
1663         if ( isForwardInclude )
1664             writeInclude( at,dim-1,!isThrown,p );      //#include for forward declare
1665                 writeEndif( p );
1666             }
1667 
1668 
1669     /**
1670      * Write valuetype for a boxed IDLEntity.
1671      * @param t Given CompoundType representing the IDLEntity.
1672      * @param p The output stream.
1673      */
1674     protected void writeBoxedIDL(
1675                                  CompoundType t,
1676                                  IndentingWriter p)
1677         throws IOException {
1678         String[] boxNames = getIDLModuleNames( t );
1679         int len = boxNames.length;
1680         String[] modNames = new String[len - 3];               //remove box modules
1681         for ( int i1 = 0; i1 < len - 3; i1++ ) modNames[i1] = boxNames[i1 + 3];
1682         String tName = unEsc( t.getIDLName() );
1683 
1684         writeBanner( t,0,!isException,p );
1685         writeInclude( t,modNames,tName,p );
1686         writeIfndef( t,0,!isException,!isForward,p );
1687         writeModule1( t,p );
1688         p.pln();p.pI();
1689 
1690         p.p( "valuetype " + tName + " " );
1691         for ( int i1 = 0; i1 < modNames.length; i1++ )
1692             p.p( IDL_NAME_SEPARATOR + modNames[i1] );
1693         p.pln( IDL_NAME_SEPARATOR + tName + ";" );
1694 
1695         p.pO();p.pln();
1696         writeRepositoryID( t,p );
1697         p.pln();
1698         writeModule2( t,p );
1699         writeEndif( p );
1700         }
1701 
1702 
1703     /**
1704      * Write an exception.
1705      * @param t Given ClassType representing the exception.
1706      * @param p The output stream.
1707      */
1708     protected void writeException(
1709                                   ClassType t,
1710                                   IndentingWriter p)
1711         throws IOException {
1712         writeBanner( t,0,isException,p );
1713         writeIfndef( t,0,isException,!isForward,p );
1714         writeForwardReference( t,p );
1715         writeModule1( t,p );
1716         p.pln();p.pI();
1717 
1718         p.pln( "exception " + t.getIDLExceptionName() + " {" );
1719         p.pln();p.pI();
1720         p.pln( t.getIDLName() + " value;" );
1721         p.pO();p.pln();
1722         p.pln( "};" );
1723 
1724         p.pO();p.pln();
1725         writeModule2( t,p );
1726         writeInclude( t,0,!isThrown,p );               //include valuetype idl file
1727         writeEndif( p );
1728     }
1729 
1730 
1731     /**
1732      * Write #pragma to identify the repository ID of the given type
1733      * @param t The given Type.
1734      * @param p The output stream.
1735      */
1736     protected void writeRepositoryID(
1737                                      Type t,
1738                                      IndentingWriter p )
1739         throws IOException {
1740         String repid = t.getRepositoryID();
1741         if ( t.isCompound() ) {
1742             CompoundType ct = (CompoundType)t;
1743             if ( ct.isBoxed() )
1744                 repid = ct.getBoxedRepositoryID();
1745         }
1746 
1747         p.pln( "#pragma ID " + t.getIDLName() + " \"" +
1748                repid + "\"" );
1749     }
1750 
1751     /**
1752      * Write inheritance for an IDL interface or valuetype. Any class
1753      * inheritance precedes any interface inheritance.
1754      * For a valutype any inheritance from abstract interfaces then
1755      * follows the "supports" keyword.
1756      * @param inhHash Hashtable loaded with inherited Types
1757      * @param forValuetype true if writing inheritance for a valuetype
1758      * @param p The output stream.
1759      */
1760     protected void writeInherits(
1761                                  Hashtable inhHash,
1762                                  boolean forValuetype,
1763                                  IndentingWriter p )
1764         throws IOException {
1765         int itot = inhHash.size();
1766         int iinh = 0;
1767         int isup = 0;
1768         if ( itot < 1 ) return;                         //any inheritance to write?
1769         Enumeration inhEnum = inhHash.elements();
1770         CompoundType ct;
1771         if ( forValuetype )
1772             while ( inhEnum.hasMoreElements() ) {
1773                 ct = (CompoundType)inhEnum.nextElement();
1774                 if ( ct.getTypeCode() == TYPE_ABSTRACT ) isup++;
1775             }
1776         iinh = itot - isup;
1777 
1778         if ( iinh > 0 ) {
1779         p.p( ": " );
1780             inhEnum = inhHash.elements();
1781         while ( inhEnum.hasMoreElements() ) {         //write any class inheritance
1782                 ct = (CompoundType)inhEnum.nextElement();
1783                 if ( ct.isClass() ) {
1784                     p.p( getQualifiedIDLName( ct ) );
1785                     if ( iinh > 1 ) p.p( ", " );               //delimit them with commas
1786                     else if ( itot > 1 ) p.p( " " );
1787                 break;                                                //only one parent
1788             }
1789         }
1790             int i = 0;
1791         inhEnum = inhHash.elements();
1792         while ( inhEnum.hasMoreElements() ) {     //write any interface inheritance
1793                 ct = (CompoundType)inhEnum.nextElement();
1794                 if ( !ct.isClass() &&
1795                      !( ct.getTypeCode() == TYPE_ABSTRACT ) ) {
1796                     if ( i++ > 0 ) p.p( ", " );                     //delimit with commas
1797                     p.p( getQualifiedIDLName( ct ) );
1798             }
1799         }
1800     }
1801         if ( isup > 0 ) {                    //write abstract interface inheritance
1802             p.p( " supports " );
1803             int i = 0;
1804             inhEnum = inhHash.elements();
1805             while ( inhEnum.hasMoreElements() ) {
1806                 ct = (CompoundType)inhEnum.nextElement();
1807                 if ( ct.getTypeCode() == TYPE_ABSTRACT ) {
1808                     if ( i++ > 0 ) p.p( ", " );                     //delimit with commas
1809                     p.p( getQualifiedIDLName( ct ) );
1810                 }
1811             }
1812         }
1813     }
1814 
1815 
1816     /**
1817      * Write an IDL constant
1818      * @param constant The current CompoundType.Member constant
1819      * @param p The output stream.
1820      */
1821     protected void writeConstant(
1822                                  CompoundType.Member constant,
1823                                  IndentingWriter p )
1824         throws IOException {
1825         Type t = constant.getType();
1826         p.p( "const " );
1827         p.p( getQualifiedIDLName( t ) );
1828         p.p( " " + constant.getIDLName() + " = " + constant.getValue() );
1829         p.pln( ";" );
1830     }
1831 
1832 
1833 
1834     /**
1835      * Write an IDL data member
1836      * @param data The current CompoundType.Member data member
1837      * @param p The output stream.
1838      */
1839     protected void writeData(
1840                              CompoundType.Member data,
1841                              IndentingWriter p )
1842         throws IOException {
1843         if ( data.isInnerClassDeclaration() ) return;                      //ignore
1844         Type t = data.getType();
1845         if ( data.isPublic() )
1846             p.p( "public " );
1847         else p.p( "private " );
1848         p.pln( getQualifiedIDLName( t ) +  " " +
1849                data.getIDLName() + ";" );
1850     }
1851 
1852 
1853 
1854     /**
1855      * Write an IDL Attribute
1856      * @param attr The current CompoundType.Method attribute
1857      * @param p The output stream.
1858      */
1859     protected void writeAttribute(
1860                                   CompoundType.Method attr,
1861                                   IndentingWriter p )
1862         throws IOException {
1863         if ( attr.getAttributeKind() == ATTRIBUTE_SET ) return;  //use getters only
1864         Type t = attr.getReturnType();
1865         if ( !attr.isReadWriteAttribute() ) p.p( "readonly " );
1866         p.p( "attribute " + getQualifiedIDLName( t ) + " " );
1867         p.pln( attr.getAttributeName() + ";" );
1868     }
1869 
1870 
1871 
1872     /**
1873      * Write an IDL method
1874      * @param method The current CompoundType.Method
1875      * @param p The output stream.
1876      */
1877     protected void writeMethod(
1878                                CompoundType.Method method,
1879                                IndentingWriter p )
1880         throws IOException {
1881         if ( method.isAttribute() ) {
1882             writeAttribute( method,p );
1883             return;
1884         }
1885         Type[]    pts = method.getArguments();
1886         String[]  paramNames = method.getArgumentNames();
1887         Type      rt = method.getReturnType();
1888         Hashtable excHash = new Hashtable();
1889         getExceptions( method,excHash );
1890 
1891         if ( method.isConstructor() )
1892             if ( factory ) p.p( "factory " + method.getIDLName() + "(" );
1893             else p.p( "init(" );                                    //IDL initializer
1894         else {
1895             p.p( getQualifiedIDLName( rt ) );
1896             p.p( " " + method.getIDLName() + "(" );
1897         }
1898         p.pI();
1899 
1900         for ( int i=0; i < pts.length; i++ ) {
1901             if ( i > 0 ) p.pln( "," );               //delimit with comma and newline
1902             else p.pln();
1903             p.p( "in " );
1904             p.p( getQualifiedIDLName( pts[i] ) );
1905             p.p( " " + paramNames[i] );
1906         }
1907         p.pO();
1908         p.p( " )" );
1909 
1910         if ( excHash.size() > 0 ) {                      //any exceptions to write?
1911             p.pln( " raises (" );
1912             p.pI();
1913             int i = 0;
1914             Enumeration excEnum = excHash.elements();
1915             while ( excEnum.hasMoreElements() ) {
1916                 ValueType exc = (ValueType)excEnum.nextElement();
1917                 if ( i > 0 ) p.pln( "," );                   //delimit them with commas
1918                 if ( exc.isIDLEntityException() )
1919                     if ( exc.isCORBAUserException() )
1920                         p.p( "::org::omg::CORBA::UserEx" );
1921                     else {
1922                         String[] modNames = getIDLModuleNames( exc );
1923                         for ( int i2 = 0; i2 < modNames.length; i2++ )
1924                             p.p( IDL_NAME_SEPARATOR + modNames[i2] );
1925                         p.p( IDL_NAME_SEPARATOR + exc.getName() );
1926                     }
1927                 else p.p( exc.getQualifiedIDLExceptionName( true ) );
1928                 i++;
1929             }
1930             p.pO();
1931             p.p( " )" );
1932         }
1933 
1934         p.pln( ";" );
1935     }
1936 
1937 
1938     /**
1939      * Remove escape character ("_"), if any, from given String
1940      * @param name Given String
1941      * @return String with any escape character removed
1942      */
1943     protected String unEsc(
1944                            String name ) {
1945         if ( name.startsWith( "_" ) ) return name.substring( 1 );
1946         else return name;
1947     }
1948 
1949 
1950     /**
1951      * Write IDL banner into the output stream for a given Type
1952      * @param t The given Type.
1953      * @param dim The dimension required if t is an ArrayType.
1954      * @param isException true if writing an exception.
1955      * @param p The output stream.
1956      */
1957     protected void writeBanner(
1958                                Type t,
1959                                int dim,
1960                                boolean isException,
1961                                IndentingWriter p )
1962         throws IOException {
1963         String[] modNames = getIDLModuleNames( t );             //module name array
1964         String fName = unEsc( t.getIDLName() );                 //file name default
1965         if ( isException && t.isClass() ) {
1966             ClassType ct = (ClassType)t;                    //file name for Exception
1967             fName = unEsc( ct.getIDLExceptionName() );
1968         }
1969         if ( dim > 0 && t.isArray() ) {
1970             Type et = t.getElementType();                    //file name for sequence
1971             fName = "seq" + dim + "_" + unEsc( et.getIDLName().replace( ' ','_' ) );
1972         }
1973 
1974         p.pln( "/**" );
1975         p.p( " * " );
1976         for ( int i1 = 0; i1 < modNames.length; i1++ )
1977             p.p( modNames[i1] + "/" );
1978         p.pln( fName + ".idl" );
1979         p.pln( " * Generated by rmic -idl. Do not edit" );
1980         String d = DateFormat.getDateTimeInstance(
1981                                                   DateFormat.FULL,DateFormat.FULL,Locale.getDefault() )
1982             .format( new Date() );
1983         String ocStr = "o'clock";
1984         int ocx = d.indexOf( ocStr );             //remove unwanted o'clock, if any
1985         p.p ( " * " );
1986         if ( ocx > -1 )
1987             p.pln( d.substring( 0,ocx ) + d.substring( ocx + ocStr.length() ) );
1988         else p.pln( d );
1989         p.pln( " */" );
1990         p.pln();
1991     }
1992 
1993 
1994     /**
1995      * Write #include for orb.idl
1996      * @param p The output stream.
1997      */
1998     protected void writeIncOrb(
1999                                IndentingWriter p )
2000         throws IOException {
2001         p.pln( "#include \"orb.idl\"" );
2002     }
2003 
2004 
2005     /**
2006      * Write #ifndef guard into the output stream for a given Type
2007      * @param t The given Type.
2008      * @param dim The dimension required if t is an ArrayType.
2009      * @param isException true if writing an exception.
2010      * @param isForward. No #define needed if it's a forward declare
2011      * @param p The output stream.
2012      */
2013     protected void writeIfndef(
2014                                Type t,
2015                                int dim,
2016                                boolean isException,
2017                                boolean isForward,
2018                                IndentingWriter p )
2019         throws IOException {
2020         String[] modNames = getIDLModuleNames( t );             //module name array
2021         String fName = unEsc( t.getIDLName() );                 //file name default
2022         if ( isException && t.isClass() ) {
2023             ClassType ct = (ClassType)t;                    //file name for Exception
2024             fName = unEsc( ct.getIDLExceptionName() );
2025         }
2026         if ( dim > 0 && t.isArray() ) {
2027             Type et = t.getElementType();                    //file name for sequence
2028             fName = "seq" + dim + "_" + unEsc( et.getIDLName().replace( ' ','_' ) );
2029         }
2030         p.pln();
2031         p.p( "#ifndef __" );
2032         for ( int i = 0; i < modNames.length; i++ ) p.p( modNames[i] + "_" );
2033         p.pln( fName + "__" );
2034         if ( !isForward ) {
2035         p.p( "#define __" );
2036         for ( int i = 0; i < modNames.length; i++ ) p.p( modNames[i] + "_" );
2037             p.pln( fName + "__" );
2038             p.pln();
2039     }
2040     }
2041 
2042 
2043     /**
2044      * Write #endif bracket into the output stream
2045      * @param p The output stream.
2046      */
2047     protected void writeEndif(
2048                               IndentingWriter p )
2049         throws IOException {
2050         p.pln("#endif");
2051         p.pln();
2052     }
2053 
2054     /**
2055      * Write Module start bracketing for the given type into the output stream
2056      * @param t The given Type
2057      * @param p The output stream.
2058      */
2059     protected void writeModule1(
2060                                 Type t,
2061                                 IndentingWriter p )
2062         throws IOException {
2063 
2064         String[] modNames = getIDLModuleNames( t );
2065         p.pln();
2066         for ( int i = 0; i < modNames.length; i++ )
2067             p.pln( "module " + modNames[i] + " {" );
2068     }
2069 
2070     /**
2071      * Write Module end bracketing for the given type into the output stream
2072      * @param t The given Type
2073      * @param p The output stream.
2074      */
2075     protected void writeModule2(
2076                                 Type t,
2077                                 IndentingWriter p )
2078         throws IOException {
2079         String[] modNames = getIDLModuleNames( t );
2080         for ( int i=0; i < modNames.length; i++ ) p.pln( "};" );
2081         p.pln();
2082     }
2083 
2084 }