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