1 /*
   2  * Copyright (c) 1998, 2013, 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 /*
  27  * Licensed Materials - Property of IBM
  28  * RMI-IIOP v1.0
  29  * Copyright IBM Corp. 1998 1999  All Rights Reserved
  30  *
  31  */
  32 
  33 package sun.rmi.rmic.iiop;
  34 
  35 import java.io.File;
  36 import java.io.IOException;
  37 import java.io.SerializablePermission;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 import java.util.Vector;
  41 import java.util.Hashtable;
  42 import java.util.Enumeration;
  43 import sun.tools.java.Identifier;
  44 import sun.tools.java.ClassNotFound;
  45 import sun.tools.java.ClassDefinition;
  46 import sun.tools.java.ClassDeclaration;
  47 import sun.tools.java.CompilerError;
  48 import sun.rmi.rmic.IndentingWriter;
  49 import java.util.HashSet;
  50 import java.util.Arrays;
  51 import com.sun.corba.se.impl.util.Utility;
  52 import com.sun.corba.se.impl.util.PackagePrefixChecker;
  53 import sun.rmi.rmic.Main;
  54 
  55 
  56 /**
  57  * An IIOP stub/tie generator for rmic.
  58  *
  59  * @author      Bryan Atsatt
  60  * @author      Anil Vijendran
  61  * @author      M. Mortazavi
  62  */
  63 
  64 public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
  65 
  66     private static final String DEFAULT_STUB_CLASS = "javax.rmi.CORBA.Stub";
  67     private static final String DEFAULT_TIE_CLASS = "org.omg.CORBA_2_3.portable.ObjectImpl";
  68     private static final String DEFAULT_POA_TIE_CLASS = "org.omg.PortableServer.Servant";
  69 
  70     protected boolean reverseIDs = false;
  71     protected boolean localStubs = true;
  72     protected boolean standardPackage = false;
  73     protected boolean useHash = true;
  74     protected String stubBaseClass = DEFAULT_STUB_CLASS;
  75     protected String tieBaseClass = DEFAULT_TIE_CLASS;
  76     protected HashSet namesInUse = new HashSet();
  77     protected Hashtable classesInUse = new Hashtable();
  78     protected Hashtable imports = new Hashtable();
  79     protected int importCount = 0;
  80     protected String currentPackage = null;
  81     protected String currentClass = null;
  82     protected boolean castArray = false;
  83     protected Hashtable transactionalObjects = new Hashtable() ;
  84     protected boolean POATie = false ;
  85     protected boolean emitPermissionCheck = false;
  86 
  87     /**
  88      * Default constructor for Main to use.
  89      */
  90     public StubGenerator() {
  91     }
  92 
  93     /**
  94      * Overridden in order to set the standardPackage flag.
  95      */
  96     public void generate(
  97             sun.rmi.rmic.BatchEnvironment env,
  98             ClassDefinition cdef, File destDir) {
  99         ((sun.rmi.rmic.iiop.BatchEnvironment)env).
 100                 setStandardPackage(standardPackage);
 101         super.generate(env, cdef, destDir);
 102     }
 103 
 104     /**
 105      * Return true if a new instance should be created for each
 106      * class on the command line. Subclasses which return true
 107      * should override newInstance() to return an appropriately
 108      * constructed instance.
 109      */
 110     protected boolean requireNewInstance() {
 111         return false;
 112     }
 113 
 114     /**
 115      * Return true if non-conforming types should be parsed.
 116      * @param stack The context stack.
 117      */
 118     protected boolean parseNonConforming(ContextStack stack) {
 119 
 120         // We let the environment setting decide so that
 121         // another generator (e.g. IDLGenerator) can change
 122         // it and we will just go with the flow...
 123 
 124         return stack.getEnv().getParseNonConforming();
 125     }
 126 
 127     /**
 128      * Create and return a top-level type.
 129      * @param cdef The top-level class definition.
 130      * @param stack The context stack.
 131      * @return The compound type or null if is non-conforming.
 132      */
 133     protected CompoundType getTopType(ClassDefinition cdef, ContextStack stack) {
 134 
 135         CompoundType result = null;
 136 
 137         // Do we have an interface?
 138 
 139         if (cdef.isInterface()) {
 140 
 141             // Yes, so first try Abstract...
 142 
 143             result = AbstractType.forAbstract(cdef,stack,true);
 144 
 145             if (result == null) {
 146 
 147                 // Then try Remote...
 148 
 149                 result = RemoteType.forRemote(cdef,stack,false);
 150             }
 151         } else {
 152 
 153             // Not an interface, so try Implementation...
 154 
 155             result = ImplementationType.forImplementation(cdef,stack,false);
 156         }
 157 
 158         return result;
 159     }
 160 
 161     /**
 162      * Examine and consume command line arguments.
 163      * @param argv The command line arguments. Ignore null
 164      * and unknown arguments. Set each consumed argument to null.
 165      * @param error Report any errors using the main.error() methods.
 166      * @return true if no errors, false otherwise.
 167      */
 168     public boolean parseArgs(String argv[], Main main) {
 169         Object marker = new Object() ;
 170 
 171         // Reset any cached options...
 172 
 173         reverseIDs = false;
 174         localStubs = true;
 175         useHash = true;
 176         stubBaseClass = DEFAULT_STUB_CLASS;
 177         //       tieBaseClass = DEFAULT_TIE_CLASS;
 178         transactionalObjects = new Hashtable() ;
 179 
 180         // Parse options...
 181 
 182         boolean result = super.parseArgs(argv,main);
 183         if (result) {
 184             for (int i = 0; i < argv.length; i++) {
 185                 if (argv[i] != null) {
 186                     String arg = argv[i].toLowerCase();
 187                     if (arg.equals("-iiop")) {
 188                         argv[i] = null;
 189                     } else if (arg.equals("-xreverseids")) {
 190                         reverseIDs = true;
 191                         argv[i] = null;
 192                     } else if (arg.equals("-nolocalstubs")) {
 193                         localStubs = false;
 194                         argv[i] = null;
 195                     } else if (arg.equals("-xnohash")) {
 196                         useHash = false;
 197                         argv[i] = null;
 198                     } else if (argv[i].equals("-standardPackage")) {
 199                         standardPackage = true;
 200                         argv[i] = null;
 201                     } else if (argv[i].equals("-emitPermissionCheck")) {
 202                         emitPermissionCheck = true;
 203                         argv[i] = null;
 204                     } else if (arg.equals("-xstubbase")) {
 205                         argv[i] = null;
 206                         if (++i < argv.length && argv[i] != null && !argv[i].startsWith("-")) {
 207                             stubBaseClass = argv[i];
 208                             argv[i] = null;
 209                         } else {
 210                             main.error("rmic.option.requires.argument", "-Xstubbase");
 211                             result = false;
 212                         }
 213                     } else if (arg.equals("-xtiebase")) {
 214                         argv[i] = null;
 215                         if (++i < argv.length && argv[i] != null && !argv[i].startsWith("-")) {
 216                             tieBaseClass = argv[i];
 217                             argv[i] = null;
 218                         } else {
 219                             main.error("rmic.option.requires.argument", "-Xtiebase");
 220                             result = false;
 221                         }
 222                     } else if (arg.equals("-transactional" )) {
 223                         // Scan for the next non-flag argument.
 224                         // Assume that it is a class name and add it
 225                         // to the list of transactional classes.
 226                         for ( int ctr=i+1; ctr<argv.length; ctr++ ) {
 227                             if (argv[ctr].charAt(1) != '-') {
 228                                 transactionalObjects.put( argv[ctr], marker ) ;
 229                                 break ;
 230                             }
 231                         }
 232                         argv[i] = null;
 233                     } else if (arg.equals( "-poa" )) {
 234                         POATie = true ;
 235                         argv[i] = null;
 236                     }
 237                 }
 238             }
 239         }
 240         if(POATie){
 241             tieBaseClass = DEFAULT_POA_TIE_CLASS;
 242         } else {
 243             tieBaseClass = DEFAULT_TIE_CLASS;
 244         }
 245         return result;
 246     }
 247 
 248     /**
 249      * Return an array containing all the file names and types that need to be
 250      * generated for the given top-level type.  The file names must NOT have an
 251      * extension (e.g. ".java").
 252      * @param topType The type returned by getTopType().
 253      * @param alreadyChecked A set of Types which have already been checked.
 254      *  Intended to be passed to topType.collectMatching(filter,alreadyChecked).
 255      */
 256     protected OutputType[] getOutputTypesFor(CompoundType topType,
 257                                              HashSet alreadyChecked) {
 258 
 259         // We want to generate stubs for all remote and implementation types,
 260         // so collect them up.
 261         //
 262         // We use the form of collectMatching which allows us to pass in a set of
 263         // types which have previously been checked. By doing so, we ensure that if
 264         // the command line contains Hello and HelloImpl, we will only generate
 265         // output for Hello once...
 266 
 267         int filter = TYPE_REMOTE | TYPE_IMPLEMENTATION;
 268         Type[] genTypes = topType.collectMatching(filter,alreadyChecked);
 269         int count = genTypes.length;
 270         Vector list = new Vector(count+5);
 271         BatchEnvironment theEnv = topType.getEnv();
 272 
 273         // Now walk all types...
 274 
 275         for (int i = 0; i < genTypes.length; i++) {
 276 
 277             Type type = genTypes[i];
 278             String typeName = type.getName();
 279             boolean createStub = true;
 280 
 281             // Is it an implementation type?
 282 
 283             if (type instanceof ImplementationType) {
 284 
 285                 // Yes, so add a tie for it...
 286 
 287                 list.addElement(new OutputType(Utility.tieNameForCompiler(typeName), type));
 288 
 289                 // Does it have more than 1 remote interface?  If so, we
 290                 // want to create a stub for it...
 291 
 292                 int remoteInterfaceCount = 0;
 293                 InterfaceType[] interfaces = ((CompoundType)type).getInterfaces();
 294                 for (int j = 0; j < interfaces.length; j++) {
 295                     if (interfaces[j].isType(TYPE_REMOTE) &&
 296                         !interfaces[j].isType(TYPE_ABSTRACT)) {
 297                         remoteInterfaceCount++;
 298                     }
 299                 }
 300 
 301                 if (remoteInterfaceCount <= 1) {
 302 
 303                     // No, so do not create a stub for this type...
 304 
 305                     createStub = false;
 306                 }
 307             }
 308 
 309             // Is it an abstract interface type?
 310 
 311             if (type instanceof AbstractType) {
 312 
 313                 // Do not create a stub for this type...
 314 
 315                 createStub = false;  // d11141
 316             }
 317 
 318             if (createStub) {
 319 
 320                 // Add a stub for the type...
 321 
 322                 list.addElement(new OutputType(Utility.stubNameForCompiler(typeName), type));
 323             }
 324         }
 325 
 326         // Copy list into array..
 327 
 328         OutputType[] outputTypes = new OutputType[list.size()];
 329         list.copyInto(outputTypes);
 330         return outputTypes;
 331     }
 332 
 333     /**
 334      * Return the file name extension for the given file name (e.g. ".java").
 335      * All files generated with the ".java" extension will be compiled. To
 336      * change this behavior for ".java" files, override the compileJavaSourceFile
 337      * method to return false.
 338      * @param outputType One of the items returned by getOutputTypesFor(...)
 339      */
 340     protected String getFileNameExtensionFor(OutputType outputType) {
 341         return SOURCE_FILE_EXTENSION;
 342     }
 343 
 344     /**
 345      * Write the output for the given OutputFileName into the output stream.
 346      * @param name One of the items returned by getOutputTypesFor(...)
 347      * @param alreadyChecked A set of Types which have already been checked.
 348      *  Intended to be passed to Type.collectMatching(filter,alreadyChecked).
 349      * @param writer The output stream.
 350      */
 351     protected void writeOutputFor(      OutputType outputType,
 352                                         HashSet alreadyChecked,
 353                                         IndentingWriter writer) throws IOException {
 354 
 355         String fileName = outputType.getName();
 356         CompoundType theType = (CompoundType) outputType.getType();
 357 
 358         // Are we doing a Stub or Tie?
 359 
 360         if (fileName.endsWith(Utility.RMI_STUB_SUFFIX)) {
 361 
 362             // Stub.
 363 
 364             writeStub(outputType,writer);
 365 
 366         } else {
 367 
 368             // Tie
 369 
 370             writeTie(outputType,writer);
 371         }
 372     }
 373 
 374     /**
 375      * Write a stub for the specified type.
 376      */
 377     protected void writeStub(OutputType outputType,
 378                              IndentingWriter p) throws IOException {
 379 
 380         CompoundType theType = (CompoundType) outputType.getType();
 381         RemoteType[] remoteInterfaces = getDirectRemoteInterfaces(theType);
 382 
 383         // Write comment.
 384 
 385         p.pln("// Stub class generated by rmic, do not edit.");
 386         p.pln("// Contents subject to change without notice.");
 387         p.pln();
 388 
 389         // Set our standard classes...
 390 
 391         setStandardClassesInUse(theType,true);
 392 
 393         // Add classes for this type...
 394 
 395         addClassesInUse(theType,remoteInterfaces);
 396 
 397         // Write package and import statements...
 398 
 399         writePackageAndImports(p);
 400 
 401 //        generate
 402 //        import java.security.AccessController;
 403 //        import java.security.PrivilegedAction;
 404 //        import java.io.SerializablePermission;
 405         if (emitPermissionCheck) {
 406             p.pln("import java.security.AccessController;");
 407             p.pln("import java.security.PrivilegedAction;");
 408             p.pln("import java.io.SerializablePermission;");
 409             p.pln();
 410             p.pln();
 411         }
 412 
 413         // Declare the stub class; implement all remote interfaces.
 414 
 415         p.p("public class " + currentClass);
 416 
 417         p.p(" extends " + getName(stubBaseClass));
 418         p.p(" implements ");
 419         if (remoteInterfaces.length > 0) {
 420             for(int i = 0; i < remoteInterfaces.length; i++) {
 421                 if (i > 0) {
 422                     p.pln(",");
 423                 }
 424                 String objName = testUtil(getName(remoteInterfaces[i]), theType);
 425                 p.p(objName);
 426             }
 427         }
 428 
 429         // Add java.rmi.Remote if this type does not implement it.
 430         // This allows stubs for Abstract interfaces to be treated
 431         // uniformly...
 432 
 433         if (!implementsRemote(theType)) {
 434             p.pln(",");
 435             p.p(getName("java.rmi.Remote"));
 436         }
 437 
 438         p.plnI(" {");
 439         p.pln();
 440 
 441         // Write the ids...
 442 
 443         writeIds( p, theType, false );
 444         p.pln();
 445 
 446         if (emitPermissionCheck) {
 447 
 448             // produce the following generated code for example
 449             //
 450             // private transient boolean _instantiated = false;
 451             //
 452             // private static Void checkPermission() {
 453             // SecurityManager sm = System.getSecurityManager();
 454             // if (sm != null) {
 455             //     sm.checkPermission(new SerializablePermission(
 456             // "enableSubclassImplementation")); // testing
 457             // }
 458             // return null;
 459             // }
 460             //
 461             // private _XXXXX_Stub(Void ignore) {
 462             // }
 463             //
 464             // public _XXXXX_Stub() {
 465             // this(checkPermission());
 466             // _instantiated = true;
 467             // }
 468             //
 469             // private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
 470             //    checkPermission();
 471             //    s.defaultReadObject();
 472             //    _instantiated = true;
 473             // }
 474             //
 475             // where XXXXX is the name of the remote interface
 476 
 477                 p.pln();
 478                 p.plnI("private transient boolean _instantiated = false;");
 479                 p.pln();
 480                 p.pO();
 481                 p.plnI("private static Void checkPermission() {");
 482                 p.plnI("SecurityManager sm = System.getSecurityManager();");
 483                 p.pln("if (sm != null) {");
 484                 p.pI();
 485                 p.plnI("sm.checkPermission(new SerializablePermission(");
 486                 p.plnI("\"enableSubclassImplementation\"));");
 487                 p.pO();
 488                 p.pO();
 489                 p.pOln("}");
 490                 p.pln("return null;");
 491                 p.pO();
 492                 p.pOln("}");
 493                 p.pln();
 494                 p.pO();
 495 
 496                 p.pI();
 497                 p.plnI("private " + currentClass + "(Void ignore) {  }");
 498                 p.pln();
 499                 p.pO();
 500 
 501                 p.plnI("public " + currentClass + "() { ");
 502                 p.pln("this(checkPermission());");
 503                 p.pln("_instantiated = true;");
 504                 p.pOln("}");
 505                 p.pln();
 506                 p.plnI("private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {");
 507                 p.plnI("checkPermission();");
 508                 p.pO();
 509                 p.pln("s.defaultReadObject();");
 510                 p.pln("_instantiated = true;");
 511                 p.pOln("}");
 512                 p.pln();
 513                 //p.pO();
 514         }
 515 
 516        if (!emitPermissionCheck) {
 517             p.pI();
 518        }
 519 
 520         // Write the _ids() method...
 521 
 522         p.plnI("public String[] _ids() { ");
 523         p.pln("return (String[]) _type_ids.clone();");
 524         p.pOln("}");
 525 
 526         // Get all the methods and write each stub method...
 527 
 528         CompoundType.Method[] remoteMethods = theType.getMethods();
 529         int methodCount = remoteMethods.length;
 530         if (methodCount > 0) {
 531             boolean writeHeader = true;
 532             for(int i = 0; i < methodCount; i++) {
 533                 if (!remoteMethods[i].isConstructor()) {
 534                     if (writeHeader) {
 535                         writeHeader = false;
 536                     }
 537                     p.pln();
 538                     writeStubMethod(p, remoteMethods[i], theType);
 539                 }
 540             }
 541         }
 542 
 543         // Write the cast array hack...
 544 
 545         writeCastArray(p);
 546 
 547         p.pOln("}");            // end stub class
 548     }
 549 
 550     void addClassInUse(String qualifiedName) {
 551         String unqualifiedName = qualifiedName;
 552         String packageName = null;
 553         int index = qualifiedName.lastIndexOf('.');
 554         if (index > 0) {
 555             unqualifiedName = qualifiedName.substring(index+1);
 556             packageName = qualifiedName.substring(0,index);
 557         }
 558         addClassInUse(unqualifiedName,qualifiedName,packageName);
 559     }
 560 
 561     void addClassInUse(Type type) {
 562         if (!type.isPrimitive()) {
 563             Identifier id = type.getIdentifier();
 564             String name = IDLNames.replace(id.getName().toString(),". ",".");
 565             String packageName = type.getPackageName();
 566             String qualifiedName;
 567             if (packageName != null) {
 568                 qualifiedName = packageName+"."+name;
 569             } else {
 570                 qualifiedName = name;
 571             }
 572             addClassInUse(name,qualifiedName,packageName);
 573         }
 574     }
 575 
 576     void addClassInUse(Type[] types) {
 577         for (int i = 0; i < types.length; i++) {
 578             addClassInUse(types[i]);
 579         }
 580     }
 581 
 582     void addStubInUse(Type type) {
 583         if (type.getIdentifier() != idCorbaObject &&
 584             type.isType(TYPE_CORBA_OBJECT)) {
 585             String stubName = getStubNameFor(type,false);
 586             String packageName = type.getPackageName();
 587             String fullName;
 588             if (packageName == null) {
 589                 fullName = stubName;
 590             } else {
 591                 fullName = packageName + "." + stubName;
 592             }
 593             addClassInUse(stubName,fullName,packageName);
 594         }
 595         if (type.isType(TYPE_REMOTE) ||
 596             type.isType(TYPE_JAVA_RMI_REMOTE)) {
 597             addClassInUse("javax.rmi.PortableRemoteObject");
 598         }
 599     }
 600 
 601     String getStubNameFor(Type type, boolean qualified) {
 602         String stubName;
 603         String className;
 604         if (qualified) {
 605             className = type.getQualifiedName();
 606         } else {
 607             className = type.getName();
 608         }
 609         if (((CompoundType)type).isCORBAObject()) {
 610             stubName = Utility.idlStubName(className);
 611         } else {
 612             stubName = Utility.stubNameForCompiler(className);
 613         }
 614         return stubName;
 615     }
 616 
 617     void addStubInUse(Type[] types) {
 618         for (int i = 0; i < types.length; i++) {
 619             addStubInUse(types[i]);
 620         }
 621     }
 622 
 623     private static final String NO_IMPORT = new String();
 624 
 625     void addClassInUse(String unqualifiedName, String qualifiedName, String packageName) {
 626 
 627         // Have we already got an entry for this qualifiedName?
 628 
 629         String currentName = (String)classesInUse.get(qualifiedName);
 630 
 631         if (currentName == null) {
 632 
 633             // No, never seen it before. Grab any existing import
 634             // name and then decide what to do...
 635 
 636             String importName = (String) imports.get(unqualifiedName);
 637             String nameToUse = null;
 638 
 639             if (packageName == null) {
 640 
 641                 // Default package, so doesn't matter which name to use...
 642 
 643                 nameToUse = unqualifiedName;
 644 
 645             } else if (packageName.equals("java.lang")) {
 646 
 647                 // java.lang.*, so use unqualified name...
 648 
 649                 nameToUse = unqualifiedName;
 650 
 651                 // unless you want to be able to import things from the right place :--)
 652 
 653                 if(nameToUse.endsWith("_Stub")) nameToUse = Util.packagePrefix()+qualifiedName;
 654 
 655             } else if (currentPackage != null && packageName.equals(currentPackage)) {
 656 
 657                 // Class in currentPackage, so use unqualified name...
 658 
 659                 nameToUse = unqualifiedName;
 660 
 661                 // Do we already have a previous import under this
 662                 // unqualified name?
 663 
 664                 if (importName != null) {
 665 
 666                     // Yes, so we use qualifiedName...
 667 
 668                     nameToUse = qualifiedName;
 669 
 670                 }
 671 
 672             } else if (importName != null) {
 673 
 674                 // It is in some package for which we normally
 675                 // would import, but we have a previous import
 676                 // under this unqualified name. We must use
 677                 // the qualified name...
 678 
 679                 nameToUse = qualifiedName;
 680 
 681                 /*
 682                   // Is the currentPackage the default package?
 683 
 684                   if (currentPackage == null) {
 685 
 686                   // Yes, so undo the import so that all
 687                   // uses for this name will be qualified...
 688 
 689                   String old = (String)imports.remove(unqualifiedName);
 690                   classesInUse.put(old,old);
 691                   importCount--;
 692 
 693                   // Note that this name is in use but should
 694                   // not be imported...
 695 
 696                   imports.put(nameToUse,NO_IMPORT);
 697                   }
 698                 */
 699             } else if (qualifiedName.equals("org.omg.CORBA.Object")) {
 700 
 701                 // Always qualify this quy to avoid confusion...
 702 
 703                 nameToUse = qualifiedName;
 704 
 705             } else {
 706 
 707                 // Default to using unqualified name, and add
 708                 // this guy to the imports...
 709 
 710                 // Check for nested class in which case we use
 711                 // the fully qualified name instead of imports
 712                 if (unqualifiedName.indexOf('.') != -1) {
 713                     nameToUse = qualifiedName;
 714                 } else {
 715                     nameToUse = unqualifiedName;
 716                     imports.put(unqualifiedName,qualifiedName);
 717                     importCount++;
 718                 }
 719             }
 720 
 721             // Now add the name...
 722 
 723             classesInUse.put(qualifiedName,nameToUse);
 724         }
 725     }
 726 
 727     String getName(Type type) {
 728         if (type.isPrimitive()) {
 729             return type.getName() + type.getArrayBrackets();
 730         }
 731         Identifier id = type.getIdentifier();
 732         String name = IDLNames.replace(id.toString(),". ",".");
 733         return getName(name) + type.getArrayBrackets();
 734     }
 735 
 736     // Added for Bug 4818753
 737     String getExceptionName(Type type) {
 738         Identifier id = type.getIdentifier();
 739         return IDLNames.replace(id.toString(),". ",".");
 740     }
 741 
 742     String getName(String qualifiedName) {
 743         return (String)classesInUse.get(qualifiedName);
 744     }
 745 
 746     String getName(Identifier id) {
 747         return getName(id.toString());
 748     }
 749 
 750     String getStubName(Type type) {
 751         String stubName = getStubNameFor(type,true);
 752         return getName(stubName);
 753     }
 754 
 755     void setStandardClassesInUse(CompoundType type,
 756                                  boolean stub) throws IOException {
 757 
 758         // Reset our state...
 759 
 760         currentPackage = type.getPackageName();
 761         imports.clear();
 762         classesInUse.clear();
 763         namesInUse.clear();
 764         importCount = 0;
 765         castArray = false;
 766 
 767         // Add the top-level type...
 768 
 769         addClassInUse(type);
 770 
 771         // Set current class name...
 772 
 773         if (stub) {
 774             currentClass = Utility.stubNameForCompiler(type.getName());
 775         } else {
 776             currentClass = Utility.tieNameForCompiler(type.getName());
 777         }
 778 
 779         // Add current class...
 780 
 781         if (currentPackage == null) {
 782             addClassInUse(currentClass,currentClass,currentPackage);
 783         } else {
 784             addClassInUse(currentClass,(currentPackage+"."+currentClass),currentPackage);
 785         }
 786 
 787         // Add standard classes...
 788 
 789         addClassInUse("javax.rmi.CORBA.Util");
 790         addClassInUse(idRemote.toString());
 791         addClassInUse(idRemoteException.toString());
 792         addClassInUse(idOutputStream.toString());
 793         addClassInUse(idInputStream.toString());
 794         addClassInUse(idSystemException.toString());
 795         addClassInUse(idJavaIoSerializable.toString());
 796         addClassInUse(idCorbaORB.toString());
 797         addClassInUse(idReplyHandler.toString());
 798 
 799         // Add stub/tie specific imports...
 800 
 801         if (stub) {
 802             addClassInUse(stubBaseClass);
 803             addClassInUse("java.rmi.UnexpectedException");
 804             addClassInUse(idRemarshalException.toString());
 805             addClassInUse(idApplicationException.toString());
 806             if (localStubs) {
 807                 addClassInUse("org.omg.CORBA.portable.ServantObject");
 808             }
 809         } else {
 810             addClassInUse(type);
 811             addClassInUse(tieBaseClass);
 812             addClassInUse(idTieInterface.toString());
 813             addClassInUse(idBadMethodException.toString());
 814             addClassInUse(idPortableUnknownException.toString());
 815             addClassInUse(idJavaLangThrowable.toString());
 816         }
 817     }
 818 
 819     void addClassesInUse(CompoundType type, RemoteType[] interfaces) {
 820 
 821         // Walk all methods and add types in use...
 822 
 823         CompoundType.Method[] methods = type.getMethods();
 824         for (int i = 0; i < methods.length; i++) {
 825             addClassInUse(methods[i].getReturnType());
 826             addStubInUse(methods[i].getReturnType());
 827             addClassInUse(methods[i].getArguments());
 828             addStubInUse(methods[i].getArguments());
 829             addClassInUse(methods[i].getExceptions());
 830             // bug 4473859: Also include narrower subtypes for use
 831             addClassInUse(methods[i].getImplExceptions());
 832         }
 833 
 834         // If this is a stub, add all interfaces...
 835 
 836         if (interfaces != null) {
 837             addClassInUse(interfaces);
 838         }
 839     }
 840 
 841     void writePackageAndImports(IndentingWriter p) throws IOException {
 842 
 843         // Write package declaration...
 844 
 845         if (currentPackage != null) {
 846             p.pln("package " +
 847                      Util.correctPackageName(
 848                           currentPackage, false, standardPackage)
 849                    + ";");
 850             p.pln();
 851         }
 852 
 853         // Get imports into an array and sort them...
 854 
 855         String[] names = new String[importCount];
 856         int index = 0;
 857         for (Enumeration e = imports.elements() ; e.hasMoreElements() ;) {
 858             String it = (String) e.nextElement();
 859             if (it != NO_IMPORT) {
 860                 names[index++] = it;
 861             }
 862         }
 863 
 864         Arrays.sort(names,new StringComparator());
 865 
 866         // Now dump them out...
 867 
 868         for (int i = 0; i < importCount; i++) {
 869             if(
 870                Util.isOffendingPackage(names[i])
 871                && names[i].endsWith("_Stub")
 872                && String.valueOf(names[i].charAt(names[i].lastIndexOf(".")+1)).equals("_")
 873                ){
 874                 p.pln("import " + PackagePrefixChecker.packagePrefix()+names[i]+";");
 875             } else{
 876                 p.pln("import " + names[i] + ";");
 877             }
 878         }
 879         p.pln();
 880 
 881         // Include offending packages . . .
 882         if ( currentPackage!=null && Util.isOffendingPackage(currentPackage) ){
 883             p.pln("import " + currentPackage +".*  ;");
 884         }
 885         p.pln();
 886 
 887     }
 888 
 889     boolean implementsRemote(CompoundType theType) {
 890         boolean result = theType.isType(TYPE_REMOTE) && !theType.isType(TYPE_ABSTRACT);
 891 
 892         // If theType is not remote, look at all the interfaces
 893         // until we find one that is...
 894 
 895         if (!result) {
 896             InterfaceType[] interfaces = theType.getInterfaces();
 897             for (int i = 0; i < interfaces.length; i++) {
 898                 result = implementsRemote(interfaces[i]);
 899                 if (result) {
 900                     break;
 901                 }
 902             }
 903         }
 904 
 905         return result;
 906     }
 907 
 908     void writeStubMethod (  IndentingWriter p,
 909                             CompoundType.Method method,
 910                             CompoundType theType) throws IOException {
 911 
 912         // Wtite the method declaration and opening brace...
 913         String methodName = method.getName();
 914         String methodIDLName = method.getIDLName();
 915 
 916         Type paramTypes[] = method.getArguments();
 917         String paramNames[] = method.getArgumentNames();
 918         Type returnType = method.getReturnType();
 919         ValueType[] exceptions = getStubExceptions(method,false);
 920         boolean hasIOException = false;
 921 
 922         addNamesInUse(method);
 923         addNameInUse("_type_ids");
 924 
 925         String objName = testUtil(getName(returnType), returnType);
 926         p.p("public " + objName + " " + methodName + "(");
 927         for(int i = 0; i < paramTypes.length; i++) {
 928             if (i > 0)
 929                 p.p(", ");
 930             p.p(getName(paramTypes[i]) + " " + paramNames[i]);
 931         }
 932 
 933         p.p(")");
 934         if (exceptions.length > 0) {
 935             p.p(" throws ");
 936             for(int i = 0; i < exceptions.length; i++) {
 937                 if (i > 0) {
 938                     p.p(", ");
 939                 }
 940                 // Added for Bug 4818753
 941                 p.p(getExceptionName(exceptions[i]));
 942             }
 943         }
 944 
 945         p.plnI(" {");
 946 
 947         // Now create the method body...
 948         if (emitPermissionCheck) {
 949             p.pln("if ((System.getSecurityManager() != null) && (!_instantiated)) {");
 950             p.plnI("    throw new java.io.IOError(new java.io.IOException(\"InvalidObject \"));");
 951             p.pOln("}");
 952             p.pln();
 953         }
 954 
 955 
 956         if (localStubs) {
 957             writeLocalStubMethodBody(p,method,theType);
 958         } else {
 959             writeNonLocalStubMethodBody(p,method,theType);
 960         }
 961 
 962         // Close out the method...
 963 
 964         p.pOln("}");
 965     }
 966 
 967 
 968     void writeLocalStubMethodBody (IndentingWriter p,
 969                                    CompoundType.Method method,
 970                                    CompoundType theType) throws IOException {
 971 
 972         String objName;
 973         String paramNames[] = method.getArgumentNames();
 974         Type returnType = method.getReturnType();
 975         ValueType[] exceptions = getStubExceptions(method,false);
 976         String methodName = method.getName();
 977         String methodIDLName = method.getIDLName();
 978 
 979         p.plnI("if (!Util.isLocal(this)) {");
 980         writeNonLocalStubMethodBody(p,method,theType);
 981         p.pOlnI("} else {");
 982         String so = getVariableName("so");
 983 
 984         p.pln("ServantObject "+so+" = _servant_preinvoke(\""+methodIDLName+"\","+getName(theType)+".class);");
 985         p.plnI("if ("+so+" == null) {");
 986         if (!returnType.isType(TYPE_VOID)) {
 987             p.p("return ");
 988         }
 989         p.p(methodName+"(");
 990         for (int i = 0; i < paramNames.length; i++) {
 991             if (i > 0)
 992                 p.p(", ");
 993             p.p(paramNames[i]);
 994         }
 995         p.pln(");");
 996         if (returnType.isType(TYPE_VOID)) {
 997             p.pln( "return ;" ) ;
 998         }
 999 
1000         p.pOln("}");
1001         p.plnI("try {");
1002 
1003         // Generate code to copy required arguments, and
1004         // get back the names by which all arguments are known...
1005 
1006         String[] argNames = writeCopyArguments(method,p);
1007 
1008         // Now write the method...
1009 
1010         boolean copyReturn = mustCopy(returnType);
1011         String resultName = null;
1012         if (!returnType.isType(TYPE_VOID)) {
1013             if (copyReturn) {
1014                 resultName = getVariableName("result");
1015                 objName = testUtil(getName(returnType), returnType);
1016                 p.p(objName+" "+resultName + " = ");
1017             } else {
1018                 p.p("return ");
1019             }
1020         }
1021         objName = testUtil(getName(theType), theType);
1022         p.p("(("+objName+")"+so+".servant)."+methodName+"(");
1023 
1024         for (int i = 0; i < argNames.length; i++) {
1025             if (i > 0)
1026                 p.p(", ");
1027             p.p(argNames[i]);
1028         }
1029 
1030         if (copyReturn) {
1031             p.pln(");");
1032             objName = testUtil(getName(returnType), returnType);
1033             p.pln("return ("+objName+")Util.copyObject("+resultName+",_orb());");
1034         } else {
1035             p.pln(");");
1036         }
1037 
1038         String e1 = getVariableName("ex");
1039         String e2 = getVariableName("exCopy");
1040         p.pOlnI("} catch (Throwable "+e1+") {");
1041 
1042         p.pln("Throwable "+e2+" = (Throwable)Util.copyObject("+e1+",_orb());");
1043         for(int i = 0; i < exceptions.length; i++) {
1044             if (exceptions[i].getIdentifier() != idRemoteException &&
1045                 exceptions[i].isType(TYPE_VALUE)) {
1046                 // Added for Bug 4818753
1047                 p.plnI("if ("+e2+" instanceof "+getExceptionName(exceptions[i])+") {");
1048                 p.pln("throw ("+getExceptionName(exceptions[i])+")"+e2+";");
1049                 p.pOln("}");
1050             }
1051         }
1052 
1053         p.pln("throw Util.wrapException("+e2+");");
1054         p.pOlnI("} finally {");
1055         p.pln("_servant_postinvoke("+so+");");
1056         p.pOln("}");
1057         p.pOln("}");
1058     }
1059 
1060 
1061     void writeNonLocalStubMethodBody (  IndentingWriter p,
1062                                         CompoundType.Method method,
1063                                         CompoundType theType) throws IOException {
1064 
1065         String methodName = method.getName();
1066         String methodIDLName = method.getIDLName();
1067 
1068         Type paramTypes[] = method.getArguments();
1069         String paramNames[] = method.getArgumentNames();
1070         Type returnType = method.getReturnType();
1071         ValueType[] exceptions = getStubExceptions(method,true);
1072 
1073         String in = getVariableName("in");
1074         String out = getVariableName("out");
1075         String ex = getVariableName("ex");
1076 
1077         // Decide if we need to use the new streams for
1078         // any of the read calls...
1079 
1080         boolean needNewReadStreamClass = false;
1081         for (int i = 0; i < exceptions.length; i++) {
1082             if (exceptions[i].getIdentifier() != idRemoteException &&
1083                 exceptions[i].isType(TYPE_VALUE) &&
1084                 needNewReadStreamClass(exceptions[i])) {
1085                 needNewReadStreamClass = true;
1086                 break;
1087             }
1088         }
1089         if (!needNewReadStreamClass) {
1090             for (int i = 0; i < paramTypes.length; i++) {
1091                 if (needNewReadStreamClass(paramTypes[i])) {
1092                     needNewReadStreamClass = true;
1093                     break;
1094                 }
1095             }
1096         }
1097         if (!needNewReadStreamClass) {
1098             needNewReadStreamClass = needNewReadStreamClass(returnType);
1099         }
1100 
1101         // Decide if we need to use the new streams for
1102         // any of the write calls...
1103 
1104         boolean needNewWriteStreamClass = false;
1105         for (int i = 0; i < paramTypes.length; i++) {
1106             if (needNewWriteStreamClass(paramTypes[i])) {
1107                 needNewWriteStreamClass = true;
1108                 break;
1109             }
1110         }
1111 
1112         // Now write the method, inserting casts where needed...
1113 
1114         p.plnI("try {");
1115         if (needNewReadStreamClass) {
1116             p.pln(idExtInputStream + " "+in+" = null;");
1117         } else {
1118             p.pln(idInputStream + " "+in+" = null;");
1119         }
1120         p.plnI("try {");
1121 
1122         String argStream = "null";
1123 
1124         if (needNewWriteStreamClass) {
1125             p.plnI(idExtOutputStream + " "+out+" = ");
1126             p.pln("(" + idExtOutputStream + ")");
1127             p.pln("_request(\"" + methodIDLName + "\", true);");
1128             p.pO();
1129         } else {
1130             p.pln("OutputStream "+out+" = _request(\"" + methodIDLName + "\", true);");
1131         }
1132 
1133         if (paramTypes.length > 0) {
1134             writeMarshalArguments(p, out, paramTypes, paramNames);
1135             p.pln();
1136         }
1137         argStream = out;
1138 
1139         if (returnType.isType(TYPE_VOID)) {
1140             p.pln("_invoke(" + argStream + ");" );
1141         } else {
1142             if (needNewReadStreamClass) {
1143                 p.plnI(in+" = (" + idExtInputStream + ")_invoke(" + argStream + ");");
1144                 p.pO();
1145             } else {
1146                 p.pln(in+" = _invoke(" + argStream + ");");
1147             }
1148             p.p("return ");
1149             writeUnmarshalArgument(p, in, returnType, null);
1150             p.pln();
1151         }
1152 
1153         // Handle ApplicationException...
1154 
1155         p.pOlnI("} catch ("+getName(idApplicationException)+" "+ex+") {");
1156         if (needNewReadStreamClass) {
1157             p.pln(in + " = (" + idExtInputStream + ") "+ex+".getInputStream();");
1158         } else {
1159             p.pln(in + " = "+ex+".getInputStream();");
1160         }
1161 
1162         boolean idRead = false;
1163         boolean idAllocated = false;
1164         for(int i = 0; i < exceptions.length; i++) {
1165             if (exceptions[i].getIdentifier() != idRemoteException) {
1166 
1167                 // Is this our special-case IDLEntity exception?
1168 
1169                 if (exceptions[i].isIDLEntityException() && !exceptions[i].isCORBAUserException()) {
1170 
1171                     // Yes.
1172 
1173                     if (!idAllocated && !idRead) {
1174                         p.pln("String $_id = "+ex+".getId();");
1175                         idAllocated = true;
1176                     }
1177 
1178                     String helperName = IDLNames.replace(exceptions[i].getQualifiedIDLName(false),"::",".");
1179                     helperName += "Helper";
1180                     p.plnI("if ($_id.equals("+helperName+".id())) {");
1181                     p.pln("throw "+helperName+".read("+in+");");
1182 
1183                 } else {
1184 
1185                     // No.
1186 
1187                     if (!idAllocated && !idRead) {
1188         p.pln("String $_id = "+in+".read_string();");
1189                         idAllocated = true;
1190                         idRead = true;
1191                     } else if (idAllocated && !idRead) {
1192                         p.pln("$_id = "+in+".read_string();");
1193                         idRead = true;
1194                     }
1195                     p.plnI("if ($_id.equals(\""+getExceptionRepositoryID(exceptions[i])+"\")) {");
1196                     // Added for Bug 4818753
1197                     p.pln("throw ("+getExceptionName(exceptions[i])+") "+in+".read_value(" + getExceptionName(exceptions[i]) + ".class);");
1198                 }
1199                 p.pOln("}");
1200             }
1201         }
1202         if (!idAllocated && !idRead) {
1203             p.pln("String $_id = "+in+".read_string();");
1204             idAllocated = true;
1205             idRead = true;
1206         } else if (idAllocated && !idRead) {
1207             p.pln("$_id = "+in+".read_string();");
1208             idRead = true;
1209         }
1210         p.pln("throw new UnexpectedException($_id);");
1211 
1212         // Handle RemarshalException...
1213 
1214         p.pOlnI("} catch ("+getName(idRemarshalException)+" "+ex+") {");
1215         if (!returnType.isType(TYPE_VOID)) {
1216             p.p("return ");
1217         }
1218         p.p(methodName + "(");
1219         for(int i = 0; i < paramTypes.length; i++) {
1220             if (i > 0) {
1221                 p.p(",");
1222             }
1223             p.p(paramNames[i]);
1224         }
1225         p.pln(");");
1226 
1227         // Ensure that we release the reply...
1228 
1229         p.pOlnI("} finally {");
1230         p.pln("_releaseReply("+in+");");
1231 
1232         p.pOln("}");
1233 
1234         // Handle SystemException...
1235 
1236         p.pOlnI("} catch (SystemException "+ex+") {");
1237         p.pln("throw Util.mapSystemException("+ex+");");
1238         p.pOln("}");
1239 
1240         // returnResult(p,returnType);
1241     }
1242 
1243     void allocateResult (IndentingWriter p,
1244                          Type returnType) throws IOException {
1245         if (!returnType.isType(TYPE_VOID)) {
1246             String objName = testUtil(getName(returnType), returnType);
1247             p.p(objName + " result = ");
1248         }
1249     }
1250 
1251     int getTypeCode(Type type) {
1252 
1253         int typeCode = type.getTypeCode();
1254 
1255         // Handle late-breaking special case for
1256         // abstract IDL entities...
1257 
1258         if ((type instanceof CompoundType) &&
1259             ((CompoundType)type).isAbstractBase()) {
1260             typeCode = TYPE_ABSTRACT;
1261         }
1262 
1263         return typeCode;
1264     }
1265 
1266 
1267     /**
1268      * Write a snippet of Java code to marshal a value named "name" of
1269      * type "type" to the java.io.ObjectOutput stream named "stream".
1270      */
1271     void writeMarshalArgument(IndentingWriter p,
1272                               String streamName,
1273                               Type type, String name) throws IOException {
1274 
1275         int typeCode = getTypeCode(type);
1276 
1277         switch (typeCode) {
1278         case TYPE_BOOLEAN:
1279             p.p(streamName + ".write_boolean(" + name + ");");
1280             break;
1281         case TYPE_BYTE:
1282             p.p(streamName + ".write_octet(" + name + ");");
1283             break;
1284         case TYPE_CHAR:
1285             p.p(streamName + ".write_wchar(" + name + ");");
1286             break;
1287         case TYPE_SHORT:
1288             p.p(streamName + ".write_short(" + name + ");");
1289             break;
1290         case TYPE_INT:
1291             p.p(streamName + ".write_long(" + name + ");");
1292             break;
1293         case TYPE_LONG:
1294             p.p(streamName + ".write_longlong(" + name + ");");
1295             break;
1296         case TYPE_FLOAT:
1297             p.p(streamName + ".write_float(" + name + ");");
1298             break;
1299         case TYPE_DOUBLE:
1300             p.p(streamName + ".write_double(" + name + ");");
1301             break;
1302         case TYPE_STRING:
1303             p.p(streamName + ".write_value(" + name + "," + getName(type) + ".class);");
1304             break;
1305         case TYPE_ANY:
1306             p.p("Util.writeAny("+ streamName + "," + name + ");");
1307             break;
1308         case TYPE_CORBA_OBJECT:
1309             p.p(streamName + ".write_Object(" + name + ");");
1310             break;
1311         case TYPE_REMOTE:
1312             p.p("Util.writeRemoteObject("+ streamName + "," + name + ");");
1313             break;
1314         case TYPE_ABSTRACT:
1315             p.p("Util.writeAbstractObject("+ streamName + "," + name + ");");
1316             break;
1317         case TYPE_NC_INTERFACE:
1318             p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);");
1319             break;
1320         case TYPE_VALUE:
1321             p.p(streamName + ".write_value(" + name + "," + getName(type) + ".class);");
1322             break;
1323         case TYPE_IMPLEMENTATION:
1324             p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);");
1325             break;
1326         case TYPE_NC_CLASS:
1327             p.p(streamName + ".write_value((Serializable)" + name + "," + getName(type) + ".class);");
1328             break;
1329         case TYPE_ARRAY:
1330             castArray = true;
1331             p.p(streamName + ".write_value(cast_array(" + name + ")," + getName(type) + ".class);");
1332             break;
1333         case TYPE_JAVA_RMI_REMOTE:
1334             p.p("Util.writeRemoteObject("+ streamName + "," + name + ");");
1335             break;
1336         default:
1337             throw new Error("unexpected type code: " + typeCode);
1338         }
1339     }
1340 
1341     /**
1342      * Write a snippet of Java code to unmarshal a value of type "type"
1343      * from the java.io.ObjectInput stream named "stream" into a variable
1344      * named "name" (if "name" is null, the value in unmarshalled and
1345      * discarded).
1346      */
1347     void writeUnmarshalArgument(IndentingWriter p,
1348                                 String streamName,
1349                                 Type type,
1350                                 String name) throws IOException {
1351 
1352         int typeCode = getTypeCode(type);
1353 
1354         if (name != null) {
1355             p.p(name + " = ");
1356         }
1357 
1358         switch (typeCode) {
1359         case TYPE_BOOLEAN:
1360             p.p(streamName + ".read_boolean();");
1361             break;
1362         case TYPE_BYTE:
1363             p.p(streamName + ".read_octet();");
1364             break;
1365         case TYPE_CHAR:
1366             p.p(streamName + ".read_wchar();");
1367             break;
1368         case TYPE_SHORT:
1369             p.p(streamName + ".read_short();");
1370             break;
1371         case TYPE_INT:
1372             p.p(streamName + ".read_long();");
1373             break;
1374         case TYPE_LONG:
1375             p.p(streamName + ".read_longlong();");
1376             break;
1377         case TYPE_FLOAT:
1378             p.p(streamName + ".read_float();");
1379             break;
1380         case TYPE_DOUBLE:
1381             p.p(streamName + ".read_double();");
1382             break;
1383         case TYPE_STRING:
1384             p.p("(String) " + streamName + ".read_value(" + getName(type) + ".class);");
1385             break;
1386         case TYPE_ANY:
1387             if (type.getIdentifier() != idJavaLangObject) {
1388                 p.p("(" + getName(type) + ") ");
1389             }
1390             p.p("Util.readAny(" + streamName + ");");
1391             break;
1392         case TYPE_CORBA_OBJECT:
1393             if (type.getIdentifier() == idCorbaObject) {
1394                 p.p("(" + getName(type) + ") " + streamName + ".read_Object();");
1395             } else {
1396                 p.p("(" + getName(type) + ") " + streamName + ".read_Object(" + getStubName(type) + ".class);");
1397             }
1398             break;
1399         case TYPE_REMOTE:
1400             String objName = testUtil(getName(type), type);
1401             p.p("(" + objName + ") " +
1402                 "PortableRemoteObject.narrow(" + streamName + ".read_Object(), " + objName + ".class);");
1403             break;
1404         case TYPE_ABSTRACT:
1405             p.p("(" + getName(type) + ") " + streamName + ".read_abstract_interface();");
1406             break;
1407         case TYPE_NC_INTERFACE:
1408             p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);");
1409             break;
1410         case TYPE_VALUE:
1411             p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);");
1412             break;
1413         case TYPE_IMPLEMENTATION:
1414             p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);");
1415             break;
1416         case TYPE_NC_CLASS:
1417             p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);");
1418             break;
1419         case TYPE_ARRAY:
1420             p.p("(" + getName(type) + ") " + streamName + ".read_value(" + getName(type) + ".class);");
1421             break;
1422         case TYPE_JAVA_RMI_REMOTE:
1423             p.p("(" + getName(type) + ") " +
1424                 "PortableRemoteObject.narrow(" + streamName + ".read_Object(), " + getName(type) + ".class);");
1425             //      p.p("(" + getName(type) + ") " + streamName + ".read_Object(" + getStubName(type) + ".class);");
1426             break;
1427         default:
1428             throw new Error("unexpected type code: " + typeCode);
1429         }
1430     }
1431 
1432     /**
1433      * Get a list of all the RepositoryIDs for interfaces
1434      * implemented directly or indirectly by theType. In the
1435      * case of an  ImplementationType which implements 2 or
1436      * more remote interfaces, this list will begin with the
1437      * Identifier for the implementation (see section 5.9 in
1438      * the Java -> IDL mapping). Ensures that the most derived
1439      * type is first in the list because the IOR is generated
1440      * using that entry in the _ids array.
1441      */
1442     String[] getAllRemoteRepIDs (CompoundType theType) {
1443 
1444         String[] result;
1445 
1446         // Collect up all the (inherited) remote interfaces
1447         // (ignores all the 'special' interfaces: Remote,
1448         // Serializable, Externalizable)...
1449 
1450         Type[] types = collectAllRemoteInterfaces(theType);
1451 
1452         int length = types.length;
1453         boolean haveImpl = theType instanceof ImplementationType;
1454         InterfaceType[] interfaces = theType.getInterfaces();
1455         int remoteCount = countRemote(interfaces,false);
1456         int offset = 0;
1457 
1458         // Do we have an implementation type that implements
1459         // more than one remote interface?
1460 
1461         if (haveImpl && remoteCount > 1) {
1462 
1463             // Yes, so we need to insert it at the beginning...
1464 
1465             result = new String[length + 1];
1466             result[0] = getRepositoryID(theType);
1467             offset = 1;
1468 
1469         } else {
1470 
1471             // No.
1472 
1473             result = new String[length];
1474 
1475             // Here we need to ensure that the most derived
1476             // interface ends up being first in the list. If
1477             // there is only one, we're done.
1478 
1479             if (length > 1) {
1480 
1481                 // First, decide what the most derived type is...
1482 
1483                 String mostDerived = null;
1484 
1485                 if (haveImpl) {
1486 
1487                     // If we get here, we know that there is only one
1488                     // direct remote interface, so just find it...
1489 
1490                     for (int i = 0; i < interfaces.length; i++) {
1491                         if (interfaces[i].isType(TYPE_REMOTE)) {
1492                             mostDerived = interfaces[i].getRepositoryID();
1493                             break;
1494                         }
1495                     }
1496                 } else {
1497 
1498                     // If we get here we know that theType is a RemoteType
1499                     // so just use its id...
1500 
1501                     mostDerived = theType.getRepositoryID();
1502                 }
1503 
1504                 // Now search types list and make sure mostDerived is
1505                 // at index zero...
1506 
1507                 for (int i = 0; i < length; i++) {
1508                     if (types[i].getRepositoryID() == mostDerived) {
1509 
1510                         // Found it. Swap it if we need to...
1511 
1512                         if (i > 0) {
1513                             Type temp = types[0];
1514                             types[0] = types[i];
1515                             types[i] = temp;
1516                         }
1517 
1518                         break;
1519                     }
1520                 }
1521             }
1522         }
1523 
1524         // Now copy contents of the types array...
1525 
1526         for (int i = 0; i < types.length; i++) {
1527             result[offset++] = getRepositoryID(types[i]);
1528         }
1529 
1530         // If we're supposed to, reverse the array. This
1531         // is only done when the -testReverseIDs flag is
1532         // passed, and that should ONLY be done for test
1533         // cases. This is an undocumented feature.
1534 
1535         if (reverseIDs) {
1536             int start = 0;
1537             int end = result.length -1;
1538             while (start < end) {
1539                 String temp = result[start];
1540                 result[start++] = result[end];
1541                 result[end--] = temp;
1542             }
1543         }
1544 
1545         return result;
1546     }
1547 
1548     /**
1549      * Collect all the inherited remote interfaces.
1550      */
1551     Type[] collectAllRemoteInterfaces (CompoundType theType) {
1552         Vector list = new Vector();
1553 
1554         // Collect up all the Remote interfaces, and get an instance
1555         // for java.rmi.Remote...
1556 
1557         addRemoteInterfaces(list,theType);
1558 
1559         // Create and return our results...
1560 
1561         Type[] result = new Type[list.size()];
1562         list.copyInto(result);
1563 
1564         return result;
1565     }
1566 
1567     /**
1568      * Add all the inherited remote interfaces to list.
1569      */
1570     void addRemoteInterfaces(Vector list, CompoundType theType) {
1571 
1572         if (theType != null) {
1573             if (theType.isInterface() && !list.contains(theType)) {
1574                 list.addElement(theType);
1575             }
1576 
1577             InterfaceType[] interfaces = theType.getInterfaces();
1578             for (int i = 0; i < interfaces.length; i++) {
1579 
1580                 if (interfaces[i].isType(TYPE_REMOTE)) {
1581                     addRemoteInterfaces(list,interfaces[i]);
1582                 }
1583             }
1584 
1585             addRemoteInterfaces(list,theType.getSuperclass());
1586         }
1587     }
1588 
1589     /**
1590      * Get a list of all the remote interfaces which this stub
1591      * should declare.
1592      */
1593     RemoteType[] getDirectRemoteInterfaces (CompoundType theType) {
1594 
1595         RemoteType[] result;
1596         InterfaceType[] interfaces = theType.getInterfaces();
1597 
1598         // First, get a list of all the interfaces...
1599 
1600         InterfaceType[] list;
1601 
1602         // Because we can be passed either an ImplementationType
1603         // (which has interfaces) or a RemoteType (which is an
1604         // interface and may have interfaces) we must handle each
1605         // separately...
1606 
1607         // Do we have an implementation type?
1608 
1609         if (theType instanceof ImplementationType) {
1610 
1611             // Yes, so list is exactly what this type
1612             // implements and is correct already.
1613 
1614             list = interfaces;
1615 
1616         } else {
1617 
1618             // No, so list is just theType...
1619 
1620             list = new InterfaceType[1];
1621             list[0] = (InterfaceType) theType;
1622         }
1623 
1624         // Ok, now count up the remote interfaces, allocate
1625         // our result and fill it in...
1626 
1627         int remoteCount = countRemote(list,false);
1628 
1629         if (remoteCount == 0) {
1630             throw new CompilerError("iiop.StubGenerator: No remote interfaces!");
1631         }
1632 
1633         result = new RemoteType[remoteCount];
1634         int offset = 0;
1635         for (int i = 0; i < list.length; i++) {
1636             if (list[i].isType(TYPE_REMOTE)) {
1637                 result[offset++] = (RemoteType)list[i];
1638             }
1639         }
1640 
1641         return result;
1642     }
1643 
1644     int countRemote (Type[] list, boolean includeAbstract) {
1645         int remoteCount = 0;
1646         for (int i = 0; i < list.length; i++) {
1647             if (list[i].isType(TYPE_REMOTE) &&
1648                 (includeAbstract || !list[i].isType(TYPE_ABSTRACT))) {
1649                 remoteCount++;
1650             }
1651         }
1652 
1653         return remoteCount;
1654     }
1655 
1656     void writeCastArray(IndentingWriter p) throws IOException {
1657         if (castArray) {
1658             p.pln();
1659             p.pln("// This method is required as a work-around for");
1660             p.pln("// a bug in the JDK 1.1.6 verifier.");
1661             p.pln();
1662             p.plnI("private "+getName(idJavaIoSerializable)+" cast_array(Object obj) {");
1663             p.pln("return ("+getName(idJavaIoSerializable)+")obj;");
1664             p.pOln("}");
1665         }
1666     }
1667     void writeIds(IndentingWriter p, CompoundType theType, boolean isTie
1668                   ) throws IOException {
1669         p.plnI("private static final String[] _type_ids = {");
1670 
1671         String[] ids = getAllRemoteRepIDs(theType);
1672 
1673         if (ids.length >0 ) {
1674             for(int i = 0; i < ids.length; i++) {
1675                 if (i > 0)
1676                     p.pln(", ");
1677                 p.p("\"" + ids[i] + "\"");
1678             }
1679         } else {
1680            // Must be an implementation which only implements Remote...
1681            p.pln("\"\"");
1682         }
1683         String qname = theType.getQualifiedName() ;
1684         boolean isTransactional = isTie && transactionalObjects.containsKey( qname ) ;
1685         // Add TransactionalObject if needed.
1686         if (isTransactional) {
1687             // Have already written an id.
1688             p.pln( ", " ) ;
1689             p.pln( "\"IDL:omg.org/CosTransactions/TransactionalObject:1.0\"" ) ;
1690         } else if (ids.length > 0) {
1691             p.pln();
1692         }
1693         p.pOln("};");
1694     }
1695 
1696 
1697     /**
1698      * Write the Tie for the remote class to a stream.
1699      */
1700     protected void writeTie(OutputType outputType,
1701                             IndentingWriter p) throws IOException
1702     {
1703         CompoundType theType = (CompoundType) outputType.getType();
1704         RemoteType[] remoteInterfaces = null;
1705 
1706         // Write comment...
1707         p.pln("// Tie class generated by rmic, do not edit.");
1708         p.pln("// Contents subject to change without notice.");
1709         p.pln();
1710 
1711         // Set our standard classes...
1712         setStandardClassesInUse(theType,false);
1713 
1714         // Add classes for this type...
1715         addClassesInUse(theType,remoteInterfaces);
1716 
1717         // Write package and import statements...
1718         writePackageAndImports(p);
1719 
1720         // Declare the tie class.
1721         p.p("public class " + currentClass + " extends " +
1722             getName(tieBaseClass) + " implements Tie");
1723 
1724         // Add java.rmi.Remote if this type does not implement it.
1725         // This allows stubs for Abstract interfaces to be treated
1726         // uniformly...
1727         if (!implementsRemote(theType)) {
1728             p.pln(",");
1729             p.p(getName("java.rmi.Remote"));
1730         }
1731 
1732         p.plnI(" {");
1733 
1734         // Write data members...
1735         p.pln();
1736         p.pln("volatile private " + getName(theType) + " target = null;");
1737         p.pln();
1738 
1739         // Write the ids...
1740         writeIds( p, theType, true ) ;
1741 
1742         // Write setTarget method...
1743         p.pln();
1744         p.plnI("public void setTarget(Remote target) {");
1745         p.pln("this.target = (" + getName(theType) + ") target;");
1746         p.pOln("}");
1747 
1748         // Write getTarget method...
1749         p.pln();
1750         p.plnI("public Remote getTarget() {");
1751         p.pln("return target;");
1752         p.pOln("}");
1753 
1754         // Write thisObject method...
1755         p.pln();
1756         write_tie_thisObject_method(p,idCorbaObject);
1757 
1758         // Write deactivate method...
1759         p.pln();
1760         write_tie_deactivate_method(p);
1761 
1762         // Write get orb method...
1763         p.pln();
1764         p.plnI("public ORB orb() {");
1765         p.pln("return _orb();");
1766         p.pOln("}");
1767 
1768         // Write set orb method...
1769         p.pln();
1770         write_tie_orb_method(p);
1771 
1772         // Write the _ids() method...
1773         p.pln();
1774         write_tie__ids_method(p);
1775 
1776         // Get all the methods...
1777         CompoundType.Method[] remoteMethods = theType.getMethods();
1778 
1779         // Register all the argument names used, plus our
1780         // data member names...
1781 
1782         addNamesInUse(remoteMethods);
1783         addNameInUse("target");
1784         addNameInUse("_type_ids");
1785 
1786         // Write the _invoke method...
1787         p.pln();
1788 
1789         String in = getVariableName("in");
1790         String _in = getVariableName("_in");
1791         String ex = getVariableName("ex");
1792         String method = getVariableName("method");
1793         String reply = getVariableName("reply");
1794 
1795         p.plnI("public OutputStream  _invoke(String "+method+", InputStream "+_in+", " +
1796                "ResponseHandler "+reply+") throws SystemException {");
1797 
1798         if (remoteMethods.length > 0) {
1799             p.plnI("try {");
1800             p.pln(getName(theType) + " target = this.target;");
1801             p.plnI("if (target == null) {");
1802             p.pln("throw new java.io.IOException();");
1803             p.pOln("}");
1804             p.plnI(idExtInputStream + " "+in+" = ");
1805             p.pln("(" + idExtInputStream + ") "+_in+";");
1806             p.pO();
1807 
1808             // See if we should use a hash table style
1809             // comparison...
1810 
1811             StaticStringsHash hash = getStringsHash(remoteMethods);
1812 
1813             if (hash != null) {
1814                 p.plnI("switch ("+method+"."+hash.method+") {");
1815                 for (int i = 0; i < hash.buckets.length; i++) {
1816                     p.plnI("case "+hash.keys[i]+": ");
1817                     for (int j = 0; j < hash.buckets[i].length; j++) {
1818                         CompoundType.Method current = remoteMethods[hash.buckets[i][j]];
1819                         if (j > 0) {
1820                             p.pO("} else ");
1821                         }
1822                         p.plnI("if ("+method+".equals(\""+ current.getIDLName() +"\")) {");
1823                         writeTieMethod(p, theType,current);
1824                     }
1825                     p.pOln("}");
1826                     p.pO();
1827                 }
1828             } else {
1829                 for(int i = 0; i < remoteMethods.length; i++) {
1830                 CompoundType.Method current = remoteMethods[i];
1831                 if (i > 0) {
1832                     p.pO("} else ");
1833                 }
1834 
1835                 p.plnI("if ("+method+".equals(\""+ current.getIDLName() +"\")) {");
1836                 writeTieMethod(p, theType, current);
1837             }
1838             }
1839 
1840             if (hash != null) {
1841                 p.pI();
1842                 //        p.plnI("default:");
1843             } else {
1844                 //   p.pOlnI("} else {");
1845             }
1846             //              p.pln("throw new "+getName(idBadMethodException)+"();");
1847 
1848             if (hash != null) {
1849                 p.pO();
1850             }
1851             p.pOln("}");
1852             p.pln("throw new "+getName(idBadMethodException)+"();");
1853 
1854             p.pOlnI("} catch ("+getName(idSystemException)+" "+ex+") {");
1855             p.pln("throw "+ex+";");
1856 
1857             p.pOlnI("} catch ("+getName(idJavaLangThrowable)+" "+ex+") {");
1858             p.pln("throw new " + getName(idPortableUnknownException) + "("+ex+");");
1859             p.pOln("}");
1860         } else {
1861             // No methods...
1862 
1863             p.pln("throw new " + getName(idBadMethodException) + "();");
1864         }
1865 
1866         p.pOln("}");            // end invoke
1867 
1868         // Write the cast array hack...
1869 
1870         writeCastArray(p);
1871 
1872         // End tie class...
1873         p.pOln("}");
1874     }
1875     public void catchWrongPolicy(IndentingWriter p) throws IOException {
1876         p.pln("");
1877     }
1878     public void catchServantNotActive(IndentingWriter p) throws IOException {
1879         p.pln("");
1880     }
1881     public void catchObjectNotActive(IndentingWriter p) throws IOException {
1882         p.pln("");
1883     }
1884 
1885     public void write_tie_thisObject_method(IndentingWriter p,
1886                                             Identifier idCorbaObject)
1887         throws IOException
1888     {
1889         if(POATie){
1890             p.plnI("public " + idCorbaObject + " thisObject() {");
1891             /*
1892             p.pln("org.omg.CORBA.Object objref = null;");
1893             p.pln("try{");
1894             p.pln("objref = _poa().servant_to_reference(this);");
1895             p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){");
1896             catchWrongPolicy(p);
1897             p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){");
1898             catchServantNotActive(p);
1899             p.pln("}");
1900             p.pln("return objref;");
1901             */
1902             p.pln("return _this_object();");
1903             p.pOln("}");
1904         } else {
1905             p.plnI("public " + idCorbaObject + " thisObject() {");
1906             p.pln("return this;");
1907             p.pOln("}");
1908         }
1909     }
1910 
1911     public void write_tie_deactivate_method(IndentingWriter p)
1912         throws IOException
1913     {
1914         if(POATie){
1915             p.plnI("public void deactivate() {");
1916             p.pln("try{");
1917             p.pln("_poa().deactivate_object(_poa().servant_to_id(this));");
1918             p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){");
1919             catchWrongPolicy(p);
1920             p.pln("}catch (org.omg.PortableServer.POAPackage.ObjectNotActive exception){");
1921             catchObjectNotActive(p);
1922             p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){");
1923             catchServantNotActive(p);
1924             p.pln("}");
1925             p.pOln("}");
1926         } else {
1927             p.plnI("public void deactivate() {");
1928             p.pln("_orb().disconnect(this);");
1929             p.pln("_set_delegate(null);");
1930             p.pln("target = null;");
1931             p.pOln("}");
1932         }
1933     }
1934 
1935     public void write_tie_orb_method(IndentingWriter p)
1936         throws IOException
1937     {
1938         if(POATie){
1939         p.plnI("public void orb(ORB orb) {");
1940         /*
1941         p.pln("try{");
1942         p.pln("orb.connect(_poa().servant_to_reference(this));");
1943         p.pln("}catch (org.omg.PortableServer.POAPackage.WrongPolicy exception){");
1944         catchWrongPolicy(p);
1945         p.pln("}catch (org.omg.PortableServer.POAPackage.ServantNotActive exception){");
1946         catchServantNotActive(p);
1947         p.pln("}");
1948         */
1949         p.pln("try {");
1950         p.pln("    ((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);");
1951         p.pln("}");
1952         p.pln("catch(ClassCastException e) {");
1953         p.pln("    throw new org.omg.CORBA.BAD_PARAM");
1954         p.pln("        (\"POA Servant requires an instance of org.omg.CORBA_2_3.ORB\");");
1955         p.pln("}");
1956         p.pOln("}");
1957         } else {
1958         p.plnI("public void orb(ORB orb) {");
1959         p.pln("orb.connect(this);");
1960         p.pOln("}");
1961         }
1962     }
1963 
1964     public void write_tie__ids_method(IndentingWriter p)
1965         throws IOException
1966     {
1967         if(POATie){
1968         p.plnI("public String[] _all_interfaces(org.omg.PortableServer.POA poa, byte[] objectId){");
1969         p.pln("return (String[]) _type_ids.clone();");
1970         p.pOln("}");
1971         } else {
1972         p.plnI("public String[] _ids() { ");
1973         p.pln("return (String[]) _type_ids.clone();");
1974         p.pOln("}");
1975         }
1976     }
1977 
1978 
1979     StaticStringsHash getStringsHash (CompoundType.Method[] methods) {
1980         if (useHash && methods.length > 1) {
1981             String[] methodNames = new String[methods.length];
1982             for (int i = 0; i < methodNames.length; i++) {
1983                 methodNames[i] = methods[i].getIDLName();
1984             }
1985             return new StaticStringsHash(methodNames);
1986         }
1987         return null;
1988     }
1989 
1990     static boolean needNewReadStreamClass(Type type) {
1991         if (type.isType(TYPE_ABSTRACT)) {
1992             return true;
1993         }
1994         // Handle late-breaking special case for
1995         // abstract IDL entities...
1996         if ((type instanceof CompoundType) &&
1997             ((CompoundType)type).isAbstractBase()) {
1998             return true;
1999         }
2000         return needNewWriteStreamClass(type);
2001     }
2002 
2003     static boolean needNewWriteStreamClass(Type type) {
2004         switch (type.getTypeCode()) {
2005         case TYPE_VOID:
2006         case TYPE_BOOLEAN:
2007         case TYPE_BYTE:
2008         case TYPE_CHAR:
2009         case TYPE_SHORT:
2010         case TYPE_INT:
2011         case TYPE_LONG:
2012         case TYPE_FLOAT:
2013         case TYPE_DOUBLE:           return false;
2014 
2015         case TYPE_STRING:           return true;
2016         case TYPE_ANY:              return false;
2017         case TYPE_CORBA_OBJECT:     return false;
2018         case TYPE_REMOTE:           return false;
2019         case TYPE_ABSTRACT:         return false;
2020         case TYPE_NC_INTERFACE:     return true;
2021         case TYPE_VALUE:            return true;
2022         case TYPE_IMPLEMENTATION:   return true;
2023         case TYPE_NC_CLASS:         return true;
2024         case TYPE_ARRAY:            return true;
2025         case TYPE_JAVA_RMI_REMOTE:  return false;
2026 
2027         default: throw new Error("unexpected type code: " + type.getTypeCode());
2028         }
2029     }
2030 
2031     /*
2032      * Decide which arguments need to be copied and write
2033      * the copy code. Returns an array of argument names to
2034      * use to refer to either the copy or the original.
2035      */
2036     String[] writeCopyArguments(CompoundType.Method method,
2037                                 IndentingWriter p) throws IOException {
2038 
2039         Type[] args = method.getArguments();
2040         String[] origNames = method.getArgumentNames();
2041 
2042         // Copy the current parameter names to a result array...
2043 
2044         String[] result = new String[origNames.length];
2045         for (int i = 0; i < result.length; i++) {
2046             result[i] = origNames[i];
2047         }
2048 
2049         // Decide which arguments must be copied, if any. If
2050         // any of the arguments are types for which a 'real' copy
2051         // will be done, rather than just an autoConnect, set
2052         // realCopy = true. Note that abstract types may only
2053         // need autoConnect, but we cannot know that at compile
2054         // time...
2055 
2056         boolean realCopy = false;
2057         boolean[] copyArg = new boolean[args.length];
2058         int copyCount = 0;
2059         int firstCopiedArg = 0; // Only used in single copy case.  It is only the first arg that
2060                                 // needs copying IF copyCount == 1.
2061 
2062         for (int i = 0; i < args.length; i++) {
2063             if (mustCopy(args[i])) {
2064                 copyArg[i] = true;
2065                 copyCount++;
2066                 firstCopiedArg = i;
2067                 if (args[i].getTypeCode() != TYPE_REMOTE &&
2068                     args[i].getTypeCode() != TYPE_IMPLEMENTATION) {
2069                     realCopy = true;
2070                 }
2071             } else {
2072                 copyArg[i] = false;
2073             }
2074         }
2075 
2076         // Do we have any types which must be copied?
2077         if (copyCount > 0) {
2078             // Yes. Are we only doing the copy to ensure
2079             // that autoConnect occurs?
2080             if (realCopy) {
2081                 // Nope. We need to go back thru the list and
2082                 // mark any strings so that they will be copied
2083                 // to preserve any shared references...
2084                 for (int i = 0; i < args.length; i++) {
2085                     if (args[i].getTypeCode() == TYPE_STRING) {
2086                         copyArg[i] = true;
2087                         copyCount++;
2088                     }
2089                 }
2090             }
2091 
2092             // We're ready to generate code. Do we have more than
2093             // one to copy?
2094             if (copyCount > 1) {
2095                 // Generate a call to copyObjects...
2096                 String arrayName = getVariableName("copies");
2097                 p.p("Object[] " + arrayName + " = Util.copyObjects(new Object[]{");
2098                 boolean first = true;
2099                 for (int i = 0; i < args.length; i++) {
2100                     if (copyArg[i]) {
2101                         if (!first) {
2102                             p.p(",");
2103                         }
2104                         first = false;
2105                         p.p(origNames[i]);
2106                     }
2107                 }
2108                 p.pln("},_orb());");
2109 
2110                 // For each of the types which was copied, create
2111                 // a local temporary for it, updating the result
2112                 // array with the new local parameter name...
2113                 int copyIndex = 0 ;
2114                 for (int i = 0; i < args.length; i++) {
2115                     if (copyArg[i]) {
2116                         result[i] = getVariableName(result[i]+"Copy");
2117                         p.pln( getName(args[i]) + " " + result[i] + " = (" + getName(args[i]) + ") " +
2118                                arrayName + "[" + copyIndex++ +"];");
2119                     }
2120                 }
2121             } else {
2122                 // Generate a call to copyObject, updating the result
2123                 // with the new local parameter name...
2124                 result[firstCopiedArg] = getVariableName(result[firstCopiedArg]+"Copy");
2125                 p.pln( getName(args[firstCopiedArg]) + " " + result[firstCopiedArg] + " = (" +
2126                        getName(args[firstCopiedArg]) + ") Util.copyObject(" +
2127                        origNames[firstCopiedArg] + ",_orb());");
2128             }
2129         }
2130 
2131         return result;
2132     }
2133 
2134     static final String SINGLE_SLASH = "\\";
2135     static final String DOUBLE_SLASH = SINGLE_SLASH + SINGLE_SLASH;
2136 
2137     String getRepositoryID(Type type) {
2138         return IDLNames.replace(type.getRepositoryID(), SINGLE_SLASH, DOUBLE_SLASH);
2139     }
2140 
2141     String getExceptionRepositoryID(Type type) {
2142         ClassType theType = (ClassType) type;
2143         return IDLNames.getIDLRepositoryID(theType.getQualifiedIDLExceptionName(false));
2144     }
2145 
2146     String getVariableName(String proposed) {
2147         while (namesInUse.contains(proposed)) {
2148             proposed = "$" + proposed;
2149         }
2150 
2151         return proposed;
2152     }
2153 
2154     void addNamesInUse(CompoundType.Method[] methods) {
2155         for (int i = 0; i < methods.length; i++) {
2156             addNamesInUse(methods[i]);
2157         }
2158     }
2159 
2160     void addNamesInUse(CompoundType.Method method) {
2161         String paramNames[] = method.getArgumentNames();
2162         for (int i = 0; i < paramNames.length; i++) {
2163             addNameInUse(paramNames[i]);
2164         }
2165     }
2166 
2167     void addNameInUse(String name) {
2168         namesInUse.add(name);
2169     }
2170 
2171     static boolean mustCopy(Type type) {
2172         switch (type.getTypeCode()) {
2173         case TYPE_VOID:
2174         case TYPE_BOOLEAN:
2175         case TYPE_BYTE:
2176         case TYPE_CHAR:
2177         case TYPE_SHORT:
2178         case TYPE_INT:
2179         case TYPE_LONG:
2180         case TYPE_FLOAT:
2181         case TYPE_DOUBLE:
2182         case TYPE_STRING:           return false;
2183 
2184         case TYPE_ANY:              return true;
2185 
2186         case TYPE_CORBA_OBJECT:     return false;
2187 
2188         case TYPE_REMOTE:
2189         case TYPE_ABSTRACT:
2190         case TYPE_NC_INTERFACE:
2191         case TYPE_VALUE:
2192         case TYPE_IMPLEMENTATION:
2193         case TYPE_NC_CLASS:
2194         case TYPE_ARRAY:
2195         case TYPE_JAVA_RMI_REMOTE:  return true;
2196 
2197         default: throw new Error("unexpected type code: " + type.getTypeCode());
2198         }
2199     }
2200 
2201     ValueType[] getStubExceptions (CompoundType.Method method, boolean sort) {
2202 
2203         ValueType[] list = method.getFilteredStubExceptions(method.getExceptions());
2204 
2205         // Sort the list so that all org.omg.CORBA.UserException
2206         // subtypes are at the beginning of the list.  This ensures
2207         // that the stub will not call read_string() before calling
2208         // XXHelper.read().
2209 
2210         if (sort) {
2211             Arrays.sort(list,new UserExceptionComparator());
2212             }
2213 
2214         return list;
2215                 }
2216 
2217     ValueType[] getTieExceptions (CompoundType.Method method) {
2218         return method.getUniqueCatchList(method.getImplExceptions());
2219     }
2220 
2221     void writeTieMethod(IndentingWriter p, CompoundType type,
2222                         CompoundType.Method method) throws IOException {
2223         String methodName = method.getName();
2224         Type paramTypes[] = method.getArguments();
2225         String paramNames[] = method.getArgumentNames();
2226         Type returnType = method.getReturnType();
2227         ValueType[] exceptions = getTieExceptions(method);
2228         String in = getVariableName("in");
2229         String ex = getVariableName("ex");
2230         String out = getVariableName("out");
2231         String reply = getVariableName("reply");
2232 
2233         for (int i = 0; i < paramTypes.length; i++) {
2234             p.p(getName(paramTypes[i])+" "+paramNames[i]+" = ");
2235             writeUnmarshalArgument(p, in, paramTypes[i], null);
2236             p.pln();
2237         }
2238 
2239         boolean handleExceptions = exceptions != null;
2240         boolean doReturn = !returnType.isType(TYPE_VOID);
2241 
2242         if (handleExceptions && doReturn) {
2243             String objName = testUtil(getName(returnType), returnType);
2244             p.pln(objName+" result;");
2245         }
2246 
2247         if (handleExceptions)
2248             p.plnI("try {");
2249 
2250         if (doReturn) {
2251             if (handleExceptions) {
2252                 p.p("result = ");
2253             } else {
2254                 p.p(getName(returnType)+" result = ");
2255             }
2256         }
2257 
2258         p.p("target."+methodName+"(");
2259         for(int i = 0; i < paramNames.length; i++) {
2260             if (i > 0)
2261                 p.p(", ");
2262             p.p(paramNames[i]);
2263         }
2264         p.pln(");");
2265 
2266         if (handleExceptions) {
2267             for(int i = 0; i < exceptions.length; i++) {
2268                 p.pOlnI("} catch ("+getName(exceptions[i])+" "+ex+") {");
2269 
2270                 // Is this our IDLEntity Exception special case?
2271 
2272                 if (exceptions[i].isIDLEntityException() && !exceptions[i].isCORBAUserException()) {
2273 
2274                                 // Yes...
2275 
2276                     String helperName = IDLNames.replace(exceptions[i].getQualifiedIDLName(false),"::",".");
2277                     helperName += "Helper";
2278                     p.pln(idOutputStream+" "+out +" = "+reply+".createExceptionReply();");
2279                     p.pln(helperName+".write("+out+","+ex+");");
2280 
2281                 } else {
2282 
2283                                 // No...
2284 
2285                     p.pln("String id = \"" + getExceptionRepositoryID(exceptions[i]) + "\";");
2286                 p.plnI(idExtOutputStream + " "+out+" = ");
2287                 p.pln("(" + idExtOutputStream + ") "+reply+".createExceptionReply();");
2288                 p.pOln(out+".write_string(id);");
2289                     p.pln(out+".write_value("+ex+"," + getName(exceptions[i]) + ".class);");
2290                 }
2291 
2292                 p.pln("return "+out+";");
2293             }
2294             p.pOln("}");
2295         }
2296 
2297         if (needNewWriteStreamClass(returnType)) {
2298             p.plnI(idExtOutputStream + " "+out+" = ");
2299             p.pln("(" + idExtOutputStream + ") "+reply+".createReply();");
2300             p.pO();
2301         } else {
2302             p.pln("OutputStream "+out+" = "+reply+".createReply();");
2303         }
2304 
2305         if (doReturn) {
2306             writeMarshalArgument(p, out, returnType, "result");
2307             p.pln();
2308         }
2309 
2310         p.pln("return "+out+";");
2311     }
2312 
2313 
2314     /**
2315      * Write Java statements to marshal a series of values in order as
2316      * named in the "names" array, with types as specified in the "types"
2317      * array", to the java.io.ObjectOutput stream named "stream".
2318      */
2319     void writeMarshalArguments(IndentingWriter p,
2320                                String streamName,
2321                                Type[] types, String[] names)
2322         throws IOException
2323     {
2324         if (types.length != names.length) {
2325             throw new Error("paramter type and name arrays different sizes");
2326         }
2327 
2328         for (int i = 0; i < types.length; i++) {
2329             writeMarshalArgument(p, streamName, types[i], names[i]);
2330             if (i != types.length -1) {
2331                 p.pln();
2332             }
2333         }
2334     }
2335 
2336     /**
2337      * Added for IASRI 4987274. Remote classes named "Util" were
2338      * getting confused with javax.rmi.CORBA.Util and the
2339      * unqualifiedName "Util".
2340      */
2341     String testUtil(String objectName, Type ttype) {
2342         if (objectName.equals("Util")) {
2343                 String correctedName = (String)ttype.getPackageName() + "." + objectName;
2344                 return correctedName;
2345         } else {
2346                 return objectName;
2347         }
2348     }
2349 }
2350 
2351 class StringComparator implements java.util.Comparator {
2352     public int compare(Object o1, Object o2) {
2353         String s1 = (String)o1;
2354         String s2 = (String)o2;
2355         return s1.compareTo(s2);
2356     }
2357 }
2358 
2359 
2360 class UserExceptionComparator implements java.util.Comparator {
2361     public int compare(Object o1, Object o2) {
2362         ValueType v1 = (ValueType)o1;
2363         ValueType v2 = (ValueType)o2;
2364         int result = 0;
2365         if (isUserException(v1)) {
2366             if (!isUserException(v2)) {
2367                 result = -1;
2368             }
2369         } else if (isUserException(v2)) {
2370             if (!isUserException(v1)) {
2371                 result = 1;
2372             }
2373         }
2374         return result;
2375     }
2376 
2377     final boolean isUserException(ValueType it) {
2378         return it.isIDLEntityException() && !it.isCORBAUserException();
2379     }
2380 }