1 /*
   2  * Copyright (c) 1998, 2007, 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.Vector;
  36 import java.util.Hashtable;
  37 import java.util.Enumeration;
  38 import java.io.IOException;
  39 import sun.tools.java.ClassDefinition;
  40 import sun.tools.java.ClassDeclaration;
  41 import sun.tools.java.Identifier;
  42 import sun.tools.java.ClassNotFound;
  43 import sun.tools.java.CompilerError;
  44 import sun.rmi.rmic.IndentingWriter;
  45 import java.util.HashSet;
  46 import com.sun.corba.se.impl.util.RepositoryId;
  47 import sun.rmi.rmic.Names;
  48 
  49 /**
  50  * Type is an abstract base class for a family of types which provide
  51  * conformance checking and name mapping as defined in the "Java to IDL
  52  * Mapping" OMG specification.  The family is composed of the following
  53  * fixed set of types:
  54  * <pre>{@literal
  55  *
  56  *                                              +- RemoteType <-- AbstractType
  57  *                                              |
  58  *                           +- InterfaceType <-+- SpecialInterfaceType
  59  *         +- PrimitiveType  |                  |
  60  *         |                 |                  +- NCInterfaceType
  61  *  Type <-+- CompoundType <-|
  62  *         |                 |                  +- ValueType
  63  *         +- ArrayType      |                  |
  64  *                           +- ClassType <-----+- ImplementationType
  65  *                                              |
  66  *                                              +- SpecialClassType
  67  *                                              |
  68  *                                              +- NCClassType
  69  *
  70  * }</pre>
  71  * PrimitiveType represents a primitive or a void type.
  72  * <p>
  73  * CompoundType is an abstract base representing any non-special class
  74  * or interface type.
  75  * <p>
  76  * InterfaceType is an abstract base representing any non-special
  77  * interface type.
  78  * <p>
  79  * RemoteType represents any non-special interface which inherits
  80  * from java.rmi.Remote.
  81  * <p>
  82  * AbstractType represents any non-special interface which does not
  83  * inherit from java.rmi.Remote, for which all methods throw RemoteException.
  84  * <p>
  85  * SpecialInterfaceType represents any one of the following types:
  86  * <pre>
  87  *    java.rmi.Remote
  88  *    java.io.Serializable
  89  *    java.io.Externalizable
  90  * </pre>
  91  * all of which are treated as special cases.
  92  * <p>
  93  * NCInterfaceType represents any non-special, non-conforming interface.
  94  * <p>
  95  * ClassType is an abstract base representing any non-special class
  96  * type.
  97  * <p>
  98  * ValueType represents any non-special class which does inherit from
  99  * java.io.Serializable and does not inherit from java.rmi.Remote.
 100  * <p>
 101  * ImplementationType represents any non-special class which implements
 102  * one or more interfaces which inherit from java.rmi.Remote.
 103  * <p>
 104  * SpecialClassType represents any one of the following types:
 105  * <pre>
 106  *    java.lang.Object
 107  *    java.lang.String
 108  *    org.omg.CORBA.Object
 109  * </pre>
 110  * all of which are treated as special cases. For all but CORBA.Object,
 111  * the type must match exactly. For CORBA.Object, the type must either be
 112  * CORBA.Object or inherit from it.
 113  * <p>
 114  * NCClassType represents any non-special, non-conforming class.
 115  * <p>
 116  * ArrayType is a wrapper for any of the other types. The getElementType()
 117  * method can be used to get the array element type.  The getArrayDimension()
 118  * method can be used to get the array dimension.
 119  * <p>
 120  * <i><strong>NOTE:</strong> None of these types is multi-thread-safe</i>
 121  * @author      Bryan Atsatt
 122  */
 123 public abstract class Type implements sun.rmi.rmic.iiop.Constants, ContextElement, Cloneable {
 124 
 125     private int typeCode;
 126     private int fullTypeCode;
 127     private Identifier id;
 128 
 129     private String name;
 130     private String packageName;
 131     private String qualifiedName;
 132 
 133     private String idlName;
 134     private String[] idlModuleNames;
 135     private String qualifiedIDLName;
 136 
 137     private String repositoryID;
 138     private Class ourClass;
 139 
 140     private int status = STATUS_PENDING;
 141 
 142     protected BatchEnvironment env;     // Easy access for subclasses.
 143     protected ContextStack stack;       // Easy access for subclasses.
 144 
 145     protected boolean destroyed = false;
 146 
 147     //_____________________________________________________________________
 148     // Public Interfaces
 149     //_____________________________________________________________________
 150 
 151     /**
 152      * Return the unqualified name for this type (e.g. com.acme.Dynamite would
 153      * return "Dynamite").
 154      */
 155     public String getName() {
 156         return name;
 157     }
 158 
 159     /**
 160      * Return the package of this type (e.g. com.acme.Dynamite would
 161      * return "com.acme"). Will return null if default package or
 162      * if this type is a primitive.
 163      */
 164     public String getPackageName() {
 165         return packageName;
 166     }
 167 
 168     /**
 169      * Return the fully qualified name of this type  (e.g. com.acme.Dynamite
 170      * would return "com.acme.Dynamite")
 171      */
 172     public String getQualifiedName() {
 173         return qualifiedName;
 174     }
 175 
 176     /**
 177      * Return signature for this type  (e.g. com.acme.Dynamite
 178      * would return "com.acme.Dynamite", byte = "B")
 179      */
 180     public abstract String getSignature();
 181 
 182     /**
 183      * IDL_Naming
 184      * Return the unqualified IDL name of this type (e.g. com.acme.Dynamite would
 185      * return "Dynamite").
 186      */
 187     public String getIDLName() {
 188         return idlName;
 189     }
 190 
 191     /**
 192      * IDL_Naming
 193      * Return the IDL module name for this type (e.g. com.acme.Dynamite would return
 194      * a three element array of {"com","acme"). May be a zero length array if
 195      * there is no module name.
 196      */
 197     public String[] getIDLModuleNames() {
 198         return idlModuleNames;
 199     }
 200 
 201     /**
 202      * IDL_Naming
 203      * Return the fully qualified IDL name for this type (e.g. com.acme.Dynamite would
 204      * return "com::acme::Dynamite").
 205      * @param global If true, prepends "::".
 206      */
 207     public String getQualifiedIDLName(boolean global) {
 208         if (global && getIDLModuleNames().length > 0) {
 209             return IDL_NAME_SEPARATOR + qualifiedIDLName;
 210         } else {
 211             return qualifiedIDLName;
 212         }
 213     }
 214 
 215     /**
 216      * Return the identifier for this type. May be qualified.
 217      */
 218     public Identifier getIdentifier() {
 219         return id;
 220     }
 221 
 222     /**
 223      * Return the repository ID for this type.
 224      */
 225     public String getRepositoryID() {
 226         return repositoryID;
 227     }
 228 
 229     /**
 230      * Return the repository ID for this "boxed" type.
 231      */
 232     public String getBoxedRepositoryID() {
 233         return RepositoryId.createForJavaType(ourClass);
 234     }
 235 
 236     /**
 237      * Return the Class for this type.
 238      */
 239     public Class getClassInstance() {
 240         if (ourClass == null) {
 241             initClass();
 242         }
 243         return ourClass;
 244     }
 245 
 246     /**
 247      * Return the status of this type.
 248      */
 249     public int getStatus() {
 250         return status;
 251     }
 252 
 253     /**
 254      * Set the status of this type.
 255      */
 256     public void setStatus(int status) {
 257         this.status = status;
 258     }
 259 
 260     /**
 261      * Return the compiler environment for this type.
 262      */
 263     public BatchEnvironment getEnv() {
 264         return env;
 265     }
 266 
 267     /**
 268      * Get type code, without modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
 269      */
 270     public int getTypeCode() {
 271         return typeCode;
 272     }
 273 
 274     /**
 275      * Get type code, with modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
 276      */
 277     public int getFullTypeCode() {
 278         return fullTypeCode;
 279     }
 280 
 281     /**
 282      * Get type code modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
 283      */
 284     public int getTypeCodeModifiers() {
 285         return fullTypeCode & TM_MASK;
 286     }
 287 
 288     /**
 289      * Check for a certain type. Type codes are defined in sun.rmi.rmic.iiop.Constants.
 290      * Returns true if all of the bits in typeCodeMask are present in the full type code
 291      * of this object.
 292      */
 293     public boolean isType(int typeCodeMask) {
 294         return (fullTypeCode & typeCodeMask) == typeCodeMask;
 295     }
 296 
 297     /**
 298      * Like isType(), but returns true if <em>any</em> of the bits in typeCodeMask are
 299      * present in the full type code of this object.
 300      */
 301     public boolean typeMatches(int typeCodeMask) {
 302         return (fullTypeCode & typeCodeMask) > 0;
 303     }
 304 
 305 
 306     /**
 307      * Return the fullTypeCode. If an array, returns the
 308      * type code from the element type.
 309      */
 310     public int getRootTypeCode() {
 311         if (isArray()) {
 312             return getElementType().getFullTypeCode();
 313         } else {
 314             return fullTypeCode;
 315         }
 316     }
 317 
 318     /**
 319      * Return true if this type is-a InterfaceType.
 320      */
 321     public boolean isInterface() {
 322         return (fullTypeCode & TM_INTERFACE) == TM_INTERFACE;
 323     }
 324 
 325     /**
 326      * Return true if this type is-a ClassType.
 327      */
 328     public boolean isClass() {
 329         return (fullTypeCode & TM_CLASS) == TM_CLASS;
 330     }
 331 
 332     /**
 333      * Return true if this type is-a inner class or interface.
 334      */
 335     public boolean isInner() {
 336         return (fullTypeCode & TM_INNER) == TM_INNER;
 337     }
 338 
 339 
 340     /**
 341      * Return true if this type is-a SpecialInterfaceType.
 342      */
 343     public boolean isSpecialInterface() {
 344         return (fullTypeCode & TM_SPECIAL_INTERFACE) == TM_SPECIAL_INTERFACE;
 345     }
 346 
 347     /**
 348      * Return true if this type is-a SpecialClassType.
 349      */
 350     public boolean isSpecialClass() {
 351         return (fullTypeCode & TM_SPECIAL_CLASS) == TM_SPECIAL_CLASS;
 352     }
 353 
 354     /**
 355      * Return true if this type is-a CompoundType.
 356      */
 357     public boolean isCompound() {
 358         return (fullTypeCode & TM_COMPOUND) == TM_COMPOUND;
 359     }
 360 
 361     /**
 362      * Return true if this type is-a PrimitiveType.
 363      */
 364     public boolean isPrimitive() {
 365         return (fullTypeCode & TM_PRIMITIVE) == TM_PRIMITIVE;
 366     }
 367 
 368     /**
 369      * Return true if this type is-a ArrayType.
 370      */
 371     public boolean isArray() {
 372         return (fullTypeCode & TYPE_ARRAY) == TYPE_ARRAY;
 373     }
 374 
 375     /**
 376      * Return true if this type is a conforming type.
 377      */
 378     public boolean isConforming() {
 379         return (fullTypeCode & TM_NON_CONFORMING) == TM_NON_CONFORMING;
 380     }
 381 
 382     /**
 383      * Return a string representation of this type.
 384      */
 385     public String toString () {
 386         return getQualifiedName();
 387     }
 388 
 389     /**
 390      * Get element type. Returns null if not an array.
 391      */
 392     public Type getElementType () {
 393         return null;
 394     }
 395 
 396     /**
 397      * Get array dimension. Returns zero if not an array.
 398      */
 399     public int getArrayDimension () {
 400         return 0;
 401     }
 402 
 403     /**
 404      * Get brackets string. Returns "" if not an array.
 405      */
 406     public String getArrayBrackets () {
 407         return "";
 408     }
 409 
 410     /**
 411      * Equality check based on the string representation.
 412      */
 413     public boolean equals(Object obj) {
 414 
 415         String us = toString();
 416         String them = ((Type)obj).toString();
 417         return us.equals(them);
 418     }
 419 
 420     /**
 421      * Collect all the matching types referenced directly or indirectly
 422      * by this type, including itself.
 423      * @param typeCodeFilter The typeCode to use as a filter.
 424      */
 425     public Type[] collectMatching (int typeCodeFilter) {
 426         return collectMatching(typeCodeFilter,new HashSet(env.allTypes.size()));
 427     }
 428 
 429     /**
 430      * Collect all the matching types referenced directly or indirectly
 431      * by this type, including itself.
 432      * @param typeCodeFilter The typeCode to use as a filter.
 433      * @param alreadyChecked Contains types which have previously been checked
 434      * and will be ignored. Updated during collection.
 435      */
 436     public Type[] collectMatching (int typeCodeFilter, HashSet alreadyChecked) {
 437         Vector matching = new Vector();
 438 
 439         // Fill up the list...
 440 
 441         addTypes(typeCodeFilter,alreadyChecked,matching);
 442 
 443         // Copy vector contents to array and return it...
 444 
 445         Type[] result = new Type[matching.size()];
 446         matching.copyInto(result);
 447 
 448         return result;
 449     }
 450 
 451     /**
 452      * Return a string describing this type.
 453      */
 454     public abstract String getTypeDescription ();
 455 
 456     /**
 457      * Return the name of this type. For arrays, will include "[]" if useIDLNames == false.
 458      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 459      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 460      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 461      */
 462     public String getTypeName ( boolean useQualifiedNames,
 463                                 boolean useIDLNames,
 464                                 boolean globalIDLNames) {
 465         if (useIDLNames) {
 466             if (useQualifiedNames) {
 467                 return getQualifiedIDLName(globalIDLNames);
 468             } else {
 469                 return getIDLName();
 470             }
 471         } else {
 472             if (useQualifiedNames) {
 473                 return getQualifiedName();
 474             } else {
 475                 return getName();
 476             }
 477         }
 478     }
 479 
 480     /**
 481      * Print all types referenced directly or indirectly by this type which
 482      * match the filter.
 483      * @param writer The stream to print to.
 484      * @param typeCodeFilter The type codes to print.
 485      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 486      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 487      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 488      */
 489     public void print ( IndentingWriter writer,
 490                         int typeCodeFilter,
 491                         boolean useQualifiedNames,
 492                         boolean useIDLNames,
 493                         boolean globalIDLNames) throws IOException {
 494 
 495         Type[] theTypes = collectMatching(typeCodeFilter);
 496         print(writer,theTypes,useQualifiedNames,useIDLNames,globalIDLNames);
 497     }
 498 
 499     /**
 500      * Print an array of types.
 501      * @param writer The stream to print to.
 502      * @param theTypes The types to print.
 503      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 504      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 505      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 506      */
 507     public static void print (  IndentingWriter writer,
 508                                 Type[] theTypes,
 509                                 boolean useQualifiedNames,
 510                                 boolean useIDLNames,
 511                                 boolean globalIDLNames) throws IOException {
 512 
 513         for (int i = 0; i < theTypes.length; i++) {
 514             theTypes[i].println(writer,useQualifiedNames,useIDLNames,globalIDLNames);
 515         }
 516     }
 517 
 518 
 519     /**
 520      * Print this type.
 521      * @param writer The stream to print to.
 522      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 523      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 524      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 525      */
 526     public void print ( IndentingWriter writer,
 527                         boolean useQualifiedNames,
 528                         boolean useIDLNames,
 529                         boolean globalIDLNames) throws IOException {
 530         printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
 531     }
 532 
 533     /**
 534      * Print this type, followed by a newline.
 535      * @param writer The stream to print to.
 536      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 537      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 538      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 539      */
 540     public void println (       IndentingWriter writer,
 541                                 boolean useQualifiedNames,
 542                                 boolean useIDLNames,
 543                                 boolean globalIDLNames) throws IOException  {
 544 
 545         print(writer,useQualifiedNames,useIDLNames,globalIDLNames);
 546         writer.pln();
 547     }
 548 
 549 
 550 
 551     /**
 552      * Print the name of this type.
 553      * @param writer The stream to print to.
 554      * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
 555      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 556      * @param globalIDLNames If true and useIDLNames true, prepends "::".
 557      */
 558     public void printTypeName ( IndentingWriter writer,
 559                                 boolean useQualifiedNames,
 560                                 boolean useIDLNames,
 561                                 boolean globalIDLNames) throws IOException {
 562 
 563         writer.p(getTypeName(useQualifiedNames,useIDLNames,globalIDLNames));
 564     }
 565 
 566     /**
 567      * Return context element name.
 568      */
 569     public String getElementName() {
 570         return getQualifiedName();
 571     }
 572 
 573     //_____________________________________________________________________
 574     // Subclass Interfaces
 575     //_____________________________________________________________________
 576 
 577     /**
 578      * Print the "opening" of the package or module of this type.
 579      * @param writer The stream to print to.
 580      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 581      */
 582     protected void printPackageOpen (   IndentingWriter writer,
 583                                         boolean useIDLNames) throws IOException {
 584 
 585         if (useIDLNames) {
 586             String[] moduleNames = getIDLModuleNames();
 587             for (int i = 0; i < moduleNames.length; i++ ) {
 588                 writer.plnI("module " + moduleNames[i] + " {");
 589             }
 590         } else {
 591             String packageName = getPackageName();
 592             if (packageName != null) {
 593                 writer.pln("package " + packageName + ";");
 594             }
 595         }
 596     }
 597 
 598     /**
 599      * Get a type out of the table.
 600      */
 601     protected static Type getType (sun.tools.java.Type key, ContextStack stack) {
 602         return getType(key.toString(),stack);
 603     }
 604 
 605     /**
 606      * Get a type out of the table.
 607      */
 608     protected static Type getType (String key, ContextStack stack) {
 609         Type result = (Type) stack.getEnv().allTypes.get(key);
 610 
 611         if (result != null) {
 612             stack.traceExistingType(result);
 613         }
 614 
 615         return result;
 616     }
 617 
 618     /**
 619      * Remove a type from the table.
 620      */
 621     protected static void removeType (String key, ContextStack stack) {
 622         Type value = (Type) stack.getEnv().allTypes.remove(key);
 623         stack.getEnv().invalidTypes.put(value,key);
 624     }
 625 
 626     /**
 627      * Remove a type from the table.
 628      */
 629     protected static void removeType (sun.tools.java.Type key, ContextStack stack) {
 630         String theKey = key.toString();
 631         Type old = (Type) stack.getEnv().allTypes.remove(theKey);
 632         putInvalidType(old,theKey,stack);
 633     }
 634 
 635     /**
 636      * Put a type into the table.
 637      */
 638     protected static void putType (sun.tools.java.Type key, Type value, ContextStack stack) {
 639         stack.getEnv().allTypes.put(key.toString(),value);
 640     }
 641 
 642     /**
 643      * Put a type into the table.
 644      */
 645     protected static void putType (String key, Type value, ContextStack stack) {
 646         stack.getEnv().allTypes.put(key,value);
 647     }
 648 
 649     /**
 650      * Put an invalid type into the.
 651      */
 652     protected static void putInvalidType (Type key, String value, ContextStack stack) {
 653         stack.getEnv().invalidTypes.put(key,value);
 654     }
 655 
 656 
 657     /**
 658      * Remove all invalid types...
 659      */
 660     public void removeInvalidTypes () {
 661         if (env.invalidTypes.size() > 0) {
 662             env.invalidTypes.clear();
 663         }
 664     }
 665 
 666     /**
 667      * Walk all types and tell them to update invalid types...
 668      */
 669     protected static void updateAllInvalidTypes (ContextStack stack) {
 670         BatchEnvironment env = stack.getEnv();
 671         if (env.invalidTypes.size() > 0) {
 672 
 673             // Walk all types and swap invalid...
 674 
 675             for (Enumeration e = env.allTypes.elements() ; e.hasMoreElements() ;) {
 676                 Type it = (Type) e.nextElement();
 677                 it.swapInvalidTypes();
 678             }
 679 
 680             // Delete all invalidTypes...
 681 
 682             env.invalidTypes.clear();
 683         }
 684     }
 685 
 686     /**
 687      * Return count of previously parsed types.
 688      */
 689     protected int countTypes () {
 690         return env.allTypes.size();
 691     }
 692 
 693     /**
 694      * Reset types removes all previously parsed types.
 695      */
 696     void resetTypes () {
 697         env.reset();
 698     }
 699 
 700     /**
 701      * Release all resources.
 702      */
 703     protected void destroy () {
 704         if (!destroyed) {
 705             id = null;
 706             name = null;
 707             packageName = null;
 708             qualifiedName = null;
 709             idlName = null;
 710             idlModuleNames = null;
 711             qualifiedIDLName = null;
 712             repositoryID = null;
 713             ourClass = null;
 714             env = null;
 715             stack = null;
 716             destroyed = true;
 717         }
 718     }
 719 
 720     /**
 721      * Convert all invalid types to valid ones.
 722      */
 723     protected void swapInvalidTypes () {
 724     }
 725 
 726     /**
 727      * Convert an invalid type to a valid one.
 728      */
 729     protected Type getValidType (Type invalidType) {
 730         if (invalidType.getStatus() == STATUS_VALID) {
 731             return invalidType;
 732         }
 733 
 734         String key = (String)env.invalidTypes.get(invalidType);
 735         Type result = null;
 736         if (key != null) {
 737             result = (Type) env.allTypes.get(key);
 738         }
 739 
 740         if (result == null) {
 741             throw new Error("Failed to find valid type to swap for " + invalidType + " mis-identified as " + invalidType.getTypeDescription());
 742         }
 743         //System.out.println("Swapped " + result + " from " + invalidType.getTypeDescription()
 744         //    + " to " + result.getTypeDescription());
 745         //ContextStack.dumpCallStack();
 746         return result;
 747     }
 748 
 749     /**
 750      * Print the "closing" of the package or module of this type.
 751      * @param writer The stream to print to.
 752      * @param useIDLNames If true, print IDL names; otherwise, print java names.
 753      */
 754     protected void printPackageClose (  IndentingWriter writer,
 755                                         boolean useIDLNames) throws IOException {
 756         if (useIDLNames) {
 757             String[] moduleNames = getIDLModuleNames();
 758             for (int i = 0; i < moduleNames.length; i++ ) {
 759                 writer.pOln("};");
 760             }
 761         }
 762     }
 763 
 764     /**
 765      * Create a Type instance for the given type. Requires that
 766      * setName(Identifier) be called afterward.
 767      */
 768     protected Type(ContextStack stack, int fullTypeCode) {
 769         this.env = stack.getEnv();
 770         this.stack = stack;
 771         this.fullTypeCode = fullTypeCode;
 772         typeCode = fullTypeCode & TYPE_MASK;
 773     }
 774 
 775     /**
 776      * Set type codes. May only be called during initialization.
 777      */
 778     protected void setTypeCode(int fullTypeCode) {
 779         this.fullTypeCode = fullTypeCode;
 780         typeCode = fullTypeCode & TYPE_MASK;
 781     }
 782 
 783     /**
 784      * Set name and package. May only be called during initialization.
 785      */
 786     protected void setNames(Identifier id, String[] idlModuleNames, String idlName) {
 787 
 788         this.id = id;
 789         name = Names.mangleClass(id).getName().toString();
 790         packageName = null;
 791 
 792         if (id.isQualified()) {
 793             packageName = id.getQualifier().toString();
 794             qualifiedName = packageName + NAME_SEPARATOR + name;
 795         } else {
 796             qualifiedName = name;
 797         }
 798 
 799         setIDLNames(idlModuleNames,idlName);
 800     }
 801 
 802 
 803     /**
 804      * Set IDL name. May only be called during initialization.
 805      */
 806     protected void setIDLNames(String[] idlModuleNames, String idlName) {
 807         this.idlName = idlName;
 808 
 809         if (idlModuleNames != null) {
 810             this.idlModuleNames = idlModuleNames;
 811         } else {
 812             this.idlModuleNames = new String[0];
 813         }
 814         qualifiedIDLName = IDLNames.getQualifiedName(idlModuleNames,idlName);
 815     }
 816 
 817     /**
 818      * Report a ClassNotFoundException thru the compiler environment.
 819      */
 820     protected static void classNotFound(ContextStack stack,
 821                                         ClassNotFound e) {
 822         classNotFound(false,stack,e);
 823     }
 824 
 825     /**
 826      * Report a ClassNotFoundException thru the compiler environment.
 827      */
 828     protected static void classNotFound(boolean quiet,
 829                                         ContextStack stack,
 830                                         ClassNotFound e) {
 831         if (!quiet) stack.getEnv().error(0, "rmic.class.not.found", e.name);
 832         stack.traceCallStack();
 833     }
 834 
 835     /**
 836      * Report a constraint failure thru the compiler environment.
 837      * @param constraintNum Used to generate a key of the form
 838      "rmic.iiop.constraint.N", which must identify a message
 839      in the "rmic.properties" file.
 840      * @param quiet True if should not cause failure or message.
 841      * @param stack The context stack.
 842      * @param arg0 An object to substitute for {0} in the message.
 843      * @param arg1 An object to substitute for {1} in the message.
 844      * @param arg2 An object to substitute for {2} in the message.
 845      * @return false.
 846      */
 847     protected static boolean failedConstraint(int constraintNum,
 848                                               boolean quiet,
 849                                               ContextStack stack,
 850                                               Object arg0, Object arg1, Object arg2) {
 851         String message = "rmic.iiop.constraint." + constraintNum;
 852 
 853         if (!quiet) {
 854             stack.getEnv().error(0,message,
 855                                  (arg0 != null ? arg0.toString() : null),
 856                                  (arg1 != null ? arg1.toString() : null),
 857                                  (arg2 != null ? arg2.toString() : null));
 858         } else {
 859             String error = stack.getEnv().errorString(message,arg0,arg1,arg2);
 860             stack.traceln(error);
 861         }
 862 
 863         return false;
 864     }
 865 
 866     /**
 867      * Report a constraint failure thru the compiler environment.
 868      * @param constraintNum Used to generate a key of the form
 869      "rmic.iiop.constraint.N", which must identify a message
 870      in the "rmic.properties" file.
 871      * @param quiet True if should not cause failure or message.
 872      * @param stack The context stack.
 873      * @param arg0 An object to substitute for {0} in the message.
 874      * @param arg1 An object to substitute for {1} in the message.
 875      * @return false.
 876      */
 877     protected static boolean failedConstraint(int constraintNum,
 878                                               boolean quiet,
 879                                               ContextStack stack,
 880                                               Object arg0, Object arg1) {
 881         return failedConstraint(constraintNum,quiet,stack,arg0,arg1,null);
 882     }
 883 
 884 
 885     /**
 886      * Report a constraint failure thru the compiler environment.
 887      * @param constraintNum Used to generate a key of the form
 888      "rmic.iiop.constraint.N", which must identify a message
 889      in the "rmic.properties" file.
 890      * @param quiet True if should not cause failure or message.
 891      * @param stack The context stack.
 892      * @param arg0 An object to substitute for {0} in the message.
 893      * @return false.
 894      */
 895     protected static boolean failedConstraint(int constraintNum,
 896                                               boolean quiet,
 897                                               ContextStack stack,
 898                                               Object arg0) {
 899         return failedConstraint(constraintNum,quiet,stack,arg0,null,null);
 900     }
 901 
 902     /**
 903      * Report a constraint failure thru the compiler environment.
 904      * @param quiet True if should not cause failure or message.
 905      * @param stack The context stack.
 906      * @param constraintNum Used to generate a key of the form
 907      "rmic.iiop.constraint.N", which must identify a message
 908      in the "rmic.properties" file.
 909      * @return false.
 910      */
 911     protected static boolean failedConstraint(int constraintNum,
 912                                               boolean quiet,
 913                                               ContextStack stack) {
 914         return failedConstraint(constraintNum,quiet,stack,null,null,null);
 915     }
 916 
 917     /**
 918      * Cloning is supported by returning a shallow copy of this object.
 919      */
 920     protected Object clone() {
 921         try {
 922             return super.clone();
 923         } catch (CloneNotSupportedException e) {
 924             throw new Error("clone failed");
 925         }
 926     }
 927 
 928     /*
 929      * Add matching types to list. Return true if this type has not
 930      * been previously checked, false otherwise.
 931      */
 932     protected boolean addTypes (int typeCodeFilter,
 933                                 HashSet checked,
 934                                 Vector matching) {
 935 
 936         boolean result;
 937 
 938         // Have we already checked this type?
 939 
 940         if (checked.contains(this)) {
 941 
 942             // Yes, so return false.
 943 
 944             result = false;
 945 
 946         } else {
 947 
 948             // Nope, so add it...
 949 
 950             checked.add(this);
 951 
 952             // Do we match the filter?
 953 
 954             if (typeMatches(typeCodeFilter)) {
 955 
 956                 // Yep. so add it and set result to true...
 957 
 958                 matching.addElement(this);
 959             }
 960 
 961             // Return true.
 962 
 963             result = true;
 964         }
 965 
 966         return result;
 967     }
 968 
 969     /*
 970      * Load a Class instance. Return null if fail.
 971      */
 972     protected abstract Class loadClass();
 973 
 974     private boolean initClass() {
 975         if (ourClass == null) {
 976             ourClass = loadClass();
 977             if (ourClass == null) {
 978                 failedConstraint(27,false,stack,getQualifiedName());
 979                 return false;
 980             }
 981         }
 982         return true;
 983     }
 984 
 985     /*
 986      * Set the clz and repositoryID fields. Reports error
 987      * and returns false if fails, returns true if succeeds.
 988      */
 989     protected boolean setRepositoryID() {
 990 
 991         // First, load the class...
 992 
 993         if (!initClass()) {
 994             return false;
 995         }
 996 
 997         // Now make the repositoryID and return success...
 998 
 999         repositoryID = RepositoryId.createForAnyType(ourClass);
1000         return true;
1001     }
1002 
1003 
1004     //_____________________________________________________________________
1005     // Internal Interfaces
1006     //_____________________________________________________________________
1007 
1008     private Type () {} // Disallowed.
1009 }