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