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 33package sun.rmi.rmic.iiop; 34 35import java.util.Arrays; 36import java.util.Vector; 37import sun.tools.java.Identifier; 38import sun.tools.java.ClassNotFound; 39import sun.tools.java.ClassDefinition; 40import sun.tools.java.ClassDeclaration; 41import sun.tools.java.MemberDefinition; 42import sun.tools.java.CompilerError; 43import sun.tools.tree.Node; 44import sun.tools.tree.LocalMember; 45import sun.tools.tree.CharExpression; 46import sun.tools.tree.IntegerExpression; 47import sun.rmi.rmic.IndentingWriter; 48import java.io.IOException; 49import java.util.HashSet; 50import java.util.Enumeration; 51import java.io.File; 52 53/** 54 * A CompoundType is an abstract base class for all IIOP class and 55 * interface types. 56 * 57 * @author Bryan Atsatt 58 */ 59public abstract class CompoundType extends Type { 60 61 protected Method[] methods; 62 protected InterfaceType[] interfaces; 63 protected Member[] members; 64 protected ClassDefinition classDef; 65 protected ClassDeclaration classDecl; 66 67 protected boolean isCORBAObject = false; 68 protected boolean isIDLEntity = false; 69 protected boolean isAbstractBase = false; 70 protected boolean isValueBase = false; 71 protected boolean isCORBAUserException = false; 72 protected boolean isException = false; 73 protected boolean isCheckedException = false; 74 protected boolean isRemoteExceptionOrSubclass = false; 75 protected String idlExceptionName; 76 protected String qualifiedIDLExceptionName; 77 78 //_____________________________________________________________________ 79 // Public Interfaces 80 //_____________________________________________________________________ 81 82 /** 83 * Return true if this type implements 84 * org.omg.CORBA.Object. 85 */ 86 public boolean isCORBAObject () { 87 return isCORBAObject; 88 } 89 90 /** 91 * Return true if this type implements 92 * org.omg.CORBA.portable.IDLEntity. 93 */ 94 public boolean isIDLEntity () { 95 return isIDLEntity; 96 } 97 98 /** 99 * Return true if this type implements 100 * org.omg.CORBA.portable.ValueBase. 101 */ 102 public boolean isValueBase () { 103 return isValueBase; 104 } 105 106 /** 107 * Return true if this type is a CORBA 108 * abstract interface. 109 */ 110 public boolean isAbstractBase () { 111 return isAbstractBase; 112 } 113 114 /** 115 * Return true if this type is an exception. 116 */ 117 public boolean isException () { 118 return isException; 119 } 120 121 /** 122 * Return true if this type is a "checked" exception. 123 * Result if valid iff isException() returns true. 124 */ 125 public boolean isCheckedException () { 126 return isCheckedException; 127 } 128 129 /** 130 * Return true if this type is a java.rmi.RemoteException 131 * or one of its subclasses. Result if valid iff isException() 132 * returns true. 133 */ 134 public boolean isRemoteExceptionOrSubclass () { 135 return isRemoteExceptionOrSubclass; 136 } 137 138 /** 139 * Return true if this type is exactly 140 * org.omg.CORBA.UserException. 141 */ 142 public boolean isCORBAUserException () { 143 return isCORBAUserException; 144 } 145 146 /** 147 * Return true if this type implements 148 * {@code isIDLEntity() && isException()}. 149 */ 150 public boolean isIDLEntityException () { 151 return isIDLEntity() && isException(); 152 } 153 /** 154 * Return true if {@code isIDLEntity() && !isValueBase() 155 * && !isAbstractBase() && !isCORBAObject() 156 * && !isIDLEntityException()}. 157 */ 158 public boolean isBoxed () { 159 return (isIDLEntity() && !isValueBase() && 160 !isAbstractBase() && !isCORBAObject() && 161 !isIDLEntityException()); 162 } 163 164 /** 165 * If this type represents an exception, return the 166 * IDL name including the "Ex" mangling, otherwise 167 * return null. 168 */ 169 public String getIDLExceptionName () { 170 return idlExceptionName; 171 } 172 173 /** 174 * If this type represents an exception, return the 175 * qualified IDL name including the "Ex" mangling, 176 * otherwise return null. 177 * @param global If true, prepends "::". 178 */ 179 public String getQualifiedIDLExceptionName (boolean global) { 180 if (qualifiedIDLExceptionName != null && 181 global && 182 getIDLModuleNames().length > 0) { 183 return IDL_NAME_SEPARATOR + qualifiedIDLExceptionName; 184 } else { 185 return qualifiedIDLExceptionName; 186 } 187 } 188 189 /** 190 * Return signature for this type (e.g. com.acme.Dynamite 191 * would return "com.acme.Dynamite", byte = "B") 192 */ 193 public String getSignature() { 194 String sig = classDecl.getType().getTypeSignature(); 195 if (sig.endsWith(";")) { 196 sig = sig.substring(0,sig.length()-1); 197 } 198 return sig; 199 } 200 201 /** 202 * Return the ClassDeclaration for this type. 203 */ 204 public ClassDeclaration getClassDeclaration() { 205 return classDecl; 206 } 207 208 /** 209 * Return the ClassDefinition for this type. 210 */ 211 public ClassDefinition getClassDefinition() { 212 return classDef; 213 } 214 215 /** 216 * Return the parent class of this type. Returns null if this 217 * type is an interface or if there is no parent. 218 */ 219 public ClassType getSuperclass() { 220 return null; 221 } 222 223 /** 224 * Return an array of interfaces directly implemented by this type. 225 * <p> 226 * The order of the array returned is arbitrary. 227 */ 228 public InterfaceType[] getInterfaces() { 229 if( interfaces != null ) { 230 return (InterfaceType[]) interfaces.clone(); 231 } 232 return null; 233 } 234 235 /** 236 * Return an array of Type.Method objects representing all 237 * of the methods implemented directly by this type. 238 */ 239 public Method[] getMethods() { 240 if( methods != null ) { 241 return (Method[]) methods.clone(); 242 } 243 return null; 244 } 245 246 /** 247 * Return an array of Type.Member objects representing all of 248 * the data members directly implemented by this interface. 249 */ 250 public Member[] getMembers() { 251 if( members != null ) { 252 return (Member[]) members.clone(); 253 } 254 return null; 255 } 256 257 /** 258 * Create a CompoundType object for the given class. 259 * 260 * If the class is not a properly formed or if some other error occurs, the 261 * return value will be null, and errors will have been reported to the 262 * supplied BatchEnvironment. 263 */ 264 public static CompoundType forCompound (ClassDefinition classDef, 265 ContextStack stack) { 266 CompoundType result = null; 267 268 try { 269 result = (CompoundType) makeType(classDef.getType(),classDef,stack); 270 } catch (ClassCastException e) {} 271 272 return result; 273 } 274 275 276 //_____________________________________________________________________ 277 // Subclass/Internal Interfaces 278 //_____________________________________________________________________ 279 280 /** 281 * Release all resources. 282 */ 283 protected void destroy () { 284 if (!destroyed) { 285 super.destroy(); 286 287 if (methods != null) { 288 for (int i = 0; i < methods.length; i++) { 289 if (methods[i] != null) methods[i].destroy(); 290 } 291 methods = null; 292 } 293 294 if (interfaces != null) { 295 for (int i = 0; i < interfaces.length; i++) { 296 if (interfaces[i] != null) interfaces[i].destroy(); 297 } 298 interfaces = null; 299 } 300 301 if (members != null) { 302 for (int i = 0; i < members.length; i++) { 303 if (members[i] != null) members[i].destroy(); 304 } 305 members = null; 306 } 307 308 classDef = null; 309 classDecl = null; 310 } 311 } 312 313 /* 314 * Load a Class instance. Return null if fail. 315 */ 316 protected Class loadClass() { 317 318 Class ourClass = null; 319 320 // To avoid getting out-of-date Class instances, and 321 // to ensure that there is an instance, we must compile 322 // any classes that we've seen and which are not yet 323 // compiled. We can't just compile this class, 'cuz it 324 // may have dependencies on classes which have not been 325 // compiled... 326 327 try { 328 env.getMain().compileAllClasses(env); 329 } catch (Exception e1) { 330 for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) { 331 ClassDeclaration c = (ClassDeclaration)e.nextElement(); 332 } 333 failedConstraint(26,false,stack,"required classes"); 334 env.flushErrors(); 335 } 336 337 // Now try to get the Class... 338 // The outer try block is there for people who might want to use 339 // the compiler at run-time of their AS. 340 // They could set and use their own context class loader for loading 341 // classes directly. 342 try { 343 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 344 ourClass = cl.loadClass(getQualifiedName()); 345 } catch(ClassNotFoundException cfe) { 346 347 try { 348 ourClass = env.classPathLoader.loadClass(getQualifiedName()); 349 } catch (NullPointerException e) { 350 // This should never happen 351 } catch (ClassNotFoundException e) { 352 // Fall through to the next case (which is to look in the 353 // output directory for generated files) 354 } 355 } 356 357 /* This piece of code used to cause the compiler to ignore jar files 358 on its classpath 359 try { 360 ourClass = Util.loadClass(getQualifiedName(),null,null); 361 } catch (ClassNotFoundException e) { 362 } catch (LinkageError e) { 363 } 364 */ 365 366 if (ourClass == null) { 367 368 // Try one last thing. If the class was compiled into 369 // a directory that's not in the classpath, the load 370 // will fail. Let's get the bits off the disk and load 371 // it directly... 372 373 if (env.loader == null) { 374 File destDir = env.getMain().getDestinationDir(); 375 if (destDir == null) { 376 destDir = new File("."); 377 } 378 env.loader = new DirectoryLoader(destDir); 379 } 380 381 try { 382 ourClass = env.loader.loadClass(getQualifiedName()); 383 } catch (Exception e) {} 384 } 385 386 return ourClass; 387 } 388 389 // Print "extends XX" 390 391 protected boolean printExtends (IndentingWriter writer, 392 boolean useQualifiedNames, 393 boolean useIDLNames, 394 boolean globalIDLNames) throws IOException { 395 396 ClassType parent = getSuperclass(); 397 398 if (parent != null && (!useIDLNames || 399 (!parent.isType(TYPE_ANY) && !parent.isType(TYPE_CORBA_OBJECT)))) { 400 writer.p(" extends "); 401 parent.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 402 return true; 403 } 404 return false; 405 } 406 407 // Print "implements XX, YY" 408 409 protected void printImplements (IndentingWriter writer, 410 String prefix, 411 boolean useQualifiedNames, 412 boolean useIDLNames, 413 boolean globalIDLNames) throws IOException { 414 415 InterfaceType[] interfaces = getInterfaces(); 416 417 String adjective = " implements"; 418 419 if (isInterface()) { 420 adjective = " extends"; 421 } 422 423 if (useIDLNames) { 424 adjective = ":"; 425 } 426 427 for (int i = 0; i < interfaces.length; i++) { 428 if (!useIDLNames || (!interfaces[i].isType(TYPE_ANY) && !interfaces[i].isType(TYPE_CORBA_OBJECT))) { 429 if (i == 0) { 430 writer.p(prefix + adjective + " "); 431 } else { 432 writer.p(", "); 433 } 434 interfaces[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 435 } 436 } 437 } 438 439 // Print members 440 441 protected void printMembers ( IndentingWriter writer, 442 boolean useQualifiedNames, 443 boolean useIDLNames, 444 boolean globalIDLNames) throws IOException { 445 446 CompoundType.Member[] members = getMembers(); 447 448 for (int i = 0; i < members.length; i++) { 449 if (!members[i].isInnerClassDeclaration()) { 450 Type it = members[i].getType(); 451 String visibility = members[i].getVisibility(); 452 String name; 453 454 if (useIDLNames) { 455 name = members[i].getIDLName(); 456 } else { 457 name = members[i].getName(); 458 } 459 460 String value = members[i].getValue(); 461 462 writer.p(visibility); 463 if (visibility.length() > 0) { 464 writer.p(" "); 465 } 466 it.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 467 writer.p(" " + name); 468 469 if (value != null) { 470 writer.pln(" = " + value + ";"); 471 } else { 472 writer.pln(";"); 473 } 474 } 475 } 476 } 477 478 // Print methods 479 480 protected void printMethods ( IndentingWriter writer, 481 boolean useQualifiedNames, 482 boolean useIDLNames, 483 boolean globalIDLNames) throws IOException { 484 485 CompoundType.Method[] methods = getMethods(); 486 487 for (int m = 0; m < methods.length; m++) { 488 CompoundType.Method theMethod = methods[m]; 489 printMethod(theMethod,writer,useQualifiedNames,useIDLNames,globalIDLNames); 490 } 491 } 492 493 // Print a method... 494 495 protected void printMethod (CompoundType.Method it, 496 IndentingWriter writer, 497 boolean useQualifiedNames, 498 boolean useIDLNames, 499 boolean globalIDLNames) throws IOException { 500 501 502 // Write visibility... 503 504 String visibility = it.getVisibility(); 505 506 writer.p(visibility); 507 if (visibility.length() > 0) { 508 writer.p(" "); 509 } 510 511 // Write return type... 512 513 it.getReturnType().printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 514 515 // Write method name... 516 517 if (useIDLNames) { 518 writer.p(" " + it.getIDLName()); 519 } else { 520 writer.p(" " + it.getName()); 521 } 522 523 // Write arguments... 524 525 writer.p(" ("); 526 Type[] args = it.getArguments(); 527 String[] argNames = it.getArgumentNames(); 528 529 for (int i = 0; i < args.length; i++) { 530 if (i > 0) { 531 writer.p(", "); 532 } 533 534 if (useIDLNames) { 535 writer.p("in "); 536 } 537 538 args[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 539 writer.p(" " + argNames[i]); 540 } 541 writer.p(")"); 542 543 // Write exceptions... 544 545 ClassType[] exceptions; 546 547 if (isType(TYPE_IMPLEMENTATION)) { 548 exceptions = it.getImplExceptions(); 549 } else { 550 exceptions = it.getExceptions(); 551 } 552 553 for (int i = 0; i < exceptions.length; i++) { 554 if (i == 0) { 555 if (useIDLNames) { 556 writer.p(" raises ("); 557 } else { 558 writer.p(" throws "); 559 } 560 } else { 561 writer.p(", "); 562 } 563 564 if (useIDLNames) { 565 if (useQualifiedNames) { 566 writer.p(exceptions[i].getQualifiedIDLExceptionName(globalIDLNames)); 567 } else { 568 writer.p(exceptions[i].getIDLExceptionName()); 569 } 570 writer.p(" [a.k.a. "); 571 exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 572 writer.p("]"); 573 } else { 574 exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); 575 } 576 } 577 578 if (useIDLNames && exceptions.length > 0) { 579 writer.p(")"); 580 } 581 582 if (it.isInherited()) { 583 writer.p(" // Inherited from "); 584 writer.p(it.getDeclaredBy()); 585 } 586 587 writer.pln(";"); 588 } 589 590 /** 591 * Create a CompoundType instance for the given class. NOTE: This constructor 592 * is ONLY for SpecialClassType and SpecialInterfaceType. 593 */ 594 protected CompoundType(ContextStack stack, int typeCode, ClassDefinition classDef) { 595 super(stack,typeCode); 596 this.classDef = classDef; 597 classDecl = classDef.getClassDeclaration(); 598 interfaces = new InterfaceType[0]; 599 methods = new Method[0]; 600 members = new Member[0]; 601 602 // If we are an inner class/interface, reset the type codes... 603 604 if (classDef.isInnerClass()) { 605 setTypeCode(typeCode | TM_INNER); 606 } 607 608 // Set special flags... 609 610 setFlags(); 611 } 612 613 private void setFlags() { 614 615 try { 616 617 // Set our special interface flags... 618 619 isCORBAObject = env.defCorbaObject.implementedBy(env,classDecl); 620 isIDLEntity = env.defIDLEntity.implementedBy(env,classDecl); 621 isValueBase = env.defValueBase.implementedBy(env,classDecl); 622 isAbstractBase = isInterface() && // Interface, not a class. 623 isIDLEntity && // Implements IDLEntity. 624 !isValueBase && // Does not implement ValueBase. 625 !isCORBAObject; // Does not implement org.omg.CORBA.Object; 626 isCORBAUserException = (classDecl.getName() == idCorbaUserException); 627 628 // Is this an exception? 629 630 if (env.defThrowable.implementedBy(env, classDecl)) { 631 632 // Yes... 633 634 isException = true; 635 636 // Is it a checked exception? 637 638 if (env.defRuntimeException.implementedBy(env,classDecl) || 639 env.defError.implementedBy(env,classDecl)) { 640 isCheckedException = false; 641 } else { 642 isCheckedException = true; 643 } 644 645 // Is it java.rmi.RemoteException or a subclass? 646 647 if (env.defRemoteException.implementedBy(env,classDecl)) { 648 isRemoteExceptionOrSubclass = true; 649 } else { 650 isRemoteExceptionOrSubclass = false; 651 } 652 } else { 653 isException = false; 654 } 655 } catch (ClassNotFound e) { 656 classNotFound(stack,e); 657 } 658 } 659 660 /** 661 * Create a CompoundType instance for the given class. The resulting 662 * object is not yet completely initialized. 663 */ 664 protected CompoundType(ContextStack stack, ClassDefinition classDef, 665 int typeCode) { 666 super(stack,typeCode); 667 this.classDef = classDef; 668 classDecl = classDef.getClassDeclaration(); 669 670 // If we are an inner class/interface, reset the type codes... 671 672 if (classDef.isInnerClass()) { 673 setTypeCode(typeCode | TM_INNER); 674 } 675 676 // Set special flags... 677 678 setFlags(); 679 680 // Set names... 681 682 Identifier id = classDef.getName(); 683 String idlName; 684 String[] idlModuleNames; 685 686 try { 687 688 // These can fail if we get case-sensitive name matches... 689 690 idlName = IDLNames.getClassOrInterfaceName(id,env); 691 idlModuleNames = IDLNames.getModuleNames(id,isBoxed(),env); 692 693 setNames(id,idlModuleNames,idlName); 694 695 // Is this an exception? 696 697 if (isException()) { 698 699 // Yes, so set our mangled exception names... 700 701 isException = true; 702 idlExceptionName = IDLNames.getExceptionName(getIDLName()); 703 qualifiedIDLExceptionName = 704 IDLNames.getQualifiedName(getIDLModuleNames(),idlExceptionName); 705 } 706 707 // Set interfaces, methods and members... 708 709 interfaces = null; // set in initialize() 710 methods = null; // set in initialize() 711 members = null; // set in initialize() 712 713 } catch (Exception e) { 714 failedConstraint(7,false,stack,id.toString(),e.getMessage()); 715 throw new CompilerError(""); 716 } 717 } 718 719 /** 720 * Initialize this instance. 721 */ 722 protected boolean initialize ( Vector directInterfaces, 723 Vector directMethods, 724 Vector directMembers, 725 ContextStack stack, 726 boolean quiet) { 727 728 boolean result = true; 729 730 // Initialize our arrays... 731 732 if (directInterfaces != null && directInterfaces.size() > 0) { 733 interfaces = new InterfaceType[directInterfaces.size()]; 734 directInterfaces.copyInto(interfaces); 735 } else { 736 interfaces = new InterfaceType[0]; 737 } 738 739 if (directMethods != null && directMethods.size() > 0) { 740 methods = new Method[directMethods.size()]; 741 directMethods.copyInto(methods); 742 743 // Now set the idl names for each... 744 745 try { 746 IDLNames.setMethodNames(this, methods,env); 747 } catch (Exception e) { 748 failedConstraint(13,quiet,stack,getQualifiedName(),e.getMessage()); 749 result = false; 750 } 751 752 } else { 753 methods = new Method[0]; 754 } 755 756 if (directMembers != null && directMembers.size() > 0) { 757 members = new Member[directMembers.size()]; 758 directMembers.copyInto(members); 759 760 // If we have any un-initialized inner classes, now is the time 761 // to init them... 762 763 for (int i = 0; i < members.length; i++) { 764 if (members[i].isInnerClassDeclaration()) { 765 try { 766 members[i].init(stack,this); 767 } catch (CompilerError e) { 768 return false; 769 } 770 } 771 } 772 773 // Now set the idl names for each... 774 775 try { 776 IDLNames.setMemberNames(this, members,methods,env); 777 } catch (Exception e) { 778 int constraint = classDef.isInterface() ? 19 : 20; 779 failedConstraint(constraint,quiet,stack,getQualifiedName(),e.getMessage()); 780 result = false; 781 } 782 783 } else { 784 members = new Member[0]; 785 } 786 787 // Set our repositoryID... 788 789 if (result) { 790 result = setRepositoryID(); 791 } 792 793 return result; 794 } 795 796 /* 797 * Return Type or null if error. classDef may be null. 798 */ 799 protected static Type makeType (sun.tools.java.Type theType, 800 ClassDefinition classDef, 801 ContextStack stack) { 802 803 if (stack.anyErrors()) return null; 804 805 // See if we can find this type in the cache. If so, return it... 806 807 String key = theType.toString(); 808 809 Type result = getType(key,stack); 810 811 if (result != null) { 812 return result; 813 } 814 815 // Gotta try with context... 816 817 result = getType(key + stack.getContextCodeString(),stack); 818 819 if (result != null) { 820 return result; 821 } 822 823 // Gotta map it... 824 825 BatchEnvironment env = stack.getEnv(); 826 int typeCode = theType.getTypeCode(); 827 switch (typeCode) { 828 case TC_BOOLEAN: 829 case TC_BYTE: 830 case TC_CHAR: 831 case TC_SHORT: 832 case TC_INT: 833 case TC_LONG: 834 case TC_FLOAT: 835 case TC_DOUBLE: 836 { 837 // Primitive... 838 839 result = PrimitiveType.forPrimitive(theType,stack); 840 break; 841 } 842 843 case TC_ARRAY: 844 { 845 // Array. 846 847 result = ArrayType.forArray(theType,stack); 848 break; 849 } 850 851 case TC_CLASS: 852 { 853 try { 854 // First, make sure we have the class definition... 855 856 ClassDefinition theClass = classDef; 857 858 if (theClass == null) { 859 theClass = env.getClassDeclaration(theType).getClassDefinition(env); 860 } 861 862 // Is it an interface or a class? 863 864 if (theClass.isInterface()) { 865 866 // An interface. Is it a special case? 867 868 result = SpecialInterfaceType.forSpecial(theClass,stack); 869 870 if (result == null) { 871 872 // No, does it implement java.rmi.Remote? 873 874 if (env.defRemote.implementedBy(env,theClass.getClassDeclaration())) { 875 876 // Yep, so just see if we can create an instance of RemoteType 877 // from it... 878 879 boolean parentIsValue = stack.isParentAValue(); 880 result = RemoteType.forRemote(theClass,stack,parentIsValue); 881 882 // If we did not succeed AND we are in a value context, then 883 // go ahead and make an NC type out of it... 884 885 if (result == null && parentIsValue) { 886 result = NCInterfaceType.forNCInterface(theClass,stack); 887 } 888 } else { 889 890 // Nope, is it an AbstractType? 891 892 result = AbstractType.forAbstract(theClass,stack,true); 893 894 if (result == null) { 895 896 // No, so treat it as a non-conforming interface type... 897 898 result = NCInterfaceType.forNCInterface(theClass,stack); 899 } 900 } 901 } 902 } else { 903 904 // A class. Is it a special case? 905 906 result = SpecialClassType.forSpecial(theClass,stack); 907 908 if (result == null) { 909 910 ClassDeclaration classDecl = theClass.getClassDeclaration(); 911 912 // Nope, does it implement java.rmi.Remote? 913 914 if (env.defRemote.implementedBy(env,classDecl)) { 915 916 // Yep, so just see if we can create an instance of 917 // ImplementationType from it... 918 919 boolean parentIsValue = stack.isParentAValue(); 920 result = ImplementationType.forImplementation(theClass,stack,parentIsValue); 921 922 // If we did not succeed AND inValue is true, then 923 // go ahead and make an NC type out of it... 924 925 if (result == null && parentIsValue) { 926 result = NCClassType.forNCClass(theClass,stack); 927 } 928 } else { 929 930 // No, does it implement Serializable? 931 932 if (env.defSerializable.implementedBy(env,classDecl)) { 933 934 // Yep, so just see if we can create an instance of ValueType 935 // from it... 936 937 result = ValueType.forValue(theClass,stack,true); 938 } 939 940 if (result == null) { 941 942 // Treat it as a non-conforming class type... 943 944 result = NCClassType.forNCClass(theClass,stack); 945 } 946 } 947 } 948 } 949 } catch (ClassNotFound e) { 950 classNotFound(stack,e); 951 } 952 break; 953 } 954 955 default: throw new CompilerError("Unknown typecode (" + typeCode + ") for " + theType.getTypeSignature()); 956 } 957 958 return result; 959 } 960 961 /* 962 * Check if exception is RemoteException or one of its parents. 963 */ 964 public static boolean isRemoteException (ClassType ex, 965 BatchEnvironment env) { 966 sun.tools.java.Type exceptionType = ex.getClassDeclaration().getType(); 967 968 if (exceptionType.equals(env.typeRemoteException) || 969 exceptionType.equals(env.typeIOException) || 970 exceptionType.equals(env.typeException) || 971 exceptionType.equals(env.typeThrowable)) { 972 973 return true; 974 } 975 return false; 976 } 977 978 /* 979 * Check if method is conforming. 980 */ 981 protected boolean isConformingRemoteMethod (Method method, boolean quiet) 982 throws ClassNotFound { 983 984 // Do we have one exception that is RemoteException or 985 // a superclass of RemoteException? 986 987 boolean haveRemote = false; 988 ClassType[] exceptions = method.getExceptions(); 989 990 for (int i = 0; i < exceptions.length; i++) { 991 992 // Is it a conforming exception? 993 994 if (isRemoteException(exceptions[i],env)) { 995 996 // Got it. 997 998 haveRemote = true; 999 break; 1000 } 1001 } 1002 1003 // Do we have our exception? 1004 1005 if (!haveRemote) { 1006 1007 // No, so report failure... 1008 1009 failedConstraint(5,quiet,stack,method.getEnclosing(), method.toString()); 1010 } 1011 1012 // Are any of the arguments exceptions which implement IDLEntity? 1013 // If so, report failure... 1014 1015 boolean noIDLEntity = !isIDLEntityException(method.getReturnType(),method,quiet); 1016 if (noIDLEntity) { 1017 Type[] args = method.getArguments(); 1018 for (int i = 0; i < args.length; i++) { 1019 if (isIDLEntityException(args[i],method,quiet)) { 1020 noIDLEntity = false; 1021 break; 1022 } 1023 } 1024 } 1025 1026 return (haveRemote && noIDLEntity); 1027 } 1028 1029 protected boolean isIDLEntityException(Type type, CompoundType.Method method,boolean quiet) 1030 throws ClassNotFound { 1031 if (type.isArray()) { 1032 type = type.getElementType(); 1033 } 1034 if (type.isCompound()){ 1035 if (((CompoundType)type).isIDLEntityException()) { 1036 failedConstraint(18,quiet,stack,method.getEnclosing(), method.toString()); 1037 return true; 1038 } 1039 } 1040 return false; 1041 } 1042 1043 /** 1044 * Convert all invalid types to valid ones. 1045 */ 1046 protected void swapInvalidTypes () { 1047 1048 // Walk all interfaces and check them... 1049 1050 for (int i = 0; i < interfaces.length; i++) { 1051 if (interfaces[i].getStatus() != STATUS_VALID) { 1052 interfaces[i] = (InterfaceType)getValidType(interfaces[i]); 1053 } 1054 } 1055 1056 // Update methods... 1057 1058 for (int i = 0; i < methods.length; i++) { 1059 methods[i].swapInvalidTypes(); 1060 } 1061 1062 // Update members... 1063 1064 for (int i = 0; i < members.length; i++) { 1065 members[i].swapInvalidTypes(); 1066 } 1067 } 1068 1069 /* 1070 * Add matching types to list. Return true if this type has not 1071 * been previously checked, false otherwise. 1072 */ 1073 protected boolean addTypes (int typeCodeFilter, 1074 HashSet checked, 1075 Vector matching) { 1076 1077 // Check self. 1078 1079 boolean result = super.addTypes(typeCodeFilter,checked,matching); 1080 1081 // Have we been checked before? 1082 1083 if (result) { 1084 1085 // Nope, so walk parent(s) and check them... 1086 1087 ClassType parent = getSuperclass(); 1088 1089 if (parent != null) { 1090 parent.addTypes(typeCodeFilter,checked,matching); 1091 } 1092 1093 // Walk all interfaces and check them... 1094 1095 //if (interfaces == null) System.out.println("NULL for " +getQualifiedName() + " interfaces"); 1096 for (int i = 0; i < interfaces.length; i++) { 1097 1098 // Now recurse and add it and any referenced types... 1099 1100 //if (interfaces[i] == null) System.out.println("NULL for " +getQualifiedName() + " interfaces[" + i + "]"); 1101 interfaces[i].addTypes(typeCodeFilter,checked,matching); 1102 } 1103 1104 // Walk all methods and check arguments... 1105 1106 //if (methods == null) System.out.println("NULL for " +getQualifiedName() + " methods"); 1107 for (int i = 0; i < methods.length; i++) { 1108 1109 // Add return type... 1110 //if (methods[i] == null) System.out.println("NULL for " +getQualifiedName() + " methods[" + i + "]"); 1111 //if (methods[i].getReturnType() == null) System.out.println("NULL for " +getQualifiedName() + methods[i]); 1112 methods[i].getReturnType().addTypes(typeCodeFilter,checked,matching); 1113 1114 // Add args... 1115 1116 Type[] args = methods[i].getArguments(); 1117 //if (args == null) System.out.println("NULL for " + getQualifiedName() + " args"); 1118 1119 for (int j = 0; j < args.length; j++) { 1120 1121 Type arg = args[j]; 1122 //if (arg == null) System.out.println("NULL for " + getQualifiedName() + " arg[" +j+"]"); 1123 1124 // Add argument... 1125 1126 arg.addTypes(typeCodeFilter,checked,matching); 1127 } 1128 1129 // Add exceptions... 1130 1131 ClassType[] exceptions = methods[i].getExceptions(); 1132 //if (exceptions == null) System.out.println("NULL for " + getQualifiedName() + " exceptions"); 1133 1134 for (int j = 0; j < exceptions.length; j++) { 1135 1136 ClassType ex = exceptions[j]; 1137 1138 // Add argument... 1139 1140 ex.addTypes(typeCodeFilter,checked,matching); 1141 } 1142 } 1143 1144 // Walk all members and add em... 1145 1146 //if (members == null) System.out.println("NULL for " +getQualifiedName() + " members"); 1147 for (int i = 0; i < members.length; i++) { 1148 //if (members[i] == null) System.out.println("NULL for " +getQualifiedName() + " members[" + i + "]"); 1149 Type cType = members[i].getType(); 1150 //if (cType == null) System.out.println("NULL for " + getQualifiedName() + " cType"); 1151 1152 // Add it... 1153 1154 cType.addTypes(typeCodeFilter,checked,matching); 1155 } 1156 } 1157 1158 return result; 1159 } 1160 1161 /* 1162 * Return true if theType is a conforming constant type. 1163 */ 1164 private boolean isConformingConstantType (MemberDefinition member) { 1165 return isConformingConstantType(member.getType(),member); 1166 } 1167 1168 /* 1169 * Return true if theType is a conforming constant type. 1170 */ 1171 private boolean isConformingConstantType (sun.tools.java.Type theType,MemberDefinition member) { 1172 1173 // Constraint 3: Constants must be either primitives or String. 1174 1175 boolean result = true; 1176 int typeCode = theType.getTypeCode(); 1177 switch (typeCode) { 1178 case TC_BOOLEAN: 1179 case TC_BYTE: 1180 case TC_CHAR: 1181 case TC_SHORT: 1182 case TC_INT: 1183 case TC_LONG: 1184 case TC_FLOAT: 1185 case TC_DOUBLE: // Primitive, so OK... 1186 { 1187 break; 1188 } 1189 1190 case TC_CLASS: // Must be java.lang.String 1191 { 1192 if (theType.getClassName() != idJavaLangString) { 1193 failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); 1194 result = false; 1195 } 1196 break; 1197 } 1198 1199 case TC_ARRAY: // Array constants are not allowed. 1200 { 1201 failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); 1202 result = false; 1203 break; 1204 } 1205 1206 default: 1207 throw new Error("unexpected type code: " + typeCode); 1208 } 1209 1210 return result; 1211 } 1212 1213 1214 /* 1215 * Update any method from 'currentMethods' which is defined in a 1216 * parent class so that it's 'declaredBy' field specifies the 1217 * parent. 1218 * @param current The class or interface to gather methods from. 1219 * @param currentMethods The list into which to put the methods. 1220 * for contraint 6. 1221 * @param quiet true if silent errors. 1222 * @param stack the context stack. 1223 * @return currentMethods or null if failed a constraint check. 1224 */ 1225 protected Vector updateParentClassMethods(ClassDefinition current, 1226 Vector currentMethods, 1227 boolean quiet, 1228 ContextStack stack) 1229 throws ClassNotFound { 1230 1231 ClassDeclaration parentDecl = current.getSuperClass(env); 1232 1233 while (parentDecl != null) { 1234 1235 ClassDefinition parentDef = parentDecl.getClassDefinition(env); 1236 Identifier currentID = parentDecl.getName(); 1237 1238 if ( currentID == idJavaLangObject ) break; 1239 1240 // Walk all members of this class and update any that 1241 // already exist in currentMethods... 1242 1243 for (MemberDefinition member = parentDef.getFirstMember(); 1244 member != null; 1245 member = member.getNextMember()) { 1246 1247 if (member.isMethod() && 1248 !member.isInitializer() && 1249 !member.isConstructor() && 1250 !member.isPrivate()) { 1251 1252 // It's a method. Is it valid? 1253 1254 Method method; 1255 try { 1256 method = new Method((CompoundType)this,member,quiet,stack); 1257 } catch (Exception e) { 1258 // Don't report anything here, it's already been reported... 1259 return null; 1260 } 1261 1262 // Have we already seen it? 1263 1264 int index = currentMethods.indexOf(method); 1265 if (index >= 0) { 1266 1267 // Yes, so update it... 1268 1269 Method currentMethod = (Method)currentMethods.elementAt(index); 1270 currentMethod.setDeclaredBy(currentID); 1271 } 1272 else currentMethods.addElement(method); 1273 } 1274 } 1275 1276 // Update parent and keep walking up the chain... 1277 1278 parentDecl = parentDef.getSuperClass(env); 1279 } 1280 1281 return currentMethods; 1282 } 1283 1284 /* 1285 * Add all of the public and protected methods defined in 1286 * current (other than initializers) to allMethods. If a sub-interface 1287 * re-declares an inherited method, it will not be added. 1288 * @param current The class or interface to gather methods from. 1289 * @param directMethods The list into which to put the methods. 1290 * @param noMultiInheritedMethods A flag to enable/disable checking 1291 * for contraint 6. 1292 * @param quiet true if silent errors. 1293 * @param stack the context stack. 1294 * @return directMethods or null if failed a constraint check. 1295 */ 1296 protected Vector addAllMethods (ClassDefinition current, Vector directMethods, 1297 boolean noMultiInheritedMethods, 1298 boolean quiet, 1299 ContextStack stack) 1300 throws ClassNotFound { 1301 1302 // Constraint 6: Multiple inherited interfaces may not 1303 // declare the same method. 1304 1305 ClassDeclaration[] interfaces = current.getInterfaces(); 1306 1307 // We want to add members starting at the _least_ derived 1308 // interfaces. To do so, recurse until we have no more 1309 // interfaces... 1310 1311 for (int i = 0; i < interfaces.length; i++) { 1312 1313 Vector result = addAllMethods(interfaces[i].getClassDefinition(env), 1314 directMethods, 1315 noMultiInheritedMethods,quiet,stack); 1316 if (result == null) { 1317 return null; 1318 } 1319 } 1320 1321 // Walk all members of this interface, adding any unique methods 1322 // other than initializers and private methods... 1323 1324 for (MemberDefinition member = current.getFirstMember(); 1325 member != null; 1326 member = member.getNextMember()) 1327 { 1328 if (member.isMethod() && 1329 !member.isInitializer() && 1330 !member.isPrivate()) { 1331 1332 // It's a method. Is it valid? 1333 1334 Method method; 1335 try { 1336 method = new Method((CompoundType)this,member,quiet,stack); 1337 } catch (Exception e) { 1338 // Don't report anything here, it's already been reported... 1339 return null; 1340 } 1341 1342 // Have we already seen it? 1343 1344 if (!directMethods.contains(method)) { 1345 1346 // Nope, so add it... 1347 1348 directMethods.addElement(method); 1349 1350 } else { 1351 1352 // Yes. This is an error unless we are looking at the 1353 // target interface (or this is a ValueType). Are we? 1354 1355 if (noMultiInheritedMethods && current != classDef && 1356 !stack.isParentAValue() && !stack.getContext().isValue()) { 1357 1358 // Nope. Say so and signal error by returning null.. 1359 1360 Method existingMethod = (Method) directMethods.elementAt(directMethods.indexOf(method)); 1361 ClassDefinition existingMemberClassDef = existingMethod.getMemberDefinition().getClassDefinition(); 1362 1363 // There are more legal cases to consider here. 1364 // If the two methods belong to interfaces that inherit from each other 1365 // then it is just a redefinition which is legal. 1366 if ( current != existingMemberClassDef && 1367 ! inheritsFrom(current, existingMemberClassDef) && 1368 ! inheritsFrom(existingMemberClassDef, current)) 1369 { 1370 //Identifier int1 = existingMethod.getEnclosing().getIdentifier(); 1371 //Identifier int2 = current.getName(); 1372 //String message = int1.toString() + " and " + int2.toString(); 1373 String message = existingMemberClassDef.getName() + " and " + current.getName(); 1374 failedConstraint(6,quiet,stack,classDef,message,method); 1375 return null; 1376 } 1377 } 1378 1379 // Bug fix 5014329 1380 1381 // find a matching method. 1382 int index = directMethods.indexOf(method); 1383 Method other = (Method) directMethods.get(index); 1384 1385 // merge the two methods, such that the new method 1386 // will contain only those exception that can be thrown 1387 // by both these methods, not just one of them. 1388 Method newMethod = method.mergeWith(other); 1389 1390 // replace the old method with the new. 1391 directMethods.set(index, newMethod); 1392 } 1393 } 1394 } 1395 1396 return directMethods; 1397 } 1398 1399 // This should really be a method on ClassDefinition, but it takes too long to change the shared source. 1400 // Works for both, classes and interfaces. 1401 protected boolean inheritsFrom(ClassDefinition def, ClassDefinition otherDef) { 1402 if (def == otherDef) 1403 return true; 1404 1405 ClassDefinition superDef; 1406 if (def.getSuperClass() != null) { 1407 superDef = def.getSuperClass().getClassDefinition(); 1408 if (inheritsFrom(superDef, otherDef)) 1409 return true; 1410 } 1411 1412 ClassDeclaration[] interfaces = def.getInterfaces(); 1413 for (int i=0; i<interfaces.length; i++) { 1414 superDef = interfaces[i].getClassDefinition(); 1415 if (inheritsFrom(superDef, otherDef)) 1416 return true; 1417 } 1418 return false; 1419 } 1420 1421 /* 1422 * Add all of the interfaces implemented directly by current 1423 * to the list. Returns null if any are non-conforming. 1424 */ 1425 protected Vector addRemoteInterfaces (Vector list, 1426 boolean allowNonConforming, 1427 ContextStack stack) throws ClassNotFound { 1428 1429 // Add all the interfaces of current... 1430 1431 ClassDefinition theInterface = getClassDefinition(); 1432 ClassDeclaration[] interfaces = theInterface.getInterfaces(); 1433 1434 stack.setNewContextCode(ContextStack.IMPLEMENTS); 1435 1436 for (int i = 0; i < interfaces.length; i++) { 1437 1438 ClassDefinition def = interfaces[i].getClassDefinition(env); 1439 1440 // Is it a SpecialInterfaceType... 1441 1442 InterfaceType it = SpecialInterfaceType.forSpecial(def,stack);; 1443 1444 if (it == null) { 1445 1446 // No, is it Remote? 1447 1448 if (env.defRemote.implementedBy(env, interfaces[i])) { 1449 1450 // Yes, so it must be a RemoteType. 1451 1452 it = RemoteType.forRemote(def,stack,false); 1453 1454 } else { 1455 1456 // Then try Abstract... 1457 1458 it = AbstractType.forAbstract(def,stack,true); 1459 1460 if (it == null && allowNonConforming) { 1461 1462 // Must be non-conforming... 1463 1464 it = NCInterfaceType.forNCInterface(def,stack); 1465 } 1466 } 1467 } 1468 1469 if (it != null) { 1470 list.addElement(it); 1471 } else { 1472 return null; 1473 } 1474 } 1475 1476 return list; 1477 } 1478 1479 /* 1480 * Add all of the interfaces implemented directly by current 1481 * to the list. 1482 */ 1483 protected Vector addNonRemoteInterfaces (Vector list, 1484 ContextStack stack) throws ClassNotFound { 1485 1486 // Add all the interfaces of current... 1487 1488 ClassDefinition theInterface = getClassDefinition(); 1489 ClassDeclaration[] interfaces = theInterface.getInterfaces(); 1490 1491 stack.setNewContextCode(ContextStack.IMPLEMENTS); 1492 1493 for (int i = 0; i < interfaces.length; i++) { 1494 1495 ClassDefinition def = interfaces[i].getClassDefinition(env); 1496 1497 // First try SpecialInterfaceType... 1498 1499 InterfaceType it = SpecialInterfaceType.forSpecial(def,stack); 1500 1501 if (it == null) { 1502 1503 // Then try AbstractType... 1504 1505 it = AbstractType.forAbstract(def,stack,true); 1506 1507 if (it == null) { 1508 1509 // Then try NCInterfaceType... 1510 1511 it = NCInterfaceType.forNCInterface(def,stack); 1512 } 1513 } 1514 1515 if (it != null) { 1516 list.addElement(it); 1517 } else { 1518 return null; 1519 } 1520 } 1521 1522 return list; 1523 } 1524 1525 1526 /* 1527 * Walk self, adding constants and data members. 1528 * @return true if all conform, false otherwise. 1529 */ 1530 protected boolean addAllMembers (Vector allMembers, 1531 boolean onlyConformingConstants, // AND inner classes. 1532 boolean quiet, 1533 ContextStack stack) { 1534 1535 boolean result = true; 1536 1537 // Walk all members of this interface... 1538 1539 for (MemberDefinition member = getClassDefinition().getFirstMember(); 1540 member != null && result; 1541 member = member.getNextMember()) 1542 { 1543 if (!member.isMethod()) { 1544 1545 try { 1546 String value = null; 1547 1548 // Prod it to setValue if it is a constant... 1549 1550 member.getValue(env); 1551 1552 // Get the value, if any... 1553 1554 Node node = member.getValue(); 1555 1556 if (node != null) { 1557 // We don't want to change the code in CharExpression, 1558 // which is shared among tools, to return the right string 1559 // in case the type is char, so we treat it special here. 1560 if (member.getType().getTypeCode() == TC_CHAR) { 1561 Integer intValue = (Integer)((IntegerExpression)node).getValue(); 1562 value = "L'" + String.valueOf((char)intValue.intValue()) + "'"; 1563 } else { 1564 value = node.toString(); 1565 } 1566 } 1567 1568 // Are we supposed to allow only conforming constants? 1569 1570 if (onlyConformingConstants && member.getInnerClass() == null) { 1571 1572 // Yep, so check it... 1573 1574 if (value == null || !isConformingConstantType(member)) { 1575 failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName()); 1576 result = false; 1577 break; 1578 } 1579 } 1580 1581 // Make member and add to list... 1582 1583 try { 1584 Member newMember = new Member(member,value,stack,this); 1585 allMembers.addElement(newMember); 1586 } catch (CompilerError e) { 1587 result = false; 1588 } 1589 1590 } catch (ClassNotFound e) { 1591 classNotFound(stack,e); 1592 result = false; 1593 } 1594 } 1595 } 1596 1597 return result; 1598 } 1599 /* 1600 * Walk self, adding constants. 1601 * @return true if all conform, false otherwise. 1602 */ 1603 protected boolean addConformingConstants (Vector allMembers, 1604 boolean quiet, 1605 ContextStack stack) { 1606 1607 boolean result = true; 1608 1609 // Walk all members of this interface... 1610 1611 for (MemberDefinition member = getClassDefinition().getFirstMember(); 1612 member != null && result; 1613 member = member.getNextMember()) 1614 { 1615 if (!member.isMethod()) { 1616 1617 try { 1618 String value = null; 1619 1620 // Prod it to setValue if it is a constant... 1621 1622 member.getValue(env); 1623 1624 // Get the value, if any... 1625 1626 Node node = member.getValue(); 1627 1628 if (node != null) { 1629 value = node.toString(); 1630 } 1631 1632 1633 // Is it a constant? 1634 1635 if (value != null) { 1636 1637 // Yes, is it conforming? 1638 1639 if (!isConformingConstantType(member)) { 1640 failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName()); 1641 result = false; 1642 break; 1643 } 1644 1645 // Yes, so make a member and add to list... 1646 1647 try { 1648 Member newMember = new Member(member,value,stack,this); 1649 allMembers.addElement(newMember); 1650 } catch (CompilerError e) { 1651 result = false; 1652 } 1653 } 1654 } catch (ClassNotFound e) { 1655 classNotFound(stack,e); 1656 result = false; 1657 } 1658 } 1659 } 1660 1661 return result; 1662 } 1663 1664 protected ValueType[] getMethodExceptions (MemberDefinition member, 1665 boolean quiet, 1666 ContextStack stack) throws Exception { 1667 1668 boolean result = true; 1669 stack.setNewContextCode(ContextStack.METHOD_EXCEPTION); 1670 ClassDeclaration[] except = member.getExceptions(env); 1671 ValueType[] exceptions = new ValueType[except.length]; 1672 1673 try { 1674 for (int i = 0; i < except.length; i++) { 1675 ClassDefinition theClass = except[i].getClassDefinition(env); 1676 try { 1677 ValueType type = ValueType.forValue(theClass,stack,false); 1678 if (type != null) { 1679 exceptions[i] = type; 1680 } else { 1681 result = false; 1682 } 1683 } catch (ClassCastException e1) { 1684 failedConstraint(22,quiet,stack,getQualifiedName()); 1685 throw new CompilerError("Method: exception " + theClass.getName() + " not a class type!"); 1686 } catch (NullPointerException e2) { 1687 failedConstraint(23,quiet,stack,getQualifiedName()); 1688 throw new CompilerError("Method: caught null pointer exception"); 1689 } 1690 } 1691 } catch (ClassNotFound e) { 1692 classNotFound(quiet,stack,e); 1693 result = false; 1694 } 1695 1696 if (!result) { 1697 throw new Exception(); 1698 } 1699 1700 // Remove any duplicates (javac seems to allow them, but rmic will 1701 // generate bad ties)... 1702 1703 int dupCount = 0; 1704 for (int i = 0; i < exceptions.length; i++) { 1705 for (int j = 0; j < exceptions.length; j++) { 1706 if (i != j && exceptions[i] != null && exceptions[i] == exceptions[j]) { 1707 exceptions[j] = null; 1708 dupCount++; 1709 } 1710 } 1711 } 1712 if (dupCount > 0) { 1713 int offset = 0; 1714 ValueType[] temp = new ValueType[exceptions.length - dupCount]; 1715 for (int i = 0; i < exceptions.length; i++) { 1716 if (exceptions[i] != null) { 1717 temp[offset++] = exceptions[i]; 1718 } 1719 } 1720 exceptions = temp; 1721 } 1722 1723 return exceptions; 1724 } 1725 1726 1727 protected static String getVisibilityString (MemberDefinition member) { 1728 String vis = ""; 1729 String prefix = ""; 1730 1731 if (member.isPublic()) { 1732 vis += "public"; 1733 prefix = " "; 1734 } else if (member.isProtected()) { 1735 vis += "protected"; 1736 prefix = " "; 1737 } else if (member.isPrivate()) { 1738 vis += "private"; 1739 prefix = " "; 1740 } 1741 1742 if (member.isStatic()) { 1743 vis += prefix; 1744 vis += "static"; 1745 prefix = " "; 1746 } 1747 1748 if (member.isFinal()) { 1749 vis += prefix; 1750 vis += "final"; 1751 prefix = " "; 1752 } 1753 1754 return vis; 1755 } 1756 1757 protected boolean assertNotImpl(Type type, 1758 boolean quiet, 1759 ContextStack stack, 1760 CompoundType enclosing, 1761 boolean dataMember) { 1762 1763 if (type.isType(TYPE_IMPLEMENTATION)) { 1764 int constraint = dataMember ? 28 : 21; 1765 failedConstraint(constraint,quiet,stack,type,enclosing.getName()); 1766 return false; 1767 } 1768 return true; 1769 } 1770 1771 //_____________________________________________________________________ 1772 // Inner Class "Method" 1773 //_____________________________________________________________________ 1774 1775 /** 1776 * A CompoundType.Method object encapsulates IIOP-specific information 1777 * about a particular method in the interface represented by the outer 1778 * instance. 1779 */ 1780 public class Method implements ContextElement, Cloneable { 1781 1782 /** 1783 * Is this method inherited? 1784 */ 1785 public boolean isInherited () { 1786 return declaredBy != enclosing.getIdentifier(); 1787 } 1788 1789 /** 1790 * Is this method an attribute? 1791 * Return true if getAttributeKind != ATTRIBUTE_NONE. 1792 */ 1793 public boolean isAttribute () { 1794 return attributeKind != ATTRIBUTE_NONE; 1795 } 1796 1797 /** 1798 * Is this method a read-write attribute? 1799 */ 1800 public boolean isReadWriteAttribute () { 1801 return attributeKind == ATTRIBUTE_IS_RW || 1802 attributeKind == ATTRIBUTE_GET_RW; 1803 } 1804 1805 /** 1806 * Return the attribute kind. 1807 */ 1808 public int getAttributeKind() { 1809 return attributeKind; 1810 } 1811 1812 /** 1813 * Return the attribute name. Will be null if 1814 * attribute kind == ATTRIBUTE_NONE. 1815 */ 1816 public String getAttributeName() { 1817 return attributeName; 1818 } 1819 1820 /** 1821 * For kinds ATTRIBUTE_GET_RW or ATTRIBUTE_IS_RW, return 1822 * the index of the matching ATTRIBUTE_SET method, and 1823 * vice-versa. For all other cases, return -1. 1824 */ 1825 public int getAttributePairIndex() { 1826 return attributePairIndex; 1827 } 1828 1829 /** 1830 * Return context element name. 1831 */ 1832 public String getElementName() { 1833 return memberDef.toString(); 1834 } 1835 1836 /** 1837 * Equality check based on method signature. 1838 */ 1839 public boolean equals(Object obj) { 1840 Method other = (Method) obj; 1841 1842 if (getName().equals(other.getName()) && 1843 arguments.length == other.arguments.length) { 1844 1845 for (int i = 0; i < arguments.length; i++) { 1846 if (! arguments[i].equals(other.arguments[i])) { 1847 return false; 1848 } 1849 } 1850 return true; 1851 } 1852 return false; 1853 } 1854 1855 public int hashCode() { 1856 return getName().hashCode() ^ Arrays.hashCode(arguments); 1857 } 1858 1859 /** 1860 * Return a new Method object that is a legal combination of 1861 * this method object and another one. 1862 * 1863 * This requires determining the exceptions declared by the 1864 * combined method, which must be only those exceptions 1865 * that may thrown by both of the old methods. 1866 */ 1867 public Method mergeWith(Method other) { 1868 if (!equals(other)) { 1869 env.error(0, "attempt to merge method failed:", getName(), 1870 enclosing.getClassDefinition().getName()); 1871 } 1872 1873 Vector legalExceptions = new Vector(); 1874 try { 1875 collectCompatibleExceptions( 1876 other.exceptions, exceptions, legalExceptions); 1877 collectCompatibleExceptions( 1878 exceptions, other.exceptions, legalExceptions); 1879 } catch (ClassNotFound e) { 1880 env.error(0, "class.not.found", e.name, 1881 enclosing.getClassDefinition().getName()); 1882 return null; 1883 } 1884 1885 Method merged = (Method) clone(); 1886 merged.exceptions = new ValueType[legalExceptions.size()]; 1887 legalExceptions.copyInto(merged.exceptions); 1888 merged.implExceptions = merged.exceptions; 1889 1890 return merged; 1891 } 1892 1893 /** 1894 * Add to the supplied list all exceptions in the "from" array 1895 * that are subclasses of an exception in the "with" array. 1896 */ 1897 private void collectCompatibleExceptions( 1898 ValueType[] from, ValueType[] with, Vector list) 1899 throws ClassNotFound { 1900 1901 for (int i = 0; i < from.length; i++) { 1902 ClassDefinition exceptionDef = from[i].getClassDefinition(); 1903 if (!list.contains(from[i])) { 1904 for (int j = 0; j < with.length; j++) { 1905 if (exceptionDef.subClassOf( 1906 enclosing.getEnv(), 1907 with[j].getClassDeclaration())) { 1908 list.addElement(from[i]); 1909 break; 1910 } 1911 } 1912 } 1913 } 1914 } 1915 1916 /** 1917 * Return the compound type which contains this method. 1918 */ 1919 public CompoundType getEnclosing() { 1920 return enclosing; 1921 } 1922 1923 /** 1924 * Return the identifier for the class or interface which 1925 * declares this method. 1926 */ 1927 public Identifier getDeclaredBy() { 1928 return declaredBy; 1929 } 1930 1931 /** 1932 * Return the visibility (e.g. "public final") of this member. 1933 */ 1934 public String getVisibility() { 1935 return vis; 1936 } 1937 1938 /** 1939 * Methods to check various attributes. 1940 */ 1941 public boolean isPublic() { 1942 return memberDef.isPublic(); 1943 } 1944 1945 public boolean isProtected() { 1946 return memberDef.isPrivate(); 1947 } 1948 1949 public boolean isPrivate() { 1950 return memberDef.isPrivate(); 1951 } 1952 1953 public boolean isStatic() { 1954 return memberDef.isStatic(); 1955 } 1956 1957 /** 1958 * Return the name of this method. 1959 */ 1960 public String getName() { 1961 return name; 1962 } 1963 1964 /** 1965 * IDL_Naming 1966 * Return the IDL name of this method. 1967 */ 1968 public String getIDLName() { 1969 return idlName; 1970 } 1971 1972 /** 1973 * Return the type of this method. 1974 */ 1975 public sun.tools.java.Type getType() { 1976 return memberDef.getType(); 1977 } 1978 1979 /** 1980 * Return true if this is a constructor. 1981 */ 1982 public boolean isConstructor () { 1983 return memberDef.isConstructor(); 1984 } 1985 1986 /** 1987 * Return true if this is NOT a constructor {@code &&} is not 1988 * an attribute. 1989 */ 1990 public boolean isNormalMethod () { 1991 return (!memberDef.isConstructor()) && attributeKind == ATTRIBUTE_NONE; 1992 } 1993 1994 /** 1995 * Get the return type of this method. May be null. 1996 */ 1997 public Type getReturnType() { 1998 return returnType; 1999 } 2000 2001 /** 2002 * Return the argument types of this method. 2003 */ 2004 public Type[] getArguments() { 2005 return (Type[]) arguments.clone(); 2006 } 2007 2008 /** 2009 * Return the names of the argument types of this method. 2010 */ 2011 public String[] getArgumentNames() { 2012 return argumentNames; 2013 } 2014 2015 /** 2016 * Return the MemberDefinition from which this method was created. 2017 */ 2018 public MemberDefinition getMemberDefinition() { 2019 return memberDef; 2020 } 2021 2022 /** 2023 * Return an array of the exception classes declared to be 2024 * thrown by this remote method. 2025 * 2026 * For methods with the same name and type signature inherited 2027 * from multiple remote interfaces, the array will contain 2028 * the set of exceptions declared in all of the interfaces' 2029 * methods that can be legally thrown in each of them. 2030 */ 2031 public ValueType[] getExceptions() { 2032 return (ValueType[]) exceptions.clone(); 2033 } 2034 2035 /** 2036 * Same as getExceptions(), except when method is in an 2037 * ImplementationType and the exceptions list is narrower. 2038 */ 2039 public ValueType[] getImplExceptions() { 2040 return (ValueType[]) implExceptions.clone(); 2041 } 2042 2043 /** 2044 * Return an array containing only those exceptions which 2045 * need to be caught. Removes java.rmi.RemoteException, 2046 * java.lang.RuntimeException, java.lang.Error, and their 2047 * subclasses, then removes any exceptions which are more 2048 * derived than another in the list. Returns null if no 2049 * exceptions need to be caught. 2050 */ 2051 public ValueType[] getUniqueCatchList(ValueType[] list) { 2052 ValueType[] result = list; 2053 int newSize = list.length; 2054 2055 try { 2056 2057 // First, remove RemoteException, RuntimeException, Error, and their subclasses... 2058 for (int i = 0; i < list.length; i++) { 2059 ClassDeclaration decl = list[i].getClassDeclaration(); 2060 if (env.defRemoteException.superClassOf(env, decl) || 2061 env.defRuntimeException.superClassOf(env, decl) || 2062 env.defError.superClassOf(env, decl)) { 2063 list[i] = null; 2064 newSize--; 2065 } 2066 } 2067 2068 // Now remove derived types... 2069 for (int i = 0; i < list.length; i++) { 2070 if (list[i] != null) { 2071 ClassDefinition current = list[i].getClassDefinition(); 2072 for (int j = 0; j < list.length; j++) { 2073 if (j != i && list[i] != null && list[j] != null && 2074 current.superClassOf(env, list[j].getClassDeclaration())) { 2075 list[j] = null; 2076 newSize--; 2077 } 2078 } 2079 } 2080 } 2081 2082 } catch (ClassNotFound e) { 2083 classNotFound(stack,e); // Report error but do not stop. 2084 } 2085 2086 // Create new list if we removed anything... 2087 2088 if (newSize < list.length) { 2089 ValueType[] temp = new ValueType[newSize]; 2090 int offset = 0; 2091 for (int i = 0; i < list.length; i++) { 2092 if (list[i] != null) { 2093 temp[offset++] = list[i]; 2094 } 2095 } 2096 list = temp; 2097 } 2098 2099 if (list.length == 0) { 2100 return null; 2101 } else { 2102 return list; 2103 } 2104 } 2105 2106 /** 2107 * Return an array containing only those exceptions which need to be 2108 * handled explicitly by the stub. Removes java.lang.RuntimeException, 2109 * java.lang.Error, and their subclasses, since these are all passed 2110 * back as CORBA system exceptions. Also removes subclasses of 2111 * java.rmi.RemoteException but not java.rmi.RemoteException itself, 2112 * since this may need to be thrown by the stub. 2113 */ 2114 public ValueType[] getFilteredStubExceptions(ValueType[] list) { 2115 ValueType[] result = list; 2116 int newSize = list.length; 2117 2118 try { 2119 2120 for (int i = 0; i < list.length; i++) { 2121 ClassDeclaration decl = list[i].getClassDeclaration(); 2122 if ((env.defRemoteException.superClassOf(env, decl) && 2123 !env.defRemoteException.getClassDeclaration().equals(decl)) || 2124 env.defRuntimeException.superClassOf(env, decl) || 2125 env.defError.superClassOf(env, decl)) { 2126 list[i] = null; 2127 newSize--; 2128 } 2129 } 2130 2131 } catch (ClassNotFound e) { 2132 classNotFound(stack,e); // Report error but do not stop. 2133 } 2134 2135 // Create new list if we removed anything... 2136 2137 if (newSize < list.length) { 2138 ValueType[] temp = new ValueType[newSize]; 2139 int offset = 0; 2140 for (int i = 0; i < list.length; i++) { 2141 if (list[i] != null) { 2142 temp[offset++] = list[i]; 2143 } 2144 } 2145 list = temp; 2146 } 2147 2148 return list; 2149 } 2150 2151 /** 2152 * Return the string representation of this method. 2153 */ 2154 public String toString() { 2155 2156 if (stringRep == null) { 2157 2158 StringBuffer result = new StringBuffer(returnType.toString()); 2159 2160 // Add name... 2161 2162 result.append(" "); 2163 result.append(getName()); 2164 result.append(" ("); 2165 2166 // Add arguments... 2167 2168 for (int i = 0; i < arguments.length; i++) { 2169 if (i > 0) { 2170 result.append(", "); 2171 } 2172 result.append(arguments[i]); 2173 result.append(" "); 2174 result.append(argumentNames[i]); 2175 } 2176 2177 result.append(")"); 2178 2179 // Add exceptions... 2180 2181 for (int i = 0; i < exceptions.length; i++) { 2182 if (i == 0) { 2183 result.append(" throws "); 2184 } else { 2185 result.append(", "); 2186 } 2187 result.append(exceptions[i]); 2188 } 2189 2190 result.append(";"); 2191 2192 stringRep = result.toString(); 2193 } 2194 2195 return stringRep; 2196 } 2197 2198 2199 /** 2200 * Set attribute kind. May only be called during initialization. 2201 */ 2202 public void setAttributeKind(int kind) { 2203 attributeKind = kind; 2204 } 2205 2206 /** 2207 * Set pair index. May only be called during initialization. 2208 */ 2209 public void setAttributePairIndex(int index) { 2210 attributePairIndex = index; 2211 } 2212 2213 /** 2214 * Set attribute name. May only be called during initialization. 2215 */ 2216 public void setAttributeName(String name) { 2217 attributeName = name; 2218 } 2219 2220 /** 2221 * Set the idl name. May only be called during initialization. 2222 */ 2223 public void setIDLName (String idlName) { 2224 this.idlName=idlName; 2225 } 2226 2227 /** 2228 * Set the implExceptions array. May only be called during initialization. 2229 */ 2230 public void setImplExceptions (ValueType[] exceptions) { 2231 implExceptions = exceptions; 2232 } 2233 2234 /** 2235 * Set the declaredBy Identifier. May only be called during initialization. 2236 */ 2237 public void setDeclaredBy (Identifier by) { 2238 declaredBy = by; 2239 } 2240 2241 /** 2242 * Convert all invalid types to valid ones. 2243 */ 2244 protected void swapInvalidTypes () { 2245 2246 // Check return type... 2247 2248 if (returnType.getStatus() != STATUS_VALID) { 2249 returnType = getValidType(returnType); 2250 } 2251 2252 // Check args... 2253 2254 for (int i = 0; i < arguments.length; i++) { 2255 if (arguments[i].getStatus() != STATUS_VALID) { 2256 arguments[i] = getValidType(arguments[i]); 2257 } 2258 } 2259 2260 // Check exceptions... 2261 2262 for (int i = 0; i < exceptions.length; i++) { 2263 if (exceptions[i].getStatus() != STATUS_VALID) { 2264 exceptions[i] = (ValueType)getValidType(exceptions[i]); 2265 } 2266 } 2267 2268 // Check implExceptions... 2269 2270 for (int i = 0; i < implExceptions.length; i++) { 2271 if (implExceptions[i].getStatus() != STATUS_VALID) { 2272 implExceptions[i] = (ValueType)getValidType(implExceptions[i]); 2273 } 2274 } 2275 } 2276 2277 /** 2278 * Release all resources. 2279 */ 2280 public void destroy () { 2281 if (memberDef != null) { 2282 memberDef = null; 2283 enclosing = null; 2284 if (exceptions != null) { 2285 for (int i = 0; i < exceptions.length; i++) { 2286 if (exceptions[i] != null) exceptions[i].destroy(); 2287 exceptions[i] = null; 2288 } 2289 exceptions = null; 2290 } 2291 2292 if (implExceptions != null) { 2293 for (int i = 0; i < implExceptions.length; i++) { 2294 if (implExceptions[i] != null) implExceptions[i].destroy(); 2295 implExceptions[i] = null; 2296 } 2297 implExceptions = null; 2298 } 2299 2300 if (returnType != null) returnType.destroy(); 2301 returnType = null; 2302 2303 if (arguments != null) { 2304 for (int i = 0; i < arguments.length; i++) { 2305 if (arguments[i] != null) arguments[i].destroy(); 2306 arguments[i] = null; 2307 } 2308 arguments = null; 2309 } 2310 2311 if (argumentNames != null) { 2312 for (int i = 0; i < argumentNames.length; i++) { 2313 argumentNames[i] = null; 2314 } 2315 argumentNames = null; 2316 } 2317 2318 vis = null; 2319 name = null; 2320 idlName = null; 2321 stringRep = null; 2322 attributeName = null; 2323 declaredBy = null; 2324 } 2325 } 2326 2327 private MemberDefinition memberDef; 2328 private CompoundType enclosing; 2329 private ValueType[] exceptions; 2330 private ValueType[] implExceptions; 2331 private Type returnType; 2332 private Type[] arguments; 2333 private String[] argumentNames; 2334 private String vis; 2335 private String name; 2336 private String idlName; 2337 private String stringRep = null; 2338 private int attributeKind = ATTRIBUTE_NONE; 2339 private String attributeName = null; 2340 private int attributePairIndex = -1; 2341 private Identifier declaredBy = null; 2342 2343 /** 2344 * Make up an argument name for the given type. 2345 */ 2346 private String makeArgName (int argNum, Type type) { 2347 return "arg" + argNum; 2348 } 2349 2350 /** 2351 * Create a new Method object corresponding to the given 2352 * method definition. 2353 */ 2354 public Method (CompoundType enclosing, 2355 MemberDefinition memberDef, 2356 boolean quiet, 2357 ContextStack stack) throws Exception { 2358 2359 this.enclosing = enclosing; 2360 this.memberDef = memberDef; 2361 vis = getVisibilityString(memberDef); 2362 idlName = null; // See setIDLName() 2363 boolean valid = true; 2364 declaredBy = memberDef.getClassDeclaration().getName(); 2365 2366 // Set name... 2367 2368 name = memberDef.getName().toString(); 2369 2370 // Update the context... 2371 2372 stack.setNewContextCode(ContextStack.METHOD); 2373 stack.push(this); 2374 2375 // Set return type... 2376 2377 stack.setNewContextCode(ContextStack.METHOD_RETURN); 2378 sun.tools.java.Type methodType = memberDef.getType(); 2379 sun.tools.java.Type rtnType = methodType.getReturnType(); 2380 2381 if (rtnType == sun.tools.java.Type.tVoid) { 2382 returnType = PrimitiveType.forPrimitive(rtnType,stack); 2383 } else { 2384 returnType = makeType(rtnType,null,stack); 2385 if (returnType == null || 2386 !assertNotImpl(returnType,quiet,stack,enclosing,false)) { 2387 valid = false; 2388 failedConstraint(24,quiet,stack,enclosing.getName()); 2389 } 2390 } 2391 2392 // Set arguments and argument names... 2393 2394 stack.setNewContextCode(ContextStack.METHOD_ARGUMENT); 2395 sun.tools.java.Type[] args = memberDef.getType().getArgumentTypes(); 2396 arguments = new Type[args.length]; 2397 argumentNames = new String[args.length]; 2398 Vector origArgNames = memberDef.getArguments(); 2399 2400 for (int i = 0; i < args.length; i++) { 2401 Type type = null; 2402 try { 2403 type = makeType(args[i],null,stack); 2404 } catch (Exception e) { 2405 } 2406 2407 if (type != null) { 2408 if (!assertNotImpl(type,quiet,stack,enclosing,false)) { 2409 valid = false; 2410 } else { 2411 arguments[i] = type; 2412 if (origArgNames != null) { 2413 LocalMember local = (LocalMember)origArgNames.elementAt(i+1); 2414 argumentNames[i] = local.getName().toString(); 2415 } else { 2416 argumentNames[i] = makeArgName(i,type); 2417 } 2418 } 2419 } else { 2420 valid = false; 2421 failedConstraint(25,false,stack,enclosing.getQualifiedName(),name); 2422 } 2423 } 2424 2425 if (!valid) { 2426 stack.pop(false); 2427 throw new Exception(); 2428 } 2429 2430 // Set exceptions... 2431 2432 try { 2433 exceptions = enclosing.getMethodExceptions(memberDef,quiet,stack); 2434 implExceptions = exceptions; 2435 stack.pop(true); 2436 } catch (Exception e) { 2437 stack.pop(false); 2438 throw new Exception(); 2439 } 2440 } 2441 2442 /** 2443 * Cloning is supported by returning a shallow copy of this object. 2444 */ 2445 protected Object clone() { 2446 try { 2447 return super.clone(); 2448 } catch (CloneNotSupportedException e) { 2449 throw new Error("clone failed"); 2450 } 2451 } 2452 } 2453 2454 //_____________________________________________________________________ 2455 // Inner Class "Member" 2456 //_____________________________________________________________________ 2457 2458 /** 2459 * An CompoundType.Member object wraps a Type and a value representing 2460 * a data member, including constants. 2461 */ 2462 public class Member implements ContextElement, Cloneable { 2463 2464 /** 2465 * Return context element name. 2466 */ 2467 public String getElementName() { 2468 return "\"" + getName() + "\""; 2469 } 2470 2471 /** 2472 * Return the type of this member. 2473 */ 2474 public Type getType() { 2475 return type; 2476 } 2477 2478 /** 2479 * Return the name of this member. 2480 */ 2481 public String getName() { 2482 return name; 2483 } 2484 2485 /** 2486 * IDL_Naming 2487 * Return the IDL name of this member. 2488 */ 2489 public String getIDLName() { 2490 return idlName; 2491 } 2492 2493 /** 2494 * Return the visibility (e.g. "public final") of this member. 2495 */ 2496 public String getVisibility() { 2497 return vis; 2498 } 2499 2500 /** 2501 * Methods to check various attributes. 2502 */ 2503 public boolean isPublic() { 2504 return member.isPublic(); 2505 } 2506 2507 public boolean isPrivate() { 2508 return member.isPrivate(); 2509 } 2510 2511 public boolean isStatic() { 2512 return member.isStatic(); 2513 } 2514 2515 public boolean isFinal() { 2516 return member.isFinal(); 2517 } 2518 2519 public boolean isTransient() { 2520 if (forceTransient) return true; 2521 return member.isTransient(); 2522 } 2523 2524 /** 2525 * Return the value of this member. May be null. 2526 */ 2527 public String getValue() { 2528 return value; 2529 } 2530 2531 /** 2532 * Return true if this member represents an inner class declaration, 2533 * false otherwise. 2534 */ 2535 public boolean isInnerClassDeclaration() { 2536 return innerClassDecl; 2537 } 2538 2539 /** 2540 * Return true if this member represents a constant. 2541 */ 2542 public boolean isConstant () { 2543 return constant; 2544 } 2545 2546 /** 2547 * Return the string representation of this constant. 2548 */ 2549 public String toString() { 2550 2551 String result = type.toString(); 2552 2553 if (value != null) { 2554 result += (" = " + value); 2555 } 2556 2557 return result; 2558 } 2559 2560 /** 2561 * Convert all invalid types to valid ones. 2562 */ 2563 protected void swapInvalidTypes () { 2564 if (type.getStatus() != STATUS_VALID) { 2565 type = getValidType(type); 2566 } 2567 } 2568 2569 protected void setTransient() { 2570 if (! isTransient()) { 2571 forceTransient = true; 2572 if (vis.length() > 0) { 2573 vis = vis + " transient"; 2574 } else { 2575 vis = "transient"; 2576 } 2577 } 2578 } 2579 2580 protected MemberDefinition getMemberDefinition() { 2581 return member; 2582 } 2583 2584 /** 2585 * Release all resources. 2586 */ 2587 public void destroy () { 2588 if (type != null) { 2589 type.destroy(); 2590 type = null; 2591 vis = null; 2592 value = null; 2593 name = null; 2594 idlName = null; 2595 member = null; 2596 } 2597 } 2598 2599 private Type type; 2600 private String vis; 2601 private String value; 2602 private String name; 2603 private String idlName; 2604 private boolean innerClassDecl; 2605 private boolean constant; 2606 private MemberDefinition member; 2607 private boolean forceTransient; 2608 2609 /** 2610 * Create a new Member object. 2611 */ 2612 public Member(MemberDefinition member, 2613 String value, 2614 ContextStack stack, 2615 CompoundType enclosing) { 2616 this.member = member; 2617 this.value = value; 2618 forceTransient = false; 2619 innerClassDecl = member.getInnerClass() != null; 2620 2621 // If we are not an inner class, finish initializing now. 2622 // Otherwise, wait until outer class is finished, then 2623 // call init to avoid potential recursion problems... 2624 2625 if (!innerClassDecl) { 2626 init (stack,enclosing); 2627 } 2628 } 2629 2630 public void init (ContextStack stack, CompoundType enclosing) { 2631 2632 constant = false; 2633 name = member.getName().toString(); 2634 vis = getVisibilityString(member); 2635 idlName = null; 2636 2637 // Add self to stack... 2638 2639 int contextCode = ContextStack.MEMBER; 2640 stack.setNewContextCode(contextCode); 2641 2642 // Check for special contextCodes... 2643 2644 if (member.isVariable()) { 2645 if (value != null && member.isConstant()) { 2646 contextCode = ContextStack.MEMBER_CONSTANT; 2647 this.constant = true; 2648 } else if (member.isStatic()) { 2649 contextCode = ContextStack.MEMBER_STATIC; 2650 } else if (member.isTransient()) { 2651 contextCode = ContextStack.MEMBER_TRANSIENT; 2652 } 2653 } 2654 2655 stack.setNewContextCode(contextCode); 2656 stack.push(this); 2657 2658 type = makeType(member.getType(),null,stack); 2659 2660 if (type == null || 2661 (!innerClassDecl && 2662 !member.isStatic() && 2663 !member.isTransient() && 2664 !assertNotImpl(type,false,stack,enclosing,true))) { 2665 stack.pop(false); 2666 throw new CompilerError(""); 2667 } 2668 2669 // Clean up primitive constant values... 2670 2671 if (constant && type.isPrimitive()) { 2672 if (type.isType(TYPE_LONG) || type.isType(TYPE_FLOAT) || type.isType(TYPE_DOUBLE)) { 2673 int length = value.length(); 2674 char lastChar = value.charAt(length-1); 2675 if (!Character.isDigit(lastChar)) { 2676 this.value = value.substring(0,length-1); 2677 } 2678 } else if (type.isType(TYPE_BOOLEAN)) { 2679 value = value.toUpperCase(); 2680 } 2681 } 2682 if (constant && type.isType(TYPE_STRING)) { 2683 value = "L" + value; 2684 } 2685 stack.pop(true); 2686 } 2687 2688 public void setIDLName (String name) { 2689 this.idlName = name; 2690 } 2691 2692 /** 2693 * Cloning is supported by returning a shallow copy of this object. 2694 */ 2695 protected Object clone() { 2696 try { 2697 return super.clone(); 2698 } catch (CloneNotSupportedException e) { 2699 throw new Error("clone failed"); 2700 } 2701 } 2702 } 2703} 2704