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.util.Arrays;
  36 import java.util.Vector;
  37 import sun.tools.java.Identifier;
  38 import sun.tools.java.ClassNotFound;
  39 import sun.tools.java.ClassDefinition;
  40 import sun.tools.java.ClassDeclaration;
  41 import sun.tools.java.MemberDefinition;
  42 import sun.tools.java.CompilerError;
  43 import sun.tools.tree.Node;
  44 import sun.tools.tree.LocalMember;
  45 import sun.tools.tree.CharExpression;
  46 import sun.tools.tree.IntegerExpression;
  47 import sun.rmi.rmic.IndentingWriter;
  48 import java.io.IOException;
  49 import java.util.HashSet;
  50 import java.util.Enumeration;
  51 import 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  */
  59 public 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      * isIDLEntity() && isException().
 149      */
 150     public boolean isIDLEntityException () {
 151         return isIDLEntity() && isException();
 152     }
 153     /**
 154      * Return true if 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 && 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 }