Type.java revision 672:2bb058ce572e
1210284Sjmallett/*
2232812Sjmallett * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
3215990Sjmallett * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4210284Sjmallett *
5210284Sjmallett * This code is free software; you can redistribute it and/or modify it
6215990Sjmallett * under the terms of the GNU General Public License version 2 only, as
7215990Sjmallett * published by the Free Software Foundation.  Oracle designates this
8215990Sjmallett * particular file as subject to the "Classpath" exception as provided
9210284Sjmallett * by Oracle in the LICENSE file that accompanied this code.
10215990Sjmallett *
11215990Sjmallett * This code is distributed in the hope that it will be useful, but WITHOUT
12210284Sjmallett * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13215990Sjmallett * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14215990Sjmallett * version 2 for more details (a copy is included in the LICENSE file that
15215990Sjmallett * accompanied this code).
16215990Sjmallett *
17210284Sjmallett * You should have received a copy of the GNU General Public License version
18232812Sjmallett * 2 along with this work; if not, write to the Free Software Foundation,
19215990Sjmallett * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20215990Sjmallett *
21215990Sjmallett * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22210284Sjmallett * or visit www.oracle.com if you need additional information or have any
23215990Sjmallett * questions.
24215990Sjmallett */
25215990Sjmallett
26215990Sjmallett/*
27210284Sjmallett * Licensed Materials - Property of IBM
28215990Sjmallett * RMI-IIOP v1.0
29232812Sjmallett * Copyright IBM Corp. 1998 1999  All Rights Reserved
30215990Sjmallett *
31215990Sjmallett */
32215990Sjmallett
33215990Sjmallettpackage sun.rmi.rmic.iiop;
34215990Sjmallett
35215990Sjmallettimport java.util.Vector;
36215990Sjmallettimport java.util.Hashtable;
37215990Sjmallettimport java.util.Enumeration;
38215990Sjmallettimport java.io.IOException;
39210284Sjmallettimport sun.tools.java.ClassDefinition;
40210284Sjmallettimport sun.tools.java.ClassDeclaration;
41210284Sjmallettimport sun.tools.java.Identifier;
42210284Sjmallettimport sun.tools.java.ClassNotFound;
43210284Sjmallettimport sun.tools.java.CompilerError;
44210284Sjmallettimport sun.rmi.rmic.IndentingWriter;
45210284Sjmallettimport java.util.HashSet;
46232812Sjmallettimport com.sun.corba.se.impl.util.RepositoryId;
47210284Sjmallettimport sun.rmi.rmic.Names;
48210284Sjmallett
49210284Sjmallett/**
50210284Sjmallett * Type is an abstract base class for a family of types which provide
51210284Sjmallett * conformance checking and name mapping as defined in the "Java to IDL
52210284Sjmallett * Mapping" OMG specification.  The family is composed of the following
53210284Sjmallett * fixed set of types:
54210284Sjmallett * <pre>{@literal
55215990Sjmallett *
56215990Sjmallett *                                              +- RemoteType <-- AbstractType
57215990Sjmallett *                                              |
58210284Sjmallett *                           +- InterfaceType <-+- SpecialInterfaceType
59210284Sjmallett *         +- PrimitiveType  |                  |
60210284Sjmallett *         |                 |                  +- NCInterfaceType
61215990Sjmallett *  Type <-+- CompoundType <-|
62210284Sjmallett *         |                 |                  +- ValueType
63232812Sjmallett *         +- ArrayType      |                  |
64232812Sjmallett *                           +- ClassType <-----+- ImplementationType
65215990Sjmallett *                                              |
66232812Sjmallett *                                              +- SpecialClassType
67210284Sjmallett *                                              |
68210284Sjmallett *                                              +- NCClassType
69210284Sjmallett *
70210284Sjmallett * }</pre>
71232812Sjmallett * PrimitiveType represents a primitive or a void type.
72210284Sjmallett * <p>
73215990Sjmallett * CompoundType is an abstract base representing any non-special class
74215990Sjmallett * or interface type.
75215990Sjmallett * <p>
76210284Sjmallett * InterfaceType is an abstract base representing any non-special
77210284Sjmallett * interface type.
78210284Sjmallett * <p>
79215990Sjmallett * RemoteType represents any non-special interface which inherits
80210284Sjmallett * from java.rmi.Remote.
81215990Sjmallett * <p>
82210284Sjmallett * AbstractType represents any non-special interface which does not
83215990Sjmallett * inherit from java.rmi.Remote, for which all methods throw RemoteException.
84210284Sjmallett * <p>
85215990Sjmallett * SpecialInterfaceType represents any one of the following types:
86210284Sjmallett * <pre>
87215990Sjmallett *    java.rmi.Remote
88210284Sjmallett *    java.io.Serializable
89215990Sjmallett *    java.io.Externalizable
90210284Sjmallett * </pre>
91215990Sjmallett * all of which are treated as special cases.
92210284Sjmallett * <p>
93215990Sjmallett * NCInterfaceType represents any non-special, non-conforming interface.
94210284Sjmallett * <p>
95215990Sjmallett * ClassType is an abstract base representing any non-special class
96210284Sjmallett * type.
97215990Sjmallett * <p>
98210284Sjmallett * ValueType represents any non-special class which does inherit from
99210284Sjmallett * java.io.Serializable and does not inherit from java.rmi.Remote.
100210284Sjmallett * <p>
101210284Sjmallett * ImplementationType represents any non-special class which implements
102210284Sjmallett * one or more interfaces which inherit from java.rmi.Remote.
103210284Sjmallett * <p>
104210284Sjmallett * SpecialClassType represents any one of the following types:
105215990Sjmallett * <pre>
106210284Sjmallett *    java.lang.Object
107215990Sjmallett *    java.lang.String
108210284Sjmallett *    org.omg.CORBA.Object
109215990Sjmallett * </pre>
110210284Sjmallett * all of which are treated as special cases. For all but CORBA.Object,
111215990Sjmallett * the type must match exactly. For CORBA.Object, the type must either be
112210284Sjmallett * CORBA.Object or inherit from it.
113215990Sjmallett * <p>
114210284Sjmallett * NCClassType represents any non-special, non-conforming class.
115215990Sjmallett * <p>
116210284Sjmallett * ArrayType is a wrapper for any of the other types. The getElementType()
117210284Sjmallett * method can be used to get the array element type.  The getArrayDimension()
118210284Sjmallett * method can be used to get the array dimension.
119210284Sjmallett * <p>
120210284Sjmallett * <i><strong>NOTE:</strong> None of these types is multi-thread-safe</i>
121210284Sjmallett * @author      Bryan Atsatt
122210284Sjmallett */
123210284Sjmallettpublic abstract class Type implements sun.rmi.rmic.iiop.Constants, ContextElement, Cloneable {
124210284Sjmallett
125210284Sjmallett    private int typeCode;
126210284Sjmallett    private int fullTypeCode;
127210284Sjmallett    private Identifier id;
128210284Sjmallett
129210284Sjmallett    private String name;
130210284Sjmallett    private String packageName;
131210284Sjmallett    private String qualifiedName;
132210284Sjmallett
133210284Sjmallett    private String idlName;
134215990Sjmallett    private String[] idlModuleNames;
135215990Sjmallett    private String qualifiedIDLName;
136215990Sjmallett
137215990Sjmallett    private String repositoryID;
138215990Sjmallett    private Class ourClass;
139215990Sjmallett
140215990Sjmallett    private int status = STATUS_PENDING;
141215990Sjmallett
142215990Sjmallett    protected BatchEnvironment env;     // Easy access for subclasses.
143215990Sjmallett    protected ContextStack stack;       // Easy access for subclasses.
144215990Sjmallett
145215990Sjmallett    protected boolean destroyed = false;
146215990Sjmallett
147215990Sjmallett    //_____________________________________________________________________
148215990Sjmallett    // Public Interfaces
149215990Sjmallett    //_____________________________________________________________________
150215990Sjmallett
151215990Sjmallett    /**
152215990Sjmallett     * Return the unqualified name for this type (e.g. com.acme.Dynamite would
153215990Sjmallett     * return "Dynamite").
154215990Sjmallett     */
155215990Sjmallett    public String getName() {
156215990Sjmallett        return name;
157215990Sjmallett    }
158215990Sjmallett
159210284Sjmallett    /**
160210284Sjmallett     * Return the package of this type (e.g. com.acme.Dynamite would
161210284Sjmallett     * return "com.acme"). Will return null if default package or
162210284Sjmallett     * if this type is a primitive.
163210284Sjmallett     */
164210284Sjmallett    public String getPackageName() {
165210284Sjmallett        return packageName;
166210284Sjmallett    }
167210284Sjmallett
168210284Sjmallett    /**
169210284Sjmallett     * Return the fully qualified name of this type  (e.g. com.acme.Dynamite
170210284Sjmallett     * would return "com.acme.Dynamite")
171210284Sjmallett     */
172210284Sjmallett    public String getQualifiedName() {
173210284Sjmallett        return qualifiedName;
174210284Sjmallett    }
175210284Sjmallett
176210284Sjmallett    /**
177210284Sjmallett     * Return signature for this type  (e.g. com.acme.Dynamite
178210284Sjmallett     * would return "com.acme.Dynamite", byte = "B")
179210284Sjmallett     */
180210284Sjmallett    public abstract String getSignature();
181210284Sjmallett
182210284Sjmallett    /**
183210284Sjmallett     * IDL_Naming
184210284Sjmallett     * Return the unqualified IDL name of this type (e.g. com.acme.Dynamite would
185210284Sjmallett     * return "Dynamite").
186210284Sjmallett     */
187210284Sjmallett    public String getIDLName() {
188210284Sjmallett        return idlName;
189210284Sjmallett    }
190210284Sjmallett
191210284Sjmallett    /**
192210284Sjmallett     * IDL_Naming
193210284Sjmallett     * Return the IDL module name for this type (e.g. com.acme.Dynamite would return
194210284Sjmallett     * a three element array of {"com","acme"). May be a zero length array if
195210284Sjmallett     * there is no module name.
196210284Sjmallett     */
197210284Sjmallett    public String[] getIDLModuleNames() {
198210284Sjmallett        return idlModuleNames;
199210284Sjmallett    }
200210284Sjmallett
201210284Sjmallett    /**
202210284Sjmallett     * IDL_Naming
203210284Sjmallett     * Return the fully qualified IDL name for this type (e.g. com.acme.Dynamite would
204210284Sjmallett     * return "com::acme::Dynamite").
205232812Sjmallett     * @param global If true, prepends "::".
206232812Sjmallett     */
207232812Sjmallett    public String getQualifiedIDLName(boolean global) {
208232812Sjmallett        if (global && getIDLModuleNames().length > 0) {
209232812Sjmallett            return IDL_NAME_SEPARATOR + qualifiedIDLName;
210232812Sjmallett        } else {
211232812Sjmallett            return qualifiedIDLName;
212232812Sjmallett        }
213232812Sjmallett    }
214232812Sjmallett
215232812Sjmallett    /**
216232812Sjmallett     * Return the identifier for this type. May be qualified.
217232812Sjmallett     */
218232812Sjmallett    public Identifier getIdentifier() {
219232812Sjmallett        return id;
220232812Sjmallett    }
221232812Sjmallett
222232812Sjmallett    /**
223232812Sjmallett     * Return the repository ID for this type.
224232812Sjmallett     */
225232812Sjmallett    public String getRepositoryID() {
226232812Sjmallett        return repositoryID;
227232812Sjmallett    }
228232812Sjmallett
229232812Sjmallett    /**
230232812Sjmallett     * Return the repository ID for this "boxed" type.
231232812Sjmallett     */
232232812Sjmallett    public String getBoxedRepositoryID() {
233232812Sjmallett        return RepositoryId.createForJavaType(ourClass);
234232812Sjmallett    }
235232812Sjmallett
236232812Sjmallett    /**
237232812Sjmallett     * Return the Class for this type.
238232812Sjmallett     */
239210284Sjmallett    public Class getClassInstance() {
240210284Sjmallett        if (ourClass == null) {
241210284Sjmallett            initClass();
242210284Sjmallett        }
243210284Sjmallett        return ourClass;
244210284Sjmallett    }
245210284Sjmallett
246210284Sjmallett    /**
247210284Sjmallett     * Return the status of this type.
248210284Sjmallett     */
249210284Sjmallett    public int getStatus() {
250210284Sjmallett        return status;
251210284Sjmallett    }
252210284Sjmallett
253210284Sjmallett    /**
254210284Sjmallett     * Set the status of this type.
255210284Sjmallett     */
256210284Sjmallett    public void setStatus(int status) {
257232812Sjmallett        this.status = status;
258232812Sjmallett    }
259232812Sjmallett
260215990Sjmallett    /**
261215990Sjmallett     * Return the compiler environment for this type.
262215990Sjmallett     */
263215990Sjmallett    public BatchEnvironment getEnv() {
264215990Sjmallett        return env;
265215990Sjmallett    }
266215990Sjmallett
267215990Sjmallett    /**
268215990Sjmallett     * Get type code, without modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
269215990Sjmallett     */
270215990Sjmallett    public int getTypeCode() {
271215990Sjmallett        return typeCode;
272215990Sjmallett    }
273215990Sjmallett
274215990Sjmallett    /**
275215990Sjmallett     * Get type code, with modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
276210284Sjmallett     */
277210284Sjmallett    public int getFullTypeCode() {
278210284Sjmallett        return fullTypeCode;
279210284Sjmallett    }
280210284Sjmallett
281210284Sjmallett    /**
282210284Sjmallett     * Get type code modifiers. Type codes are defined in sun.rmi.rmic.iiop.Constants.
283210284Sjmallett     */
284215990Sjmallett    public int getTypeCodeModifiers() {
285210284Sjmallett        return fullTypeCode & TM_MASK;
286210284Sjmallett    }
287210284Sjmallett
288210284Sjmallett    /**
289210284Sjmallett     * Check for a certain type. Type codes are defined in sun.rmi.rmic.iiop.Constants.
290210284Sjmallett     * Returns true if all of the bits in typeCodeMask are present in the full type code
291210284Sjmallett     * of this object.
292210284Sjmallett     */
293210284Sjmallett    public boolean isType(int typeCodeMask) {
294210284Sjmallett        return (fullTypeCode & typeCodeMask) == typeCodeMask;
295215990Sjmallett    }
296215990Sjmallett
297210284Sjmallett    /**
298210284Sjmallett     * Like isType(), but returns true if <em>any</em> of the bits in typeCodeMask are
299232812Sjmallett     * present in the full type code of this object.
300232812Sjmallett     */
301232812Sjmallett    public boolean typeMatches(int typeCodeMask) {
302210284Sjmallett        return (fullTypeCode & typeCodeMask) > 0;
303232812Sjmallett    }
304232812Sjmallett
305232812Sjmallett
306210284Sjmallett    /**
307232812Sjmallett     * Return the fullTypeCode. If an array, returns the
308232812Sjmallett     * type code from the element type.
309210284Sjmallett     */
310232812Sjmallett    public int getRootTypeCode() {
311232812Sjmallett        if (isArray()) {
312210284Sjmallett            return getElementType().getFullTypeCode();
313210284Sjmallett        } else {
314210284Sjmallett            return fullTypeCode;
315210284Sjmallett        }
316210284Sjmallett    }
317210284Sjmallett
318210284Sjmallett    /**
319210284Sjmallett     * Return true if this type is-a InterfaceType.
320210284Sjmallett     */
321210284Sjmallett    public boolean isInterface() {
322210284Sjmallett        return (fullTypeCode & TM_INTERFACE) == TM_INTERFACE;
323210284Sjmallett    }
324232812Sjmallett
325232812Sjmallett    /**
326232812Sjmallett     * Return true if this type is-a ClassType.
327232812Sjmallett     */
328232812Sjmallett    public boolean isClass() {
329232812Sjmallett        return (fullTypeCode & TM_CLASS) == TM_CLASS;
330232812Sjmallett    }
331232812Sjmallett
332232812Sjmallett    /**
333232812Sjmallett     * Return true if this type is-a inner class or interface.
334232812Sjmallett     */
335210284Sjmallett    public boolean isInner() {
336210284Sjmallett        return (fullTypeCode & TM_INNER) == TM_INNER;
337210284Sjmallett    }
338210284Sjmallett
339210284Sjmallett
340210284Sjmallett    /**
341210284Sjmallett     * Return true if this type is-a SpecialInterfaceType.
342210284Sjmallett     */
343210284Sjmallett    public boolean isSpecialInterface() {
344210284Sjmallett        return (fullTypeCode & TM_SPECIAL_INTERFACE) == TM_SPECIAL_INTERFACE;
345210284Sjmallett    }
346232812Sjmallett
347232812Sjmallett    /**
348232812Sjmallett     * Return true if this type is-a SpecialClassType.
349232812Sjmallett     */
350232812Sjmallett    public boolean isSpecialClass() {
351232812Sjmallett        return (fullTypeCode & TM_SPECIAL_CLASS) == TM_SPECIAL_CLASS;
352232812Sjmallett    }
353232812Sjmallett
354232812Sjmallett    /**
355232812Sjmallett     * Return true if this type is-a CompoundType.
356232812Sjmallett     */
357210284Sjmallett    public boolean isCompound() {
358210284Sjmallett        return (fullTypeCode & TM_COMPOUND) == TM_COMPOUND;
359210284Sjmallett    }
360210284Sjmallett
361210284Sjmallett    /**
362210284Sjmallett     * Return true if this type is-a PrimitiveType.
363232812Sjmallett     */
364210284Sjmallett    public boolean isPrimitive() {
365210284Sjmallett        return (fullTypeCode & TM_PRIMITIVE) == TM_PRIMITIVE;
366210284Sjmallett    }
367210284Sjmallett
368210284Sjmallett    /**
369210284Sjmallett     * Return true if this type is-a ArrayType.
370210284Sjmallett     */
371210284Sjmallett    public boolean isArray() {
372210284Sjmallett        return (fullTypeCode & TYPE_ARRAY) == TYPE_ARRAY;
373210284Sjmallett    }
374210284Sjmallett
375210284Sjmallett    /**
376210284Sjmallett     * Return true if this type is a conforming type.
377210284Sjmallett     */
378210284Sjmallett    public boolean isConforming() {
379210284Sjmallett        return (fullTypeCode & TM_NON_CONFORMING) == TM_NON_CONFORMING;
380232812Sjmallett    }
381232812Sjmallett
382210284Sjmallett    /**
383210284Sjmallett     * Return a string representation of this type.
384210284Sjmallett     */
385232812Sjmallett    public String toString () {
386232812Sjmallett        return getQualifiedName();
387210284Sjmallett    }
388210284Sjmallett
389210284Sjmallett    /**
390210284Sjmallett     * Get element type. Returns null if not an array.
391210284Sjmallett     */
392232812Sjmallett    public Type getElementType () {
393215990Sjmallett        return null;
394232812Sjmallett    }
395232812Sjmallett
396232812Sjmallett    /**
397232812Sjmallett     * Get array dimension. Returns zero if not an array.
398232812Sjmallett     */
399232812Sjmallett    public int getArrayDimension () {
400232812Sjmallett        return 0;
401232812Sjmallett    }
402232812Sjmallett
403232812Sjmallett    /**
404232812Sjmallett     * Get brackets string. Returns "" if not an array.
405232812Sjmallett     */
406232812Sjmallett    public String getArrayBrackets () {
407232812Sjmallett        return "";
408232812Sjmallett    }
409232812Sjmallett
410215990Sjmallett    /**
411232812Sjmallett     * Equality check based on the string representation.
412232812Sjmallett     */
413232812Sjmallett    public boolean equals(Object obj) {
414232812Sjmallett
415232812Sjmallett        String us = toString();
416232812Sjmallett        String them = ((Type)obj).toString();
417232812Sjmallett        return us.equals(them);
418232812Sjmallett    }
419232812Sjmallett
420232812Sjmallett    /**
421232812Sjmallett     * Collect all the matching types referenced directly or indirectly
422232812Sjmallett     * by this type, including itself.
423232812Sjmallett     * @param typeCodeFilter The typeCode to use as a filter.
424232812Sjmallett     */
425232812Sjmallett    public Type[] collectMatching (int typeCodeFilter) {
426232812Sjmallett        return collectMatching(typeCodeFilter,new HashSet(env.allTypes.size()));
427232812Sjmallett    }
428232812Sjmallett
429232812Sjmallett    /**
430232812Sjmallett     * Collect all the matching types referenced directly or indirectly
431232812Sjmallett     * by this type, including itself.
432232812Sjmallett     * @param typeCodeFilter The typeCode to use as a filter.
433232812Sjmallett     * @param alreadyChecked Contains types which have previously been checked
434232812Sjmallett     * and will be ignored. Updated during collection.
435232812Sjmallett     */
436232812Sjmallett    public Type[] collectMatching (int typeCodeFilter, HashSet alreadyChecked) {
437232812Sjmallett        Vector matching = new Vector();
438232812Sjmallett
439232812Sjmallett        // Fill up the list...
440232812Sjmallett
441232812Sjmallett        addTypes(typeCodeFilter,alreadyChecked,matching);
442232812Sjmallett
443232812Sjmallett        // Copy vector contents to array and return it...
444232812Sjmallett
445232812Sjmallett        Type[] result = new Type[matching.size()];
446232812Sjmallett        matching.copyInto(result);
447232812Sjmallett
448232812Sjmallett        return result;
449232812Sjmallett    }
450232812Sjmallett
451232812Sjmallett    /**
452232812Sjmallett     * Return a string describing this type.
453232812Sjmallett     */
454232812Sjmallett    public abstract String getTypeDescription ();
455232812Sjmallett
456232812Sjmallett    /**
457232812Sjmallett     * Return the name of this type. For arrays, will include "[]" if useIDLNames == false.
458232812Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
459232812Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
460232812Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
461215990Sjmallett     */
462215990Sjmallett    public String getTypeName ( boolean useQualifiedNames,
463232812Sjmallett                                boolean useIDLNames,
464232812Sjmallett                                boolean globalIDLNames) {
465232812Sjmallett        if (useIDLNames) {
466215990Sjmallett            if (useQualifiedNames) {
467210284Sjmallett                return getQualifiedIDLName(globalIDLNames);
468210284Sjmallett            } else {
469210284Sjmallett                return getIDLName();
470210284Sjmallett            }
471210284Sjmallett        } else {
472210284Sjmallett            if (useQualifiedNames) {
473210284Sjmallett                return getQualifiedName();
474210284Sjmallett            } else {
475210284Sjmallett                return getName();
476210284Sjmallett            }
477210284Sjmallett        }
478210284Sjmallett    }
479210284Sjmallett
480210284Sjmallett    /**
481210284Sjmallett     * Print all types referenced directly or indirectly by this type which
482210284Sjmallett     * match the filter.
483210284Sjmallett     * @param writer The stream to print to.
484210284Sjmallett     * @param typeCodeFilter The type codes to print.
485210284Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
486210284Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
487232812Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
488232812Sjmallett     */
489232812Sjmallett    public void print ( IndentingWriter writer,
490232812Sjmallett                        int typeCodeFilter,
491232812Sjmallett                        boolean useQualifiedNames,
492232812Sjmallett                        boolean useIDLNames,
493232812Sjmallett                        boolean globalIDLNames) throws IOException {
494232812Sjmallett
495232812Sjmallett        Type[] theTypes = collectMatching(typeCodeFilter);
496232812Sjmallett        print(writer,theTypes,useQualifiedNames,useIDLNames,globalIDLNames);
497210284Sjmallett    }
498210284Sjmallett
499210284Sjmallett    /**
500210284Sjmallett     * Print an array of types.
501210284Sjmallett     * @param writer The stream to print to.
502210284Sjmallett     * @param theTypes The types to print.
503210284Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
504210284Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
505210284Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
506210284Sjmallett     */
507210284Sjmallett    public static void print (  IndentingWriter writer,
508210284Sjmallett                                Type[] theTypes,
509210284Sjmallett                                boolean useQualifiedNames,
510210284Sjmallett                                boolean useIDLNames,
511210284Sjmallett                                boolean globalIDLNames) throws IOException {
512210284Sjmallett
513210284Sjmallett        for (int i = 0; i < theTypes.length; i++) {
514210284Sjmallett            theTypes[i].println(writer,useQualifiedNames,useIDLNames,globalIDLNames);
515210284Sjmallett        }
516210284Sjmallett    }
517210284Sjmallett
518210284Sjmallett
519210284Sjmallett    /**
520210284Sjmallett     * Print this type.
521210284Sjmallett     * @param writer The stream to print to.
522210284Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
523210284Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
524210284Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
525210284Sjmallett     */
526210284Sjmallett    public void print ( IndentingWriter writer,
527210284Sjmallett                        boolean useQualifiedNames,
528210284Sjmallett                        boolean useIDLNames,
529210284Sjmallett                        boolean globalIDLNames) throws IOException {
530210284Sjmallett        printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
531210284Sjmallett    }
532210284Sjmallett
533210284Sjmallett    /**
534210284Sjmallett     * Print this type, followed by a newline.
535210284Sjmallett     * @param writer The stream to print to.
536210284Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
537210284Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
538210284Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
539210284Sjmallett     */
540210284Sjmallett    public void println (       IndentingWriter writer,
541210284Sjmallett                                boolean useQualifiedNames,
542210284Sjmallett                                boolean useIDLNames,
543210284Sjmallett                                boolean globalIDLNames) throws IOException  {
544210284Sjmallett
545210284Sjmallett        print(writer,useQualifiedNames,useIDLNames,globalIDLNames);
546210284Sjmallett        writer.pln();
547210284Sjmallett    }
548210284Sjmallett
549210284Sjmallett
550210284Sjmallett
551210284Sjmallett    /**
552210284Sjmallett     * Print the name of this type.
553210284Sjmallett     * @param writer The stream to print to.
554210284Sjmallett     * @param useQualifiedNames If true, print qualified names; otherwise, print unqualified names.
555210284Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
556210284Sjmallett     * @param globalIDLNames If true and useIDLNames true, prepends "::".
557210284Sjmallett     */
558210284Sjmallett    public void printTypeName ( IndentingWriter writer,
559210284Sjmallett                                boolean useQualifiedNames,
560210284Sjmallett                                boolean useIDLNames,
561210284Sjmallett                                boolean globalIDLNames) throws IOException {
562210284Sjmallett
563210284Sjmallett        writer.p(getTypeName(useQualifiedNames,useIDLNames,globalIDLNames));
564210284Sjmallett    }
565210284Sjmallett
566210284Sjmallett    /**
567210284Sjmallett     * Return context element name.
568210284Sjmallett     */
569210284Sjmallett    public String getElementName() {
570210284Sjmallett        return getQualifiedName();
571210284Sjmallett    }
572210284Sjmallett
573210284Sjmallett    //_____________________________________________________________________
574210284Sjmallett    // Subclass Interfaces
575210284Sjmallett    //_____________________________________________________________________
576210284Sjmallett
577210284Sjmallett    /**
578210284Sjmallett     * Print the "opening" of the package or module of this type.
579232812Sjmallett     * @param writer The stream to print to.
580232812Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
581232812Sjmallett     */
582232812Sjmallett    protected void printPackageOpen (   IndentingWriter writer,
583232812Sjmallett                                        boolean useIDLNames) throws IOException {
584232812Sjmallett
585232812Sjmallett        if (useIDLNames) {
586232812Sjmallett            String[] moduleNames = getIDLModuleNames();
587232812Sjmallett            for (int i = 0; i < moduleNames.length; i++ ) {
588232812Sjmallett                writer.plnI("module " + moduleNames[i] + " {");
589232812Sjmallett            }
590232812Sjmallett        } else {
591232812Sjmallett            String packageName = getPackageName();
592232812Sjmallett            if (packageName != null) {
593232812Sjmallett                writer.pln("package " + packageName + ";");
594232812Sjmallett            }
595232812Sjmallett        }
596232812Sjmallett    }
597232812Sjmallett
598232812Sjmallett    /**
599232812Sjmallett     * Get a type out of the table.
600232812Sjmallett     */
601232812Sjmallett    protected static Type getType (sun.tools.java.Type key, ContextStack stack) {
602232812Sjmallett        return getType(key.toString(),stack);
603232812Sjmallett    }
604232812Sjmallett
605232812Sjmallett    /**
606232812Sjmallett     * Get a type out of the table.
607232812Sjmallett     */
608232812Sjmallett    protected static Type getType (String key, ContextStack stack) {
609232812Sjmallett        Type result = (Type) stack.getEnv().allTypes.get(key);
610232812Sjmallett
611232812Sjmallett        if (result != null) {
612232812Sjmallett            stack.traceExistingType(result);
613232812Sjmallett        }
614232812Sjmallett
615232812Sjmallett        return result;
616232812Sjmallett    }
617232812Sjmallett
618232812Sjmallett    /**
619232812Sjmallett     * Remove a type from the table.
620232812Sjmallett     */
621232812Sjmallett    protected static void removeType (String key, ContextStack stack) {
622232812Sjmallett        Type value = (Type) stack.getEnv().allTypes.remove(key);
623232812Sjmallett        stack.getEnv().invalidTypes.put(value,key);
624232812Sjmallett    }
625232812Sjmallett
626232812Sjmallett    /**
627232812Sjmallett     * Remove a type from the table.
628232812Sjmallett     */
629232812Sjmallett    protected static void removeType (sun.tools.java.Type key, ContextStack stack) {
630232812Sjmallett        String theKey = key.toString();
631232812Sjmallett        Type old = (Type) stack.getEnv().allTypes.remove(theKey);
632232812Sjmallett        putInvalidType(old,theKey,stack);
633232812Sjmallett    }
634232812Sjmallett
635232812Sjmallett    /**
636232812Sjmallett     * Put a type into the table.
637232812Sjmallett     */
638232812Sjmallett    protected static void putType (sun.tools.java.Type key, Type value, ContextStack stack) {
639232812Sjmallett        stack.getEnv().allTypes.put(key.toString(),value);
640232812Sjmallett    }
641232812Sjmallett
642232812Sjmallett    /**
643232812Sjmallett     * Put a type into the table.
644232812Sjmallett     */
645232812Sjmallett    protected static void putType (String key, Type value, ContextStack stack) {
646232812Sjmallett        stack.getEnv().allTypes.put(key,value);
647232812Sjmallett    }
648232812Sjmallett
649232812Sjmallett    /**
650232812Sjmallett     * Put an invalid type into the.
651232812Sjmallett     */
652232812Sjmallett    protected static void putInvalidType (Type key, String value, ContextStack stack) {
653232812Sjmallett        stack.getEnv().invalidTypes.put(key,value);
654232812Sjmallett    }
655232812Sjmallett
656232812Sjmallett
657232812Sjmallett    /**
658232812Sjmallett     * Remove all invalid types...
659232812Sjmallett     */
660232812Sjmallett    public void removeInvalidTypes () {
661232812Sjmallett        if (env.invalidTypes.size() > 0) {
662232812Sjmallett            env.invalidTypes.clear();
663232812Sjmallett        }
664232812Sjmallett    }
665232812Sjmallett
666232812Sjmallett    /**
667232812Sjmallett     * Walk all types and tell them to update invalid types...
668232812Sjmallett     */
669232812Sjmallett    protected static void updateAllInvalidTypes (ContextStack stack) {
670232812Sjmallett        BatchEnvironment env = stack.getEnv();
671232812Sjmallett        if (env.invalidTypes.size() > 0) {
672232812Sjmallett
673232812Sjmallett            // Walk all types and swap invalid...
674232812Sjmallett
675232812Sjmallett            for (Enumeration e = env.allTypes.elements() ; e.hasMoreElements() ;) {
676232812Sjmallett                Type it = (Type) e.nextElement();
677232812Sjmallett                it.swapInvalidTypes();
678232812Sjmallett            }
679232812Sjmallett
680232812Sjmallett            // Delete all invalidTypes...
681232812Sjmallett
682232812Sjmallett            env.invalidTypes.clear();
683232812Sjmallett        }
684232812Sjmallett    }
685232812Sjmallett
686232812Sjmallett    /**
687232812Sjmallett     * Return count of previously parsed types.
688232812Sjmallett     */
689232812Sjmallett    protected int countTypes () {
690232812Sjmallett        return env.allTypes.size();
691232812Sjmallett    }
692232812Sjmallett
693232812Sjmallett    /**
694232812Sjmallett     * Reset types removes all previously parsed types.
695232812Sjmallett     */
696232812Sjmallett    void resetTypes () {
697232812Sjmallett        env.reset();
698232812Sjmallett    }
699232812Sjmallett
700232812Sjmallett    /**
701232812Sjmallett     * Release all resources.
702232812Sjmallett     */
703232812Sjmallett    protected void destroy () {
704232812Sjmallett        if (!destroyed) {
705232812Sjmallett            id = null;
706232812Sjmallett            name = null;
707232812Sjmallett            packageName = null;
708232812Sjmallett            qualifiedName = null;
709232812Sjmallett            idlName = null;
710232812Sjmallett            idlModuleNames = null;
711232812Sjmallett            qualifiedIDLName = null;
712232812Sjmallett            repositoryID = null;
713232812Sjmallett            ourClass = null;
714232812Sjmallett            env = null;
715232812Sjmallett            stack = null;
716232812Sjmallett            destroyed = true;
717232812Sjmallett        }
718232812Sjmallett    }
719232812Sjmallett
720232812Sjmallett    /**
721232812Sjmallett     * Convert all invalid types to valid ones.
722232812Sjmallett     */
723232812Sjmallett    protected void swapInvalidTypes () {
724232812Sjmallett    }
725232812Sjmallett
726232812Sjmallett    /**
727232812Sjmallett     * Convert an invalid type to a valid one.
728232812Sjmallett     */
729232812Sjmallett    protected Type getValidType (Type invalidType) {
730232812Sjmallett        if (invalidType.getStatus() == STATUS_VALID) {
731232812Sjmallett            return invalidType;
732232812Sjmallett        }
733232812Sjmallett
734232812Sjmallett        String key = (String)env.invalidTypes.get(invalidType);
735232812Sjmallett        Type result = null;
736232812Sjmallett        if (key != null) {
737232812Sjmallett            result = (Type) env.allTypes.get(key);
738232812Sjmallett        }
739232812Sjmallett
740232812Sjmallett        if (result == null) {
741232812Sjmallett            throw new Error("Failed to find valid type to swap for " + invalidType + " mis-identified as " + invalidType.getTypeDescription());
742232812Sjmallett        }
743232812Sjmallett        //System.out.println("Swapped " + result + " from " + invalidType.getTypeDescription()
744232812Sjmallett        //    + " to " + result.getTypeDescription());
745232812Sjmallett        //ContextStack.dumpCallStack();
746232812Sjmallett        return result;
747232812Sjmallett    }
748232812Sjmallett
749232812Sjmallett    /**
750232812Sjmallett     * Print the "closing" of the package or module of this type.
751232812Sjmallett     * @param writer The stream to print to.
752232812Sjmallett     * @param useIDLNames If true, print IDL names; otherwise, print java names.
753232812Sjmallett     */
754232812Sjmallett    protected void printPackageClose (  IndentingWriter writer,
755232812Sjmallett                                        boolean useIDLNames) throws IOException {
756232812Sjmallett        if (useIDLNames) {
757232812Sjmallett            String[] moduleNames = getIDLModuleNames();
758232812Sjmallett            for (int i = 0; i < moduleNames.length; i++ ) {
759232812Sjmallett                writer.pOln("};");
760232812Sjmallett            }
761232812Sjmallett        }
762232812Sjmallett    }
763232812Sjmallett
764232812Sjmallett    /**
765232812Sjmallett     * Create a Type instance for the given type. Requires that
766232812Sjmallett     * setName(Identifier) be called afterward.
767232812Sjmallett     */
768232812Sjmallett    protected Type(ContextStack stack, int fullTypeCode) {
769232812Sjmallett        this.env = stack.getEnv();
770232812Sjmallett        this.stack = stack;
771232812Sjmallett        this.fullTypeCode = fullTypeCode;
772232812Sjmallett        typeCode = fullTypeCode & TYPE_MASK;
773232812Sjmallett    }
774232812Sjmallett
775232812Sjmallett    /**
776232812Sjmallett     * Set type codes. May only be called during initialization.
777232812Sjmallett     */
778232812Sjmallett    protected void setTypeCode(int fullTypeCode) {
779232812Sjmallett        this.fullTypeCode = fullTypeCode;
780232812Sjmallett        typeCode = fullTypeCode & TYPE_MASK;
781232812Sjmallett    }
782232812Sjmallett
783232812Sjmallett    /**
784232812Sjmallett     * Set name and package. May only be called during initialization.
785232812Sjmallett     */
786232812Sjmallett    protected void setNames(Identifier id, String[] idlModuleNames, String idlName) {
787232812Sjmallett
788232812Sjmallett        this.id = id;
789232812Sjmallett        name = Names.mangleClass(id).getName().toString();
790232812Sjmallett        packageName = null;
791232812Sjmallett
792232812Sjmallett        if (id.isQualified()) {
793232812Sjmallett            packageName = id.getQualifier().toString();
794232812Sjmallett            qualifiedName = packageName + NAME_SEPARATOR + name;
795232812Sjmallett        } else {
796232812Sjmallett            qualifiedName = name;
797232812Sjmallett        }
798232812Sjmallett
799232812Sjmallett        setIDLNames(idlModuleNames,idlName);
800232812Sjmallett    }
801232812Sjmallett
802210284Sjmallett
803210284Sjmallett    /**
804210284Sjmallett     * Set IDL name. May only be called during initialization.
805210284Sjmallett     */
806210284Sjmallett    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}
1010