Type.java revision 672:2bb058ce572e
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
33package sun.rmi.rmic.iiop;
34
35import java.util.Vector;
36import java.util.Hashtable;
37import java.util.Enumeration;
38import java.io.IOException;
39import sun.tools.java.ClassDefinition;
40import sun.tools.java.ClassDeclaration;
41import sun.tools.java.Identifier;
42import sun.tools.java.ClassNotFound;
43import sun.tools.java.CompilerError;
44import sun.rmi.rmic.IndentingWriter;
45import java.util.HashSet;
46import com.sun.corba.se.impl.util.RepositoryId;
47import 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 */
123public 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}
1010