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      */
StubGenerator()90     public StubGenerator() {
91     }
92 
93     /**
94      * Overridden in order to set the standardPackage flag.
95      */
generate( sun.rmi.rmic.BatchEnvironment env, ClassDefinition cdef, File destDir)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      */
requireNewInstance()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      */
parseNonConforming(ContextStack stack)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      */
getTopType(ClassDefinition cdef, ContextStack stack)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      */
parseArgs(String argv[], Main main)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      */
getOutputTypesFor(CompoundType topType, HashSet alreadyChecked)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      */
getFileNameExtensionFor(OutputType outputType)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      */
writeOutputFor( OutputType outputType, HashSet alreadyChecked, IndentingWriter writer)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      */
writeStub(OutputType outputType, IndentingWriter p)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 
addClassInUse(String qualifiedName)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 
addClassInUse(Type type)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 
addClassInUse(Type[] types)576     void addClassInUse(Type[] types) {
577         for (int i = 0; i < types.length; i++) {
578             addClassInUse(types[i]);
579         }
580     }
581 
addStubInUse(Type type)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 
getStubNameFor(Type type, boolean qualified)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 
addStubInUse(Type[] types)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 
addClassInUse(String unqualifiedName, String qualifiedName, String packageName)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 
getName(Type type)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
getExceptionName(Type type)737     String getExceptionName(Type type) {
738         Identifier id = type.getIdentifier();
739         return IDLNames.replace(id.toString(),". ",".");
740     }
741 
getName(String qualifiedName)742     String getName(String qualifiedName) {
743         return (String)classesInUse.get(qualifiedName);
744     }
745 
getName(Identifier id)746     String getName(Identifier id) {
747         return getName(id.toString());
748     }
749 
getStubName(Type type)750     String getStubName(Type type) {
751         String stubName = getStubNameFor(type,true);
752         return getName(stubName);
753     }
754 
setStandardClassesInUse(CompoundType type, boolean stub)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 
addClassesInUse(CompoundType type, RemoteType[] interfaces)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 
writePackageAndImports(IndentingWriter p)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 
implementsRemote(CompoundType theType)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 
writeStubMethod( IndentingWriter p, CompoundType.Method method, CompoundType theType)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 
writeLocalStubMethodBody(IndentingWriter p, CompoundType.Method method, CompoundType theType)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 
writeNonLocalStubMethodBody( IndentingWriter p, CompoundType.Method method, CompoundType theType)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 
allocateResult(IndentingWriter p, Type returnType)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 
getTypeCode(Type type)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      */
writeMarshalArgument(IndentingWriter p, String streamName, Type type, String name)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      */
writeUnmarshalArgument(IndentingWriter p, String streamName, Type type, String name)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      */
getAllRemoteRepIDs(CompoundType theType)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      */
collectAllRemoteInterfaces(CompoundType theType)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      */
addRemoteInterfaces(Vector list, CompoundType theType)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      */
getDirectRemoteInterfaces(CompoundType theType)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 
countRemote(Type[] list, boolean includeAbstract)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 
writeCastArray(IndentingWriter p)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     }
writeIds(IndentingWriter p, CompoundType theType, boolean isTie )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      */
writeTie(OutputType outputType, IndentingWriter p)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     }
catchWrongPolicy(IndentingWriter p)1875     public void catchWrongPolicy(IndentingWriter p) throws IOException {
1876         p.pln("");
1877     }
catchServantNotActive(IndentingWriter p)1878     public void catchServantNotActive(IndentingWriter p) throws IOException {
1879         p.pln("");
1880     }
catchObjectNotActive(IndentingWriter p)1881     public void catchObjectNotActive(IndentingWriter p) throws IOException {
1882         p.pln("");
1883     }
1884 
write_tie_thisObject_method(IndentingWriter p, Identifier idCorbaObject)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 
write_tie_deactivate_method(IndentingWriter p)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 
write_tie_orb_method(IndentingWriter p)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 
write_tie__ids_method(IndentingWriter p)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 
getStringsHash(CompoundType.Method[] methods)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 
needNewReadStreamClass(Type type)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 
needNewWriteStreamClass(Type type)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      */
writeCopyArguments(CompoundType.Method method, IndentingWriter p)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 
getRepositoryID(Type type)2137     String getRepositoryID(Type type) {
2138         return IDLNames.replace(type.getRepositoryID(), SINGLE_SLASH, DOUBLE_SLASH);
2139     }
2140 
getExceptionRepositoryID(Type type)2141     String getExceptionRepositoryID(Type type) {
2142         ClassType theType = (ClassType) type;
2143         return IDLNames.getIDLRepositoryID(theType.getQualifiedIDLExceptionName(false));
2144     }
2145 
getVariableName(String proposed)2146     String getVariableName(String proposed) {
2147         while (namesInUse.contains(proposed)) {
2148             proposed = "$" + proposed;
2149         }
2150 
2151         return proposed;
2152     }
2153 
addNamesInUse(CompoundType.Method[] methods)2154     void addNamesInUse(CompoundType.Method[] methods) {
2155         for (int i = 0; i < methods.length; i++) {
2156             addNamesInUse(methods[i]);
2157         }
2158     }
2159 
addNamesInUse(CompoundType.Method method)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 
addNameInUse(String name)2167     void addNameInUse(String name) {
2168         namesInUse.add(name);
2169     }
2170 
mustCopy(Type type)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 
getStubExceptions(CompoundType.Method method, boolean sort)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 
getTieExceptions(CompoundType.Method method)2217     ValueType[] getTieExceptions (CompoundType.Method method) {
2218         return method.getUniqueCatchList(method.getImplExceptions());
2219     }
2220 
writeTieMethod(IndentingWriter p, CompoundType type, CompoundType.Method method)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      */
writeMarshalArguments(IndentingWriter p, String streamName, Type[] types, String[] names)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      */
testUtil(String objectName, Type ttype)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 {
compare(Object o1, Object o2)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 {
compare(Object o1, Object o2)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 
isUserException(ValueType it)2377     final boolean isUserException(ValueType it) {
2378         return it.isIDLEntityException() && !it.isCORBAUserException();
2379     }
2380 }
2381