aoqi@0: /* aoqi@0: * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * Licensed Materials - Property of IBM aoqi@0: * RMI-IIOP v1.0 aoqi@0: * Copyright IBM Corp. 1998 1999 All Rights Reserved aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: package sun.rmi.rmic.iiop; aoqi@0: aoqi@0: import java.util.Vector; aoqi@0: import java.util.Hashtable; aoqi@0: import java.util.Enumeration; aoqi@0: import java.io.IOException; aoqi@0: import sun.tools.java.ClassDefinition; aoqi@0: import sun.tools.java.ClassDeclaration; aoqi@0: import sun.tools.java.Identifier; aoqi@0: import sun.tools.java.ClassNotFound; aoqi@0: import sun.tools.java.CompilerError; aoqi@0: import sun.rmi.rmic.IndentingWriter; aoqi@0: import java.util.HashSet; aoqi@0: import com.sun.corba.se.impl.util.RepositoryId; aoqi@0: import sun.rmi.rmic.Names; aoqi@0: aoqi@0: /** aoqi@0: * Type is an abstract base class for a family of types which provide aoqi@0: * conformance checking and name mapping as defined in the "Java to IDL aoqi@0: * Mapping" OMG specification. The family is composed of the following aoqi@0: * fixed set of types: aoqi@0: *
aoqi@0:  *
aoqi@0:  *                                              +- RemoteType <-- AbstractType
aoqi@0:  *                                              |
aoqi@0:  *                           +- InterfaceType <-+- SpecialInterfaceType
aoqi@0:  *         +- PrimitiveType  |                  |
aoqi@0:  *         |                 |                  +- NCInterfaceType
aoqi@0:  *  Type <-+- CompoundType <-|
aoqi@0:  *         |                 |                  +- ValueType
aoqi@0:  *         +- ArrayType      |                  |
aoqi@0:  *                           +- ClassType <-----+- ImplementationType
aoqi@0:  *                                              |
aoqi@0:  *                                              +- SpecialClassType
aoqi@0:  *                                              |
aoqi@0:  *                                              +- NCClassType
aoqi@0:  *
aoqi@0:  * 
aoqi@0: * PrimitiveType represents a primitive or a void type. aoqi@0: *

aoqi@0: * CompoundType is an abstract base representing any non-special class aoqi@0: * or interface type. aoqi@0: *

aoqi@0: * InterfaceType is an abstract base representing any non-special aoqi@0: * interface type. aoqi@0: *

aoqi@0: * RemoteType represents any non-special interface which inherits aoqi@0: * from java.rmi.Remote. aoqi@0: *

aoqi@0: * AbstractType represents any non-special interface which does not aoqi@0: * inherit from java.rmi.Remote, for which all methods throw RemoteException. aoqi@0: *

aoqi@0: * SpecialInterfaceType represents any one of the following types: aoqi@0: *

aoqi@0:  *    java.rmi.Remote
aoqi@0:  *    java.io.Serializable
aoqi@0:  *    java.io.Externalizable
aoqi@0:  * 
aoqi@0: * all of which are treated as special cases. aoqi@0: *

aoqi@0: * NCInterfaceType represents any non-special, non-conforming interface. aoqi@0: *

aoqi@0: * ClassType is an abstract base representing any non-special class aoqi@0: * type. aoqi@0: *

aoqi@0: * ValueType represents any non-special class which does inherit from aoqi@0: * java.io.Serializable and does not inherit from java.rmi.Remote. aoqi@0: *

aoqi@0: * ImplementationType represents any non-special class which implements aoqi@0: * one or more interfaces which inherit from java.rmi.Remote. aoqi@0: *

aoqi@0: * SpecialClassType represents any one of the following types: aoqi@0: *

aoqi@0:  *    java.lang.Object
aoqi@0:  *    java.lang.String
aoqi@0:  *    org.omg.CORBA.Object
aoqi@0:  * 
aoqi@0: * all of which are treated as special cases. For all but CORBA.Object, aoqi@0: * the type must match exactly. For CORBA.Object, the type must either be aoqi@0: * CORBA.Object or inherit from it. aoqi@0: *

aoqi@0: * NCClassType represents any non-special, non-conforming class. aoqi@0: *

aoqi@0: * ArrayType is a wrapper for any of the other types. The getElementType() aoqi@0: * method can be used to get the array element type. The getArrayDimension() aoqi@0: * method can be used to get the array dimension. aoqi@0: *

aoqi@0: * NOTE: None of these types is multi-thread-safe aoqi@0: * @author Bryan Atsatt aoqi@0: */ aoqi@0: public abstract class Type implements sun.rmi.rmic.iiop.Constants, ContextElement, Cloneable { aoqi@0: aoqi@0: private int typeCode; aoqi@0: private int fullTypeCode; aoqi@0: private Identifier id; aoqi@0: aoqi@0: private String name; aoqi@0: private String packageName; aoqi@0: private String qualifiedName; aoqi@0: aoqi@0: private String idlName; aoqi@0: private String[] idlModuleNames; aoqi@0: private String qualifiedIDLName; aoqi@0: aoqi@0: private String repositoryID; aoqi@0: private Class ourClass; aoqi@0: aoqi@0: private int status = STATUS_PENDING; aoqi@0: aoqi@0: protected BatchEnvironment env; // Easy access for subclasses. aoqi@0: protected ContextStack stack; // Easy access for subclasses. aoqi@0: aoqi@0: protected boolean destroyed = false; aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Public Interfaces aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * Return the unqualified name for this type (e.g. com.acme.Dynamite would aoqi@0: * return "Dynamite"). aoqi@0: */ aoqi@0: public String getName() { aoqi@0: return name; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the package of this type (e.g. com.acme.Dynamite would aoqi@0: * return "com.acme"). Will return null if default package or aoqi@0: * if this type is a primitive. aoqi@0: */ aoqi@0: public String getPackageName() { aoqi@0: return packageName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the fully qualified name of this type (e.g. com.acme.Dynamite aoqi@0: * would return "com.acme.Dynamite") aoqi@0: */ aoqi@0: public String getQualifiedName() { aoqi@0: return qualifiedName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return signature for this type (e.g. com.acme.Dynamite aoqi@0: * would return "com.acme.Dynamite", byte = "B") aoqi@0: */ aoqi@0: public abstract String getSignature(); aoqi@0: aoqi@0: /** aoqi@0: * IDL_Naming aoqi@0: * Return the unqualified IDL name of this type (e.g. com.acme.Dynamite would aoqi@0: * return "Dynamite"). aoqi@0: */ aoqi@0: public String getIDLName() { aoqi@0: return idlName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * IDL_Naming aoqi@0: * Return the IDL module name for this type (e.g. com.acme.Dynamite would return aoqi@0: * a three element array of {"com","acme"). May be a zero length array if aoqi@0: * there is no module name. aoqi@0: */ aoqi@0: public String[] getIDLModuleNames() { aoqi@0: return idlModuleNames; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * IDL_Naming aoqi@0: * Return the fully qualified IDL name for this type (e.g. com.acme.Dynamite would aoqi@0: * return "com::acme::Dynamite"). aoqi@0: * @param global If true, prepends "::". aoqi@0: */ aoqi@0: public String getQualifiedIDLName(boolean global) { aoqi@0: if (global && getIDLModuleNames().length > 0) { aoqi@0: return IDL_NAME_SEPARATOR + qualifiedIDLName; aoqi@0: } else { aoqi@0: return qualifiedIDLName; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the identifier for this type. May be qualified. aoqi@0: */ aoqi@0: public Identifier getIdentifier() { aoqi@0: return id; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the repository ID for this type. aoqi@0: */ aoqi@0: public String getRepositoryID() { aoqi@0: return repositoryID; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the repository ID for this "boxed" type. aoqi@0: */ aoqi@0: public String getBoxedRepositoryID() { aoqi@0: return RepositoryId.createForJavaType(ourClass); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the Class for this type. aoqi@0: */ aoqi@0: public Class getClassInstance() { aoqi@0: if (ourClass == null) { aoqi@0: initClass(); aoqi@0: } aoqi@0: return ourClass; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the status of this type. aoqi@0: */ aoqi@0: public int getStatus() { aoqi@0: return status; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the status of this type. aoqi@0: */ aoqi@0: public void setStatus(int status) { aoqi@0: this.status = status; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the compiler environment for this type. aoqi@0: */ aoqi@0: public BatchEnvironment getEnv() { aoqi@0: return env; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get type code, without modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants. aoqi@0: */ aoqi@0: public int getTypeCode() { aoqi@0: return typeCode; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get type code, with modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants. aoqi@0: */ aoqi@0: public int getFullTypeCode() { aoqi@0: return fullTypeCode; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get type code modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants. aoqi@0: */ aoqi@0: public int getTypeCodeModifiers() { aoqi@0: return fullTypeCode & TM_MASK; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Check for a certain type. Type codes are defined in sun.rmi.rmic.iiop.Constants. aoqi@0: * Returns true if all of the bits in typeCodeMask are present in the full type code aoqi@0: * of this object. aoqi@0: */ aoqi@0: public boolean isType(int typeCodeMask) { aoqi@0: return (fullTypeCode & typeCodeMask) == typeCodeMask; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Like isType(), but returns true if any of the bits in typeCodeMask are aoqi@0: * present in the full type code of this object. aoqi@0: */ aoqi@0: public boolean typeMatches(int typeCodeMask) { aoqi@0: return (fullTypeCode & typeCodeMask) > 0; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Return the fullTypeCode. If an array, returns the aoqi@0: * type code from the element type. aoqi@0: */ aoqi@0: public int getRootTypeCode() { aoqi@0: if (isArray()) { aoqi@0: return getElementType().getFullTypeCode(); aoqi@0: } else { aoqi@0: return fullTypeCode; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a InterfaceType. aoqi@0: */ aoqi@0: public boolean isInterface() { aoqi@0: return (fullTypeCode & TM_INTERFACE) == TM_INTERFACE; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a ClassType. aoqi@0: */ aoqi@0: public boolean isClass() { aoqi@0: return (fullTypeCode & TM_CLASS) == TM_CLASS; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a inner class or interface. aoqi@0: */ aoqi@0: public boolean isInner() { aoqi@0: return (fullTypeCode & TM_INNER) == TM_INNER; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a SpecialInterfaceType. aoqi@0: */ aoqi@0: public boolean isSpecialInterface() { aoqi@0: return (fullTypeCode & TM_SPECIAL_INTERFACE) == TM_SPECIAL_INTERFACE; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a SpecialClassType. aoqi@0: */ aoqi@0: public boolean isSpecialClass() { aoqi@0: return (fullTypeCode & TM_SPECIAL_CLASS) == TM_SPECIAL_CLASS; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a CompoundType. aoqi@0: */ aoqi@0: public boolean isCompound() { aoqi@0: return (fullTypeCode & TM_COMPOUND) == TM_COMPOUND; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a PrimitiveType. aoqi@0: */ aoqi@0: public boolean isPrimitive() { aoqi@0: return (fullTypeCode & TM_PRIMITIVE) == TM_PRIMITIVE; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is-a ArrayType. aoqi@0: */ aoqi@0: public boolean isArray() { aoqi@0: return (fullTypeCode & TYPE_ARRAY) == TYPE_ARRAY; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is a conforming type. aoqi@0: */ aoqi@0: public boolean isConforming() { aoqi@0: return (fullTypeCode & TM_NON_CONFORMING) == TM_NON_CONFORMING; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return a string representation of this type. aoqi@0: */ aoqi@0: public String toString () { aoqi@0: return getQualifiedName(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get element type. Returns null if not an array. aoqi@0: */ aoqi@0: public Type getElementType () { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get array dimension. Returns zero if not an array. aoqi@0: */ aoqi@0: public int getArrayDimension () { aoqi@0: return 0; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get brackets string. Returns "" if not an array. aoqi@0: */ aoqi@0: public String getArrayBrackets () { aoqi@0: return ""; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Equality check based on the string representation. aoqi@0: */ aoqi@0: public boolean equals(Object obj) { aoqi@0: aoqi@0: String us = toString(); aoqi@0: String them = ((Type)obj).toString(); aoqi@0: return us.equals(them); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Collect all the matching types referenced directly or indirectly aoqi@0: * by this type, including itself. aoqi@0: * @param typeCodeFilter The typeCode to use as a filter. aoqi@0: */ aoqi@0: public Type[] collectMatching (int typeCodeFilter) { aoqi@0: return collectMatching(typeCodeFilter,new HashSet(env.allTypes.size())); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Collect all the matching types referenced directly or indirectly aoqi@0: * by this type, including itself. aoqi@0: * @param typeCodeFilter The typeCode to use as a filter. aoqi@0: * @param alreadyChecked Contains types which have previously been checked aoqi@0: * and will be ignored. Updated during collection. aoqi@0: */ aoqi@0: public Type[] collectMatching (int typeCodeFilter, HashSet alreadyChecked) { aoqi@0: Vector matching = new Vector(); aoqi@0: aoqi@0: // Fill up the list... aoqi@0: aoqi@0: addTypes(typeCodeFilter,alreadyChecked,matching); aoqi@0: aoqi@0: // Copy vector contents to array and return it... aoqi@0: aoqi@0: Type[] result = new Type[matching.size()]; aoqi@0: matching.copyInto(result); aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return a string describing this type. aoqi@0: */ aoqi@0: public abstract String getTypeDescription (); aoqi@0: aoqi@0: /** aoqi@0: * Return the name of this type. For arrays, will include "[]" if useIDLNames == false. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public String getTypeName ( boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) { aoqi@0: if (useIDLNames) { aoqi@0: if (useQualifiedNames) { aoqi@0: return getQualifiedIDLName(globalIDLNames); aoqi@0: } else { aoqi@0: return getIDLName(); aoqi@0: } aoqi@0: } else { aoqi@0: if (useQualifiedNames) { aoqi@0: return getQualifiedName(); aoqi@0: } else { aoqi@0: return getName(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Print all types referenced directly or indirectly by this type which aoqi@0: * match the filter. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param typeCodeFilter The type codes to print. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public void print ( IndentingWriter writer, aoqi@0: int typeCodeFilter, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: Type[] theTypes = collectMatching(typeCodeFilter); aoqi@0: print(writer,theTypes,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Print an array of types. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param theTypes The types to print. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public static void print ( IndentingWriter writer, aoqi@0: Type[] theTypes, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: for (int i = 0; i < theTypes.length; i++) { aoqi@0: theTypes[i].println(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Print this type. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public void print ( IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Print this type, followed by a newline. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public void println ( IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: print(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: writer.pln(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Print the name of this type. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: * @param globalIDLNames If true and useIDLNames true, prepends "::". aoqi@0: */ aoqi@0: public void printTypeName ( IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: writer.p(getTypeName(useQualifiedNames,useIDLNames,globalIDLNames)); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return context element name. aoqi@0: */ aoqi@0: public String getElementName() { aoqi@0: return getQualifiedName(); aoqi@0: } aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Subclass Interfaces aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * Print the "opening" of the package or module of this type. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: */ aoqi@0: protected void printPackageOpen ( IndentingWriter writer, aoqi@0: boolean useIDLNames) throws IOException { aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: String[] moduleNames = getIDLModuleNames(); aoqi@0: for (int i = 0; i < moduleNames.length; i++ ) { aoqi@0: writer.plnI("module " + moduleNames[i] + " {"); aoqi@0: } aoqi@0: } else { aoqi@0: String packageName = getPackageName(); aoqi@0: if (packageName != null) { aoqi@0: writer.pln("package " + packageName + ";"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get a type out of the table. aoqi@0: */ aoqi@0: protected static Type getType (sun.tools.java.Type key, ContextStack stack) { aoqi@0: return getType(key.toString(),stack); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get a type out of the table. aoqi@0: */ aoqi@0: protected static Type getType (String key, ContextStack stack) { aoqi@0: Type result = (Type) stack.getEnv().allTypes.get(key); aoqi@0: aoqi@0: if (result != null) { aoqi@0: stack.traceExistingType(result); aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Remove a type from the table. aoqi@0: */ aoqi@0: protected static void removeType (String key, ContextStack stack) { aoqi@0: Type value = (Type) stack.getEnv().allTypes.remove(key); aoqi@0: stack.getEnv().invalidTypes.put(value,key); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Remove a type from the table. aoqi@0: */ aoqi@0: protected static void removeType (sun.tools.java.Type key, ContextStack stack) { aoqi@0: String theKey = key.toString(); aoqi@0: Type old = (Type) stack.getEnv().allTypes.remove(theKey); aoqi@0: putInvalidType(old,theKey,stack); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Put a type into the table. aoqi@0: */ aoqi@0: protected static void putType (sun.tools.java.Type key, Type value, ContextStack stack) { aoqi@0: stack.getEnv().allTypes.put(key.toString(),value); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Put a type into the table. aoqi@0: */ aoqi@0: protected static void putType (String key, Type value, ContextStack stack) { aoqi@0: stack.getEnv().allTypes.put(key,value); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Put an invalid type into the. aoqi@0: */ aoqi@0: protected static void putInvalidType (Type key, String value, ContextStack stack) { aoqi@0: stack.getEnv().invalidTypes.put(key,value); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Remove all invalid types... aoqi@0: */ aoqi@0: public void removeInvalidTypes () { aoqi@0: if (env.invalidTypes.size() > 0) { aoqi@0: env.invalidTypes.clear(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Walk all types and tell them to update invalid types... aoqi@0: */ aoqi@0: protected static void updateAllInvalidTypes (ContextStack stack) { aoqi@0: BatchEnvironment env = stack.getEnv(); aoqi@0: if (env.invalidTypes.size() > 0) { aoqi@0: aoqi@0: // Walk all types and swap invalid... aoqi@0: aoqi@0: for (Enumeration e = env.allTypes.elements() ; e.hasMoreElements() ;) { aoqi@0: Type it = (Type) e.nextElement(); aoqi@0: it.swapInvalidTypes(); aoqi@0: } aoqi@0: aoqi@0: // Delete all invalidTypes... aoqi@0: aoqi@0: env.invalidTypes.clear(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return count of previously parsed types. aoqi@0: */ aoqi@0: protected int countTypes () { aoqi@0: return env.allTypes.size(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Reset types removes all previously parsed types. aoqi@0: */ aoqi@0: void resetTypes () { aoqi@0: env.reset(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Release all resources. aoqi@0: */ aoqi@0: protected void destroy () { aoqi@0: if (!destroyed) { aoqi@0: id = null; aoqi@0: name = null; aoqi@0: packageName = null; aoqi@0: qualifiedName = null; aoqi@0: idlName = null; aoqi@0: idlModuleNames = null; aoqi@0: qualifiedIDLName = null; aoqi@0: repositoryID = null; aoqi@0: ourClass = null; aoqi@0: env = null; aoqi@0: stack = null; aoqi@0: destroyed = true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Convert all invalid types to valid ones. aoqi@0: */ aoqi@0: protected void swapInvalidTypes () { aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Convert an invalid type to a valid one. aoqi@0: */ aoqi@0: protected Type getValidType (Type invalidType) { aoqi@0: if (invalidType.getStatus() == STATUS_VALID) { aoqi@0: return invalidType; aoqi@0: } aoqi@0: aoqi@0: String key = (String)env.invalidTypes.get(invalidType); aoqi@0: Type result = null; aoqi@0: if (key != null) { aoqi@0: result = (Type) env.allTypes.get(key); aoqi@0: } aoqi@0: aoqi@0: if (result == null) { aoqi@0: throw new Error("Failed to find valid type to swap for " + invalidType + " mis-identified as " + invalidType.getTypeDescription()); aoqi@0: } aoqi@0: //System.out.println("Swapped " + result + " from " + invalidType.getTypeDescription() aoqi@0: // + " to " + result.getTypeDescription()); aoqi@0: //ContextStack.dumpCallStack(); aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Print the "closing" of the package or module of this type. aoqi@0: * @param writer The stream to print to. aoqi@0: * @param useIDLNames If true, print IDL names; otherwise, print java names. aoqi@0: */ aoqi@0: protected void printPackageClose ( IndentingWriter writer, aoqi@0: boolean useIDLNames) throws IOException { aoqi@0: if (useIDLNames) { aoqi@0: String[] moduleNames = getIDLModuleNames(); aoqi@0: for (int i = 0; i < moduleNames.length; i++ ) { aoqi@0: writer.pOln("};"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Create a Type instance for the given type. Requires that aoqi@0: * setName(Identifier) be called afterward. aoqi@0: */ aoqi@0: protected Type(ContextStack stack, int fullTypeCode) { aoqi@0: this.env = stack.getEnv(); aoqi@0: this.stack = stack; aoqi@0: this.fullTypeCode = fullTypeCode; aoqi@0: typeCode = fullTypeCode & TYPE_MASK; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set type codes. May only be called during initialization. aoqi@0: */ aoqi@0: protected void setTypeCode(int fullTypeCode) { aoqi@0: this.fullTypeCode = fullTypeCode; aoqi@0: typeCode = fullTypeCode & TYPE_MASK; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set name and package. May only be called during initialization. aoqi@0: */ aoqi@0: protected void setNames(Identifier id, String[] idlModuleNames, String idlName) { aoqi@0: aoqi@0: this.id = id; aoqi@0: name = Names.mangleClass(id).getName().toString(); aoqi@0: packageName = null; aoqi@0: aoqi@0: if (id.isQualified()) { aoqi@0: packageName = id.getQualifier().toString(); aoqi@0: qualifiedName = packageName + NAME_SEPARATOR + name; aoqi@0: } else { aoqi@0: qualifiedName = name; aoqi@0: } aoqi@0: aoqi@0: setIDLNames(idlModuleNames,idlName); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Set IDL name. May only be called during initialization. aoqi@0: */ aoqi@0: protected void setIDLNames(String[] idlModuleNames, String idlName) { aoqi@0: this.idlName = idlName; aoqi@0: aoqi@0: if (idlModuleNames != null) { aoqi@0: this.idlModuleNames = idlModuleNames; aoqi@0: } else { aoqi@0: this.idlModuleNames = new String[0]; aoqi@0: } aoqi@0: qualifiedIDLName = IDLNames.getQualifiedName(idlModuleNames,idlName); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a ClassNotFoundException thru the compiler environment. aoqi@0: */ aoqi@0: protected static void classNotFound(ContextStack stack, aoqi@0: ClassNotFound e) { aoqi@0: classNotFound(false,stack,e); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a ClassNotFoundException thru the compiler environment. aoqi@0: */ aoqi@0: protected static void classNotFound(boolean quiet, aoqi@0: ContextStack stack, aoqi@0: ClassNotFound e) { aoqi@0: if (!quiet) stack.getEnv().error(0, "rmic.class.not.found", e.name); aoqi@0: stack.traceCallStack(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a constraint failure thru the compiler environment. aoqi@0: * @param constraintNum Used to generate a key of the form aoqi@0: "rmic.iiop.constraint.N", which must identify a message aoqi@0: in the "rmic.properties" file. aoqi@0: * @param quiet True if should not cause failure or message. aoqi@0: * @param stack The context stack. aoqi@0: * @param arg0 An object to substitute for {0} in the message. aoqi@0: * @param arg1 An object to substitute for {1} in the message. aoqi@0: * @param arg2 An object to substitute for {2} in the message. aoqi@0: * @return false. aoqi@0: */ aoqi@0: protected static boolean failedConstraint(int constraintNum, aoqi@0: boolean quiet, aoqi@0: ContextStack stack, aoqi@0: Object arg0, Object arg1, Object arg2) { aoqi@0: String message = "rmic.iiop.constraint." + constraintNum; aoqi@0: aoqi@0: if (!quiet) { aoqi@0: stack.getEnv().error(0,message, aoqi@0: (arg0 != null ? arg0.toString() : null), aoqi@0: (arg1 != null ? arg1.toString() : null), aoqi@0: (arg2 != null ? arg2.toString() : null)); aoqi@0: } else { aoqi@0: String error = stack.getEnv().errorString(message,arg0,arg1,arg2); aoqi@0: stack.traceln(error); aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a constraint failure thru the compiler environment. aoqi@0: * @param constraintNum Used to generate a key of the form aoqi@0: "rmic.iiop.constraint.N", which must identify a message aoqi@0: in the "rmic.properties" file. aoqi@0: * @param quiet True if should not cause failure or message. aoqi@0: * @param stack The context stack. aoqi@0: * @param arg0 An object to substitute for {0} in the message. aoqi@0: * @param arg1 An object to substitute for {1} in the message. aoqi@0: * @return false. aoqi@0: */ aoqi@0: protected static boolean failedConstraint(int constraintNum, aoqi@0: boolean quiet, aoqi@0: ContextStack stack, aoqi@0: Object arg0, Object arg1) { aoqi@0: return failedConstraint(constraintNum,quiet,stack,arg0,arg1,null); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Report a constraint failure thru the compiler environment. aoqi@0: * @param constraintNum Used to generate a key of the form aoqi@0: "rmic.iiop.constraint.N", which must identify a message aoqi@0: in the "rmic.properties" file. aoqi@0: * @param quiet True if should not cause failure or message. aoqi@0: * @param stack The context stack. aoqi@0: * @param arg0 An object to substitute for {0} in the message. aoqi@0: * @return false. aoqi@0: */ aoqi@0: protected static boolean failedConstraint(int constraintNum, aoqi@0: boolean quiet, aoqi@0: ContextStack stack, aoqi@0: Object arg0) { aoqi@0: return failedConstraint(constraintNum,quiet,stack,arg0,null,null); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a constraint failure thru the compiler environment. aoqi@0: * @param quiet True if should not cause failure or message. aoqi@0: * @param stack The context stack. aoqi@0: * @param constraintNum Used to generate a key of the form aoqi@0: "rmic.iiop.constraint.N", which must identify a message aoqi@0: in the "rmic.properties" file. aoqi@0: * @return false. aoqi@0: */ aoqi@0: protected static boolean failedConstraint(int constraintNum, aoqi@0: boolean quiet, aoqi@0: ContextStack stack) { aoqi@0: return failedConstraint(constraintNum,quiet,stack,null,null,null); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Cloning is supported by returning a shallow copy of this object. aoqi@0: */ aoqi@0: protected Object clone() { aoqi@0: try { aoqi@0: return super.clone(); aoqi@0: } catch (CloneNotSupportedException e) { aoqi@0: throw new Error("clone failed"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Add matching types to list. Return true if this type has not aoqi@0: * been previously checked, false otherwise. aoqi@0: */ aoqi@0: protected boolean addTypes (int typeCodeFilter, aoqi@0: HashSet checked, aoqi@0: Vector matching) { aoqi@0: aoqi@0: boolean result; aoqi@0: aoqi@0: // Have we already checked this type? aoqi@0: aoqi@0: if (checked.contains(this)) { aoqi@0: aoqi@0: // Yes, so return false. aoqi@0: aoqi@0: result = false; aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // Nope, so add it... aoqi@0: aoqi@0: checked.add(this); aoqi@0: aoqi@0: // Do we match the filter? aoqi@0: aoqi@0: if (typeMatches(typeCodeFilter)) { aoqi@0: aoqi@0: // Yep. so add it and set result to true... aoqi@0: aoqi@0: matching.addElement(this); aoqi@0: } aoqi@0: aoqi@0: // Return true. aoqi@0: aoqi@0: result = true; aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Load a Class instance. Return null if fail. aoqi@0: */ aoqi@0: protected abstract Class loadClass(); aoqi@0: aoqi@0: private boolean initClass() { aoqi@0: if (ourClass == null) { aoqi@0: ourClass = loadClass(); aoqi@0: if (ourClass == null) { aoqi@0: failedConstraint(27,false,stack,getQualifiedName()); aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Set the clz and repositoryID fields. Reports error aoqi@0: * and returns false if fails, returns true if succeeds. aoqi@0: */ aoqi@0: protected boolean setRepositoryID() { aoqi@0: aoqi@0: // First, load the class... aoqi@0: aoqi@0: if (!initClass()) { aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // Now make the repositoryID and return success... aoqi@0: aoqi@0: repositoryID = RepositoryId.createForAnyType(ourClass); aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Internal Interfaces aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: private Type () {} // Disallowed. aoqi@0: }