CompoundType.java revision 673:6b017d166ac2
1/*
2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * Licensed Materials - Property of IBM
28 * RMI-IIOP v1.0
29 * Copyright IBM Corp. 1998 1999  All Rights Reserved
30 *
31 */
32
33package sun.rmi.rmic.iiop;
34
35import java.util.Arrays;
36import java.util.Vector;
37import sun.tools.java.Identifier;
38import sun.tools.java.ClassNotFound;
39import sun.tools.java.ClassDefinition;
40import sun.tools.java.ClassDeclaration;
41import sun.tools.java.MemberDefinition;
42import sun.tools.java.CompilerError;
43import sun.tools.tree.Node;
44import sun.tools.tree.LocalMember;
45import sun.tools.tree.CharExpression;
46import sun.tools.tree.IntegerExpression;
47import sun.rmi.rmic.IndentingWriter;
48import java.io.IOException;
49import java.util.HashSet;
50import java.util.Enumeration;
51import java.io.File;
52
53/**
54 * A CompoundType is an abstract base class for all IIOP class and
55 * interface types.
56 *
57 * @author      Bryan Atsatt
58 */
59public abstract class CompoundType extends Type {
60
61    protected Method[] methods;
62    protected InterfaceType[] interfaces;
63    protected Member[] members;
64    protected ClassDefinition classDef;
65    protected ClassDeclaration classDecl;
66
67    protected boolean isCORBAObject = false;
68    protected boolean isIDLEntity = false;
69    protected boolean isAbstractBase = false;
70    protected boolean isValueBase = false;
71    protected boolean isCORBAUserException = false;
72    protected boolean isException = false;
73    protected boolean isCheckedException = false;
74    protected boolean isRemoteExceptionOrSubclass = false;
75    protected String idlExceptionName;
76    protected String qualifiedIDLExceptionName;
77
78    //_____________________________________________________________________
79    // Public Interfaces
80    //_____________________________________________________________________
81
82    /**
83     * Return true if this type implements
84     * org.omg.CORBA.Object.
85     */
86    public boolean isCORBAObject () {
87        return isCORBAObject;
88    }
89
90    /**
91     * Return true if this type implements
92     * org.omg.CORBA.portable.IDLEntity.
93     */
94    public boolean isIDLEntity () {
95        return isIDLEntity;
96    }
97
98    /**
99     * Return true if this type implements
100     * org.omg.CORBA.portable.ValueBase.
101     */
102    public boolean isValueBase () {
103        return isValueBase;
104    }
105
106    /**
107     * Return true if this type is a CORBA
108     * abstract interface.
109     */
110    public boolean isAbstractBase () {
111        return isAbstractBase;
112    }
113
114    /**
115     * Return true if this type is an exception.
116     */
117    public boolean isException () {
118        return isException;
119    }
120
121    /**
122     * Return true if this type is a "checked" exception.
123     * Result if valid iff isException() returns true.
124     */
125    public boolean isCheckedException () {
126        return isCheckedException;
127    }
128
129    /**
130     * Return true if this type is a java.rmi.RemoteException
131     * or one of its subclasses. Result if valid iff isException()
132     * returns true.
133     */
134    public boolean isRemoteExceptionOrSubclass () {
135        return isRemoteExceptionOrSubclass;
136    }
137
138    /**
139     * Return true if this type is exactly
140     * org.omg.CORBA.UserException.
141     */
142    public boolean isCORBAUserException () {
143        return isCORBAUserException;
144    }
145
146    /**
147     * Return true if this type implements
148     * {@code isIDLEntity() && isException()}.
149     */
150    public boolean isIDLEntityException () {
151        return isIDLEntity() && isException();
152    }
153    /**
154     * Return true if {@code isIDLEntity() && !isValueBase()
155     * && !isAbstractBase() && !isCORBAObject()
156     * && !isIDLEntityException()}.
157     */
158    public boolean isBoxed () {
159        return (isIDLEntity() && !isValueBase() &&
160                !isAbstractBase() && !isCORBAObject() &&
161                !isIDLEntityException());
162    }
163
164    /**
165     * If this type represents an exception, return the
166     * IDL name including the "Ex" mangling, otherwise
167     * return null.
168     */
169    public String getIDLExceptionName () {
170        return idlExceptionName;
171    }
172
173    /**
174     * If this type represents an exception, return the
175     * qualified IDL name including the "Ex" mangling,
176     * otherwise return null.
177     * @param global If true, prepends "::".
178     */
179    public String getQualifiedIDLExceptionName (boolean global) {
180        if (qualifiedIDLExceptionName != null &&
181            global &&
182            getIDLModuleNames().length > 0) {
183            return IDL_NAME_SEPARATOR + qualifiedIDLExceptionName;
184        } else {
185            return qualifiedIDLExceptionName;
186        }
187    }
188
189    /**
190     * Return signature for this type  (e.g. com.acme.Dynamite
191     * would return "com.acme.Dynamite", byte = "B")
192     */
193    public String getSignature() {
194        String sig = classDecl.getType().getTypeSignature();
195        if (sig.endsWith(";")) {
196            sig = sig.substring(0,sig.length()-1);
197        }
198        return sig;
199    }
200
201    /**
202     * Return the ClassDeclaration for this type.
203     */
204    public ClassDeclaration getClassDeclaration() {
205        return classDecl;
206    }
207
208    /**
209     * Return the ClassDefinition for this type.
210     */
211    public ClassDefinition getClassDefinition() {
212        return classDef;
213    }
214
215    /**
216     * Return the parent class of this type. Returns null if this
217     * type is an interface or if there is no parent.
218     */
219    public ClassType getSuperclass() {
220        return null;
221    }
222
223    /**
224     * Return an array of interfaces directly implemented by this type.
225     * <p>
226     * The order of the array returned is arbitrary.
227     */
228    public InterfaceType[] getInterfaces() {
229        if( interfaces != null ) {
230            return (InterfaceType[]) interfaces.clone();
231        }
232        return null;
233    }
234
235    /**
236     * Return an array of Type.Method objects representing all
237     * of the methods implemented directly by this type.
238     */
239    public Method[] getMethods() {
240        if( methods != null ) {
241            return (Method[]) methods.clone();
242        }
243        return null;
244    }
245
246    /**
247     * Return an array of Type.Member objects representing all of
248     * the data members directly implemented by this interface.
249     */
250    public Member[] getMembers() {
251        if( members != null ) {
252            return (Member[]) members.clone();
253        }
254        return null;
255    }
256
257    /**
258     * Create a CompoundType object for the given class.
259     *
260     * If the class is not a properly formed or if some other error occurs, the
261     * return value will be null, and errors will have been reported to the
262     * supplied BatchEnvironment.
263     */
264    public static CompoundType forCompound (ClassDefinition classDef,
265                                            ContextStack stack) {
266        CompoundType result = null;
267
268        try {
269            result = (CompoundType) makeType(classDef.getType(),classDef,stack);
270        } catch (ClassCastException e) {}
271
272        return result;
273    }
274
275
276    //_____________________________________________________________________
277    // Subclass/Internal Interfaces
278    //_____________________________________________________________________
279
280    /**
281     * Release all resources.
282     */
283    protected void destroy () {
284        if (!destroyed) {
285            super.destroy();
286
287            if (methods != null) {
288                for (int i = 0; i < methods.length; i++) {
289                    if (methods[i] != null) methods[i].destroy();
290                }
291                methods = null;
292            }
293
294            if (interfaces != null) {
295                for (int i = 0; i < interfaces.length; i++) {
296                    if (interfaces[i] != null) interfaces[i].destroy();
297                }
298                interfaces = null;
299            }
300
301            if (members != null) {
302                for (int i = 0; i < members.length; i++) {
303                    if (members[i] != null) members[i].destroy();
304                }
305                members = null;
306            }
307
308            classDef = null;
309            classDecl = null;
310        }
311    }
312
313    /*
314     * Load a Class instance. Return null if fail.
315     */
316    protected Class loadClass() {
317
318        Class ourClass = null;
319
320        // To avoid getting out-of-date Class instances, and
321        // to ensure that there is an instance, we must compile
322        // any classes that we've seen and which are not yet
323        // compiled. We can't just compile this class, 'cuz it
324        // may have dependencies on classes which have not been
325        // compiled...
326
327        try {
328            env.getMain().compileAllClasses(env);
329        } catch (Exception e1) {
330            for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
331                ClassDeclaration c = (ClassDeclaration)e.nextElement();
332            }
333            failedConstraint(26,false,stack,"required classes");
334            env.flushErrors();
335        }
336
337        // Now try to get the Class...
338        // The outer try block is there for people who might want to use
339        // the compiler at run-time of their AS.
340        // They could set and use their own context class loader for loading
341        // classes directly.
342        try {
343            ClassLoader cl = Thread.currentThread().getContextClassLoader();
344            ourClass = cl.loadClass(getQualifiedName());
345        } catch(ClassNotFoundException cfe) {
346
347            try {
348                ourClass = env.classPathLoader.loadClass(getQualifiedName());
349            } catch (NullPointerException e) {
350                // This should never happen
351            } catch (ClassNotFoundException e) {
352                // Fall through to the next case (which is to look in the
353                // output directory for generated files)
354            }
355        }
356
357        /* This piece of code used to cause the compiler to ignore jar files
358           on its classpath
359        try {
360            ourClass = Util.loadClass(getQualifiedName(),null,null);
361        } catch (ClassNotFoundException e) {
362        } catch (LinkageError e) {
363        }
364        */
365
366        if (ourClass == null) {
367
368            // Try one last thing. If the class was compiled into
369            // a directory that's not in the classpath, the load
370            // will fail. Let's get the bits off the disk and load
371            // it directly...
372
373            if (env.loader == null) {
374                File destDir = env.getMain().getDestinationDir();
375                if (destDir == null) {
376                    destDir = new File(".");
377                }
378                env.loader = new DirectoryLoader(destDir);
379            }
380
381            try {
382                ourClass = env.loader.loadClass(getQualifiedName());
383            } catch (Exception e) {}
384        }
385
386        return ourClass;
387    }
388
389    // Print "extends XX"
390
391    protected boolean printExtends (IndentingWriter writer,
392                                    boolean useQualifiedNames,
393                                    boolean useIDLNames,
394                                    boolean globalIDLNames) throws IOException {
395
396        ClassType parent = getSuperclass();
397
398        if (parent != null && (!useIDLNames ||
399                               (!parent.isType(TYPE_ANY) && !parent.isType(TYPE_CORBA_OBJECT)))) {
400            writer.p(" extends ");
401            parent.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
402            return true;
403        }
404        return false;
405    }
406
407    // Print "implements XX, YY"
408
409    protected void printImplements (IndentingWriter writer,
410                                    String prefix,
411                                    boolean useQualifiedNames,
412                                    boolean useIDLNames,
413                                    boolean globalIDLNames) throws IOException {
414
415        InterfaceType[] interfaces = getInterfaces();
416
417        String adjective = " implements";
418
419        if (isInterface()) {
420            adjective = " extends";
421        }
422
423        if (useIDLNames) {
424            adjective = ":";
425        }
426
427        for (int i = 0; i < interfaces.length; i++) {
428            if (!useIDLNames || (!interfaces[i].isType(TYPE_ANY) && !interfaces[i].isType(TYPE_CORBA_OBJECT))) {
429                if (i == 0) {
430                    writer.p(prefix + adjective + " ");
431                } else {
432                    writer.p(", ");
433                }
434                interfaces[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
435            }
436        }
437    }
438
439    // Print members
440
441    protected void printMembers (       IndentingWriter writer,
442                                        boolean useQualifiedNames,
443                                        boolean useIDLNames,
444                                        boolean globalIDLNames) throws IOException {
445
446        CompoundType.Member[] members = getMembers();
447
448        for (int i = 0; i < members.length; i++) {
449            if (!members[i].isInnerClassDeclaration()) {
450                Type it = members[i].getType();
451                String visibility = members[i].getVisibility();
452                String name;
453
454                if (useIDLNames) {
455                    name = members[i].getIDLName();
456                } else {
457                    name = members[i].getName();
458                }
459
460                String value = members[i].getValue();
461
462                writer.p(visibility);
463                if (visibility.length() > 0) {
464                    writer.p(" ");
465                }
466                it.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
467                writer.p(" " + name);
468
469                if (value != null) {
470                    writer.pln(" = " + value + ";");
471                } else {
472                    writer.pln(";");
473                }
474            }
475        }
476    }
477
478    // Print methods
479
480    protected void printMethods (       IndentingWriter writer,
481                                        boolean useQualifiedNames,
482                                        boolean useIDLNames,
483                                        boolean globalIDLNames) throws IOException {
484
485        CompoundType.Method[] methods = getMethods();
486
487        for (int m = 0; m < methods.length; m++) {
488            CompoundType.Method theMethod = methods[m];
489            printMethod(theMethod,writer,useQualifiedNames,useIDLNames,globalIDLNames);
490        }
491    }
492
493    // Print a method...
494
495    protected void printMethod (CompoundType.Method it,
496                                IndentingWriter writer,
497                                boolean useQualifiedNames,
498                                boolean useIDLNames,
499                                boolean globalIDLNames) throws IOException {
500
501
502        // Write visibility...
503
504        String visibility = it.getVisibility();
505
506        writer.p(visibility);
507        if (visibility.length() > 0) {
508            writer.p(" ");
509        }
510
511        // Write return type...
512
513        it.getReturnType().printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
514
515        // Write method name...
516
517        if (useIDLNames) {
518            writer.p(" " + it.getIDLName());
519        } else {
520            writer.p(" " + it.getName());
521        }
522
523        // Write arguments...
524
525        writer.p(" (");
526        Type[] args = it.getArguments();
527        String[] argNames = it.getArgumentNames();
528
529        for (int i = 0; i < args.length; i++) {
530            if (i > 0) {
531                writer.p(", ");
532            }
533
534            if (useIDLNames) {
535                writer.p("in ");
536            }
537
538            args[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
539            writer.p(" " + argNames[i]);
540        }
541        writer.p(")");
542
543        // Write exceptions...
544
545        ClassType[] exceptions;
546
547        if (isType(TYPE_IMPLEMENTATION)) {
548            exceptions = it.getImplExceptions();
549        } else {
550            exceptions = it.getExceptions();
551        }
552
553        for (int i = 0; i < exceptions.length; i++) {
554            if (i == 0) {
555                if (useIDLNames) {
556                    writer.p(" raises (");
557                } else {
558                    writer.p(" throws ");
559                }
560            } else {
561                writer.p(", ");
562            }
563
564            if (useIDLNames) {
565                if (useQualifiedNames) {
566                    writer.p(exceptions[i].getQualifiedIDLExceptionName(globalIDLNames));
567                } else {
568                    writer.p(exceptions[i].getIDLExceptionName());
569                }
570                writer.p(" [a.k.a. ");
571                exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
572                writer.p("]");
573            } else {
574                exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames);
575            }
576        }
577
578        if (useIDLNames && exceptions.length > 0) {
579            writer.p(")");
580        }
581
582        if (it.isInherited()) {
583            writer.p(" // Inherited from ");
584        writer.p(it.getDeclaredBy());
585        }
586
587        writer.pln(";");
588    }
589
590    /**
591     * Create a CompoundType instance for the given class. NOTE: This constructor
592     * is ONLY for SpecialClassType and SpecialInterfaceType.
593     */
594    protected CompoundType(ContextStack stack, int typeCode, ClassDefinition classDef) {
595        super(stack,typeCode);
596        this.classDef = classDef;
597        classDecl = classDef.getClassDeclaration();
598        interfaces = new InterfaceType[0];
599        methods = new Method[0];
600        members = new Member[0];
601
602        // If we are an inner class/interface, reset the type codes...
603
604        if (classDef.isInnerClass()) {
605            setTypeCode(typeCode | TM_INNER);
606        }
607
608        // Set special flags...
609
610        setFlags();
611    }
612
613    private void setFlags() {
614
615        try {
616
617        // Set our special interface flags...
618
619            isCORBAObject = env.defCorbaObject.implementedBy(env,classDecl);
620            isIDLEntity = env.defIDLEntity.implementedBy(env,classDecl);
621            isValueBase = env.defValueBase.implementedBy(env,classDecl);
622            isAbstractBase = isInterface() &&   // Interface, not a class.
623                             isIDLEntity &&     // Implements IDLEntity.
624                             !isValueBase &&    // Does not implement ValueBase.
625                             !isCORBAObject;    // Does not implement org.omg.CORBA.Object;
626            isCORBAUserException = (classDecl.getName() == idCorbaUserException);
627
628            // Is this an exception?
629
630            if (env.defThrowable.implementedBy(env, classDecl)) {
631
632                // Yes...
633
634                isException = true;
635
636                // Is it a checked exception?
637
638                if (env.defRuntimeException.implementedBy(env,classDecl) ||
639                    env.defError.implementedBy(env,classDecl)) {
640                    isCheckedException = false;
641                } else {
642                    isCheckedException = true;
643                }
644
645                // Is it java.rmi.RemoteException or a subclass?
646
647                if (env.defRemoteException.implementedBy(env,classDecl)) {
648                    isRemoteExceptionOrSubclass = true;
649                } else {
650                    isRemoteExceptionOrSubclass = false;
651                }
652            } else {
653                isException = false;
654            }
655        } catch (ClassNotFound e) {
656            classNotFound(stack,e);
657        }
658    }
659
660    /**
661     * Create a CompoundType instance for the given class.  The resulting
662     * object is not yet completely initialized.
663     */
664    protected CompoundType(ContextStack stack, ClassDefinition classDef,
665                           int typeCode) {
666        super(stack,typeCode);
667        this.classDef = classDef;
668        classDecl = classDef.getClassDeclaration();
669
670        // If we are an inner class/interface, reset the type codes...
671
672        if (classDef.isInnerClass()) {
673            setTypeCode(typeCode | TM_INNER);
674        }
675
676        // Set special flags...
677
678        setFlags();
679
680        // Set names...
681
682        Identifier id = classDef.getName();
683        String idlName;
684        String[] idlModuleNames;
685
686        try {
687
688            // These can fail if we get case-sensitive name matches...
689
690            idlName = IDLNames.getClassOrInterfaceName(id,env);
691            idlModuleNames = IDLNames.getModuleNames(id,isBoxed(),env);
692
693            setNames(id,idlModuleNames,idlName);
694
695            // Is this an exception?
696
697            if (isException()) {
698
699                // Yes, so set our mangled exception names...
700
701                isException = true;
702                idlExceptionName = IDLNames.getExceptionName(getIDLName());
703                qualifiedIDLExceptionName =
704                    IDLNames.getQualifiedName(getIDLModuleNames(),idlExceptionName);
705            }
706
707            // Set interfaces, methods and members...
708
709            interfaces = null;          // set in initialize()
710            methods = null;                     // set in initialize()
711            members = null;                 // set in initialize()
712
713        } catch (Exception e) {
714            failedConstraint(7,false,stack,id.toString(),e.getMessage());
715            throw new CompilerError("");
716        }
717    }
718
719    /**
720     * Initialize this instance.
721     */
722    protected boolean initialize (      Vector directInterfaces,
723                                        Vector directMethods,
724                                        Vector directMembers,
725                                        ContextStack stack,
726                                        boolean quiet) {
727
728        boolean result = true;
729
730        // Initialize our arrays...
731
732        if (directInterfaces != null && directInterfaces.size() > 0) {
733            interfaces = new InterfaceType[directInterfaces.size()];
734            directInterfaces.copyInto(interfaces);
735        } else {
736            interfaces = new InterfaceType[0];
737        }
738
739        if (directMethods != null && directMethods.size() > 0) {
740            methods = new Method[directMethods.size()];
741            directMethods.copyInto(methods);
742
743            // Now set the idl names for each...
744
745            try {
746                IDLNames.setMethodNames(this, methods,env);
747            } catch (Exception e) {
748                failedConstraint(13,quiet,stack,getQualifiedName(),e.getMessage());
749                result = false;
750            }
751
752        } else {
753            methods = new Method[0];
754        }
755
756        if (directMembers != null && directMembers.size() > 0) {
757            members = new Member[directMembers.size()];
758            directMembers.copyInto(members);
759
760            // If we have any un-initialized inner classes, now is the time
761            // to init them...
762
763            for (int i = 0; i < members.length; i++) {
764                if (members[i].isInnerClassDeclaration()) {
765                    try {
766                        members[i].init(stack,this);
767                    } catch (CompilerError e) {
768                        return false;
769                    }
770                }
771            }
772
773            // Now set the idl names for each...
774
775            try {
776                IDLNames.setMemberNames(this, members,methods,env);
777            } catch (Exception e) {
778                int constraint = classDef.isInterface() ? 19 : 20;
779                failedConstraint(constraint,quiet,stack,getQualifiedName(),e.getMessage());
780                result = false;
781            }
782
783        } else {
784            members = new Member[0];
785        }
786
787        // Set our repositoryID...
788
789        if (result) {
790            result = setRepositoryID();
791        }
792
793        return result;
794    }
795
796    /*
797     * Return Type or null if error. classDef may be null.
798     */
799    protected static Type makeType (sun.tools.java.Type theType,
800                                    ClassDefinition classDef,
801                                    ContextStack stack) {
802
803        if (stack.anyErrors()) return null;
804
805        // See if we can find this type in the cache.  If so, return it...
806
807        String key = theType.toString();
808
809        Type result = getType(key,stack);
810
811        if (result != null) {
812            return result;
813        }
814
815        // Gotta try with context...
816
817        result = getType(key + stack.getContextCodeString(),stack);
818
819        if (result != null) {
820            return result;
821        }
822
823        // Gotta map it...
824
825        BatchEnvironment env = stack.getEnv();
826        int typeCode = theType.getTypeCode();
827        switch (typeCode) {
828        case TC_BOOLEAN:
829        case TC_BYTE:
830        case TC_CHAR:
831        case TC_SHORT:
832        case TC_INT:
833        case TC_LONG:
834        case TC_FLOAT:
835        case TC_DOUBLE:
836            {
837                // Primitive...
838
839                result = PrimitiveType.forPrimitive(theType,stack);
840                break;
841            }
842
843        case TC_ARRAY:
844            {
845                // Array.
846
847                result = ArrayType.forArray(theType,stack);
848                break;
849            }
850
851        case TC_CLASS:
852            {
853                try {
854                                // First, make sure we have the class definition...
855
856                    ClassDefinition theClass = classDef;
857
858                    if (theClass == null) {
859                        theClass = env.getClassDeclaration(theType).getClassDefinition(env);
860                    }
861
862                                // Is it an interface or a class?
863
864                    if (theClass.isInterface()) {
865
866                        // An interface. Is it a special case?
867
868                        result = SpecialInterfaceType.forSpecial(theClass,stack);
869
870                        if (result == null) {
871
872                            // No, does it implement java.rmi.Remote?
873
874                            if (env.defRemote.implementedBy(env,theClass.getClassDeclaration())) {
875
876                                // Yep, so just see if we can create an instance of RemoteType
877                                // from it...
878
879                                boolean parentIsValue = stack.isParentAValue();
880                                result = RemoteType.forRemote(theClass,stack,parentIsValue);
881
882                                // If we did not succeed AND we are in a value context, then
883                                // go ahead and make an NC type out of it...
884
885                                if (result == null && parentIsValue) {
886                                    result = NCInterfaceType.forNCInterface(theClass,stack);
887                                }
888                            } else {
889
890                                // Nope, is it an AbstractType?
891
892                                result = AbstractType.forAbstract(theClass,stack,true);
893
894                                if (result == null) {
895
896                                    // No, so treat it as a non-conforming interface type...
897
898                                    result = NCInterfaceType.forNCInterface(theClass,stack);
899                                }
900                            }
901                        }
902                    } else {
903
904                        // A class. Is it a special case?
905
906                        result = SpecialClassType.forSpecial(theClass,stack);
907
908                        if (result == null) {
909
910                            ClassDeclaration classDecl = theClass.getClassDeclaration();
911
912                            // Nope, does it implement java.rmi.Remote?
913
914                            if (env.defRemote.implementedBy(env,classDecl)) {
915
916                                // Yep, so just see if we can create an instance of
917                                // ImplementationType from it...
918
919                                boolean parentIsValue = stack.isParentAValue();
920                                result = ImplementationType.forImplementation(theClass,stack,parentIsValue);
921
922                                // If we did not succeed AND inValue is true, then
923                                // go ahead and make an NC type out of it...
924
925                                if (result == null && parentIsValue) {
926                                    result = NCClassType.forNCClass(theClass,stack);
927                                }
928                            } else {
929
930                                // No, does it implement Serializable?
931
932                                if (env.defSerializable.implementedBy(env,classDecl)) {
933
934                                    // Yep, so just see if we can create an instance of ValueType
935                                    // from it...
936
937                                    result = ValueType.forValue(theClass,stack,true);
938                                }
939
940                                if (result == null) {
941
942                                    // Treat it as a non-conforming class type...
943
944                                    result = NCClassType.forNCClass(theClass,stack);
945                                }
946                            }
947                        }
948                    }
949                } catch (ClassNotFound e) {
950                    classNotFound(stack,e);
951                }
952                break;
953            }
954
955        default: throw new CompilerError("Unknown typecode (" + typeCode + ") for " + theType.getTypeSignature());
956        }
957
958        return result;
959    }
960
961    /*
962     * Check if exception is RemoteException or one of its parents.
963     */
964    public static boolean isRemoteException (ClassType ex,
965                                             BatchEnvironment env) {
966        sun.tools.java.Type exceptionType = ex.getClassDeclaration().getType();
967
968        if (exceptionType.equals(env.typeRemoteException) ||
969            exceptionType.equals(env.typeIOException) ||
970            exceptionType.equals(env.typeException) ||
971            exceptionType.equals(env.typeThrowable)) {
972
973            return true;
974        }
975        return false;
976    }
977
978    /*
979     * Check if method is conforming.
980     */
981    protected boolean isConformingRemoteMethod (Method method, boolean quiet)
982        throws ClassNotFound {
983
984        // Do we have one exception that is RemoteException or
985        // a superclass of RemoteException?
986
987        boolean haveRemote = false;
988        ClassType[] exceptions = method.getExceptions();
989
990        for (int i = 0; i < exceptions.length; i++) {
991
992            // Is it a conforming exception?
993
994            if (isRemoteException(exceptions[i],env)) {
995
996                // Got it.
997
998                haveRemote = true;
999                break;
1000            }
1001        }
1002
1003        // Do we have our exception?
1004
1005        if (!haveRemote) {
1006
1007            // No, so report failure...
1008
1009            failedConstraint(5,quiet,stack,method.getEnclosing(), method.toString());
1010        }
1011
1012        // Are any of the arguments exceptions which implement IDLEntity?
1013        // If so, report failure...
1014
1015        boolean noIDLEntity = !isIDLEntityException(method.getReturnType(),method,quiet);
1016        if (noIDLEntity) {
1017            Type[] args = method.getArguments();
1018            for (int i = 0; i < args.length; i++) {
1019                if (isIDLEntityException(args[i],method,quiet)) {
1020                    noIDLEntity = false;
1021                    break;
1022                }
1023            }
1024        }
1025
1026        return (haveRemote && noIDLEntity);
1027    }
1028
1029    protected boolean isIDLEntityException(Type type, CompoundType.Method method,boolean quiet)
1030        throws ClassNotFound {
1031        if (type.isArray()) {
1032            type = type.getElementType();
1033        }
1034        if (type.isCompound()){
1035            if (((CompoundType)type).isIDLEntityException()) {
1036                failedConstraint(18,quiet,stack,method.getEnclosing(), method.toString());
1037                return true;
1038            }
1039        }
1040        return false;
1041    }
1042
1043    /**
1044     * Convert all invalid types to valid ones.
1045     */
1046    protected void swapInvalidTypes () {
1047
1048        // Walk all interfaces and check them...
1049
1050        for (int i = 0; i < interfaces.length; i++) {
1051            if (interfaces[i].getStatus() != STATUS_VALID) {
1052                interfaces[i] = (InterfaceType)getValidType(interfaces[i]);
1053            }
1054        }
1055
1056        // Update methods...
1057
1058        for (int i = 0; i < methods.length; i++) {
1059            methods[i].swapInvalidTypes();
1060        }
1061
1062        // Update members...
1063
1064        for (int i = 0; i < members.length; i++) {
1065            members[i].swapInvalidTypes();
1066        }
1067    }
1068
1069    /*
1070     * Add matching types to list. Return true if this type has not
1071     * been previously checked, false otherwise.
1072     */
1073    protected boolean addTypes (int typeCodeFilter,
1074                                HashSet checked,
1075                                Vector matching) {
1076
1077        // Check self.
1078
1079        boolean result = super.addTypes(typeCodeFilter,checked,matching);
1080
1081        // Have we been checked before?
1082
1083        if (result) {
1084
1085            // Nope, so walk parent(s) and check them...
1086
1087            ClassType parent = getSuperclass();
1088
1089            if (parent != null) {
1090                parent.addTypes(typeCodeFilter,checked,matching);
1091            }
1092
1093            // Walk all interfaces and check them...
1094
1095            //if (interfaces == null) System.out.println("NULL for " +getQualifiedName() + " interfaces");
1096            for (int i = 0; i < interfaces.length; i++) {
1097
1098                // Now recurse and add it and any referenced types...
1099
1100                //if (interfaces[i] == null) System.out.println("NULL for " +getQualifiedName() + " interfaces[" + i + "]");
1101                interfaces[i].addTypes(typeCodeFilter,checked,matching);
1102            }
1103
1104            // Walk all methods and check arguments...
1105
1106            //if (methods == null) System.out.println("NULL for " +getQualifiedName() + " methods");
1107            for (int i = 0; i < methods.length; i++) {
1108
1109                // Add return type...
1110                //if (methods[i] == null) System.out.println("NULL for " +getQualifiedName() + " methods[" + i + "]");
1111                //if (methods[i].getReturnType() == null) System.out.println("NULL for " +getQualifiedName() + methods[i]);
1112                methods[i].getReturnType().addTypes(typeCodeFilter,checked,matching);
1113
1114                // Add args...
1115
1116                Type[] args = methods[i].getArguments();
1117                //if (args == null) System.out.println("NULL for " + getQualifiedName() + " args");
1118
1119                for (int j = 0; j < args.length; j++) {
1120
1121                    Type arg = args[j];
1122                    //if (arg == null) System.out.println("NULL for " + getQualifiedName() + " arg[" +j+"]");
1123
1124                                // Add argument...
1125
1126                    arg.addTypes(typeCodeFilter,checked,matching);
1127                }
1128
1129                // Add exceptions...
1130
1131                ClassType[] exceptions = methods[i].getExceptions();
1132                //if (exceptions == null) System.out.println("NULL for " + getQualifiedName() + " exceptions");
1133
1134                for (int j = 0; j < exceptions.length; j++) {
1135
1136                    ClassType ex = exceptions[j];
1137
1138                                // Add argument...
1139
1140                    ex.addTypes(typeCodeFilter,checked,matching);
1141                }
1142            }
1143
1144            // Walk all members and add em...
1145
1146            //if (members == null) System.out.println("NULL for " +getQualifiedName() + " members");
1147            for (int i = 0; i < members.length; i++) {
1148                //if (members[i] == null) System.out.println("NULL for " +getQualifiedName() + " members[" + i + "]");
1149                Type cType = members[i].getType();
1150                //if (cType == null) System.out.println("NULL for " + getQualifiedName() + " cType");
1151
1152                // Add it...
1153
1154                cType.addTypes(typeCodeFilter,checked,matching);
1155            }
1156        }
1157
1158        return result;
1159    }
1160
1161    /*
1162     * Return true if theType is a conforming constant type.
1163     */
1164    private boolean isConformingConstantType (MemberDefinition member) {
1165        return isConformingConstantType(member.getType(),member);
1166    }
1167
1168    /*
1169     * Return true if theType is a conforming constant type.
1170     */
1171    private boolean isConformingConstantType (sun.tools.java.Type theType,MemberDefinition member) {
1172
1173        // Constraint 3:    Constants must be either primitives or String.
1174
1175        boolean result = true;
1176        int typeCode = theType.getTypeCode();
1177        switch (typeCode) {
1178        case TC_BOOLEAN:
1179        case TC_BYTE:
1180        case TC_CHAR:
1181        case TC_SHORT:
1182        case TC_INT:
1183        case TC_LONG:
1184        case TC_FLOAT:
1185        case TC_DOUBLE: // Primitive, so OK...
1186            {
1187                break;
1188            }
1189
1190        case TC_CLASS:  // Must be java.lang.String
1191            {
1192                if (theType.getClassName() != idJavaLangString) {
1193                    failedConstraint(3,false,stack,member.getClassDefinition(),member.getName());
1194                    result = false;
1195                }
1196                break;
1197            }
1198
1199        case TC_ARRAY: // Array constants are not allowed.
1200            {
1201                failedConstraint(3,false,stack,member.getClassDefinition(),member.getName());
1202                result = false;
1203                break;
1204            }
1205
1206        default:
1207            throw new Error("unexpected type code: " + typeCode);
1208        }
1209
1210        return result;
1211    }
1212
1213
1214    /*
1215     * Update any method from 'currentMethods' which is defined in a
1216     * parent class so that it's 'declaredBy' field specifies the
1217     * parent.
1218     * @param current The class or interface to gather methods from.
1219     * @param currentMethods The list into which to put the methods.
1220     *  for contraint 6.
1221     * @param quiet true if silent errors.
1222     * @param stack the context stack.
1223     * @return currentMethods or null if failed a constraint check.
1224     */
1225    protected Vector updateParentClassMethods(ClassDefinition current,
1226                                              Vector currentMethods,
1227                                              boolean quiet,
1228                                              ContextStack stack)
1229        throws ClassNotFound {
1230
1231        ClassDeclaration parentDecl = current.getSuperClass(env);
1232
1233        while (parentDecl != null) {
1234
1235            ClassDefinition parentDef = parentDecl.getClassDefinition(env);
1236            Identifier currentID = parentDecl.getName();
1237
1238            if ( currentID == idJavaLangObject ) break;
1239
1240            // Walk all members of this class and update any that
1241            // already exist in currentMethods...
1242
1243            for (MemberDefinition member = parentDef.getFirstMember();
1244                 member != null;
1245                 member = member.getNextMember()) {
1246
1247                if (member.isMethod() &&
1248                    !member.isInitializer() &&
1249                    !member.isConstructor() &&
1250                    !member.isPrivate()) {
1251
1252                    // It's a method.  Is it valid?
1253
1254                    Method method;
1255                    try {
1256                        method = new Method((CompoundType)this,member,quiet,stack);
1257                    } catch (Exception e) {
1258                        // Don't report anything here, it's already been reported...
1259                        return null;
1260                    }
1261
1262                    // Have we already seen it?
1263
1264                    int index = currentMethods.indexOf(method);
1265                    if (index >= 0) {
1266
1267                        // Yes, so update it...
1268
1269                        Method currentMethod = (Method)currentMethods.elementAt(index);
1270                        currentMethod.setDeclaredBy(currentID);
1271                    }
1272                    else currentMethods.addElement(method);
1273                }
1274            }
1275
1276            // Update parent and keep walking up the chain...
1277
1278            parentDecl = parentDef.getSuperClass(env);
1279        }
1280
1281        return currentMethods;
1282    }
1283
1284    /*
1285     * Add all of the public and protected methods defined in
1286     * current (other than initializers) to allMethods. If a sub-interface
1287     * re-declares an inherited method, it will not be added.
1288     * @param current The class or interface to gather methods from.
1289     * @param directMethods The list into which to put the methods.
1290     * @param noMultiInheritedMethods A flag to enable/disable checking
1291     *  for contraint 6.
1292     * @param quiet true if silent errors.
1293     * @param stack the context stack.
1294     * @return directMethods or null if failed a constraint check.
1295     */
1296    protected Vector addAllMethods (ClassDefinition current, Vector directMethods,
1297                                    boolean noMultiInheritedMethods,
1298                                    boolean quiet,
1299                                    ContextStack stack)
1300        throws ClassNotFound {
1301
1302        // Constraint 6:    Multiple inherited interfaces may not
1303        //                  declare the same method.
1304
1305        ClassDeclaration[] interfaces = current.getInterfaces();
1306
1307        // We want to add members starting at the _least_ derived
1308        // interfaces.  To do so, recurse until we have no more
1309        // interfaces...
1310
1311        for (int i = 0; i < interfaces.length; i++) {
1312
1313            Vector result = addAllMethods(interfaces[i].getClassDefinition(env),
1314                                          directMethods,
1315                                          noMultiInheritedMethods,quiet,stack);
1316            if (result == null) {
1317                return null;
1318            }
1319        }
1320
1321        // Walk all members of this interface, adding any unique methods
1322        // other than initializers and private methods...
1323
1324        for (MemberDefinition member = current.getFirstMember();
1325             member != null;
1326             member = member.getNextMember())
1327            {
1328                if (member.isMethod() &&
1329                    !member.isInitializer() &&
1330                    !member.isPrivate()) {
1331
1332                    // It's a method.  Is it valid?
1333
1334                    Method method;
1335                    try {
1336                        method = new Method((CompoundType)this,member,quiet,stack);
1337                    } catch (Exception e) {
1338                        // Don't report anything here, it's already been reported...
1339                        return null;
1340                    }
1341
1342                                // Have we already seen it?
1343
1344                    if (!directMethods.contains(method)) {
1345
1346                        // Nope, so add it...
1347
1348                        directMethods.addElement(method);
1349
1350                    } else {
1351
1352                        // Yes. This is an error unless we are looking at the
1353                        // target interface (or this is a ValueType). Are we?
1354
1355                        if (noMultiInheritedMethods && current != classDef  &&
1356                            !stack.isParentAValue() && !stack.getContext().isValue()) {
1357
1358                            // Nope. Say so and signal error by returning null..
1359
1360                            Method existingMethod = (Method) directMethods.elementAt(directMethods.indexOf(method));
1361                            ClassDefinition existingMemberClassDef = existingMethod.getMemberDefinition().getClassDefinition();
1362
1363                            // There are more legal cases to consider here.
1364                            // If the two methods belong to interfaces that inherit from each other
1365                            // then it is just a redefinition which is legal.
1366                            if ( current != existingMemberClassDef &&
1367                                 ! inheritsFrom(current, existingMemberClassDef) &&
1368                                 ! inheritsFrom(existingMemberClassDef, current))
1369                            {
1370                                //Identifier int1 = existingMethod.getEnclosing().getIdentifier();
1371                                //Identifier int2 = current.getName();
1372                                //String message = int1.toString() + " and " + int2.toString();
1373                                String message = existingMemberClassDef.getName() + " and " + current.getName();
1374                                failedConstraint(6,quiet,stack,classDef,message,method);
1375                                return null;
1376                            }
1377                        }
1378
1379                        // Bug fix 5014329
1380
1381                        // find a matching method.
1382                        int index = directMethods.indexOf(method);
1383                        Method other = (Method) directMethods.get(index);
1384
1385                        // merge the two methods, such that the new method
1386                        // will contain only those exception that can be thrown
1387                        // by both these methods, not just one of them.
1388                        Method newMethod = method.mergeWith(other);
1389
1390                        // replace the old method with the new.
1391                        directMethods.set(index, newMethod);
1392                    }
1393                }
1394            }
1395
1396        return directMethods;
1397    }
1398
1399    // This should really be a method on ClassDefinition, but it takes too long to change the shared source.
1400    // Works for both, classes and interfaces.
1401    protected boolean inheritsFrom(ClassDefinition def, ClassDefinition otherDef) {
1402        if (def == otherDef)
1403            return true;
1404
1405        ClassDefinition superDef;
1406        if (def.getSuperClass() != null) {
1407            superDef = def.getSuperClass().getClassDefinition();
1408            if (inheritsFrom(superDef, otherDef))
1409                return true;
1410        }
1411
1412        ClassDeclaration[] interfaces = def.getInterfaces();
1413        for (int i=0; i<interfaces.length; i++) {
1414            superDef = interfaces[i].getClassDefinition();
1415            if (inheritsFrom(superDef, otherDef))
1416                return true;
1417        }
1418        return false;
1419    }
1420
1421    /*
1422     * Add all of the interfaces implemented directly by current
1423     * to the list. Returns null if any are non-conforming.
1424     */
1425    protected Vector addRemoteInterfaces (Vector list,
1426                                          boolean allowNonConforming,
1427                                          ContextStack stack) throws ClassNotFound {
1428
1429        // Add all the interfaces of current...
1430
1431        ClassDefinition theInterface = getClassDefinition();
1432        ClassDeclaration[] interfaces = theInterface.getInterfaces();
1433
1434        stack.setNewContextCode(ContextStack.IMPLEMENTS);
1435
1436        for (int i = 0; i < interfaces.length; i++) {
1437
1438            ClassDefinition def = interfaces[i].getClassDefinition(env);
1439
1440            // Is it a SpecialInterfaceType...
1441
1442            InterfaceType it = SpecialInterfaceType.forSpecial(def,stack);;
1443
1444            if (it == null) {
1445
1446                // No, is it Remote?
1447
1448                if (env.defRemote.implementedBy(env, interfaces[i])) {
1449
1450                    // Yes, so it must be a RemoteType.
1451
1452                    it = RemoteType.forRemote(def,stack,false);
1453
1454                } else {
1455
1456                    // Then try Abstract...
1457
1458                    it = AbstractType.forAbstract(def,stack,true);
1459
1460                    if (it == null && allowNonConforming) {
1461
1462                        // Must be non-conforming...
1463
1464                        it = NCInterfaceType.forNCInterface(def,stack);
1465                    }
1466                }
1467            }
1468
1469            if (it != null) {
1470                list.addElement(it);
1471            } else {
1472                return null;
1473            }
1474        }
1475
1476        return list;
1477    }
1478
1479    /*
1480     * Add all of the interfaces implemented directly by current
1481     * to the list.
1482     */
1483    protected Vector addNonRemoteInterfaces (Vector list,
1484                                             ContextStack stack) throws ClassNotFound {
1485
1486        // Add all the interfaces of current...
1487
1488        ClassDefinition theInterface = getClassDefinition();
1489        ClassDeclaration[] interfaces = theInterface.getInterfaces();
1490
1491        stack.setNewContextCode(ContextStack.IMPLEMENTS);
1492
1493        for (int i = 0; i < interfaces.length; i++) {
1494
1495            ClassDefinition def = interfaces[i].getClassDefinition(env);
1496
1497            // First try SpecialInterfaceType...
1498
1499            InterfaceType it = SpecialInterfaceType.forSpecial(def,stack);
1500
1501            if (it == null) {
1502
1503                // Then try AbstractType...
1504
1505                it = AbstractType.forAbstract(def,stack,true);
1506
1507                if (it == null) {
1508
1509                    // Then try NCInterfaceType...
1510
1511                    it = NCInterfaceType.forNCInterface(def,stack);
1512                }
1513            }
1514
1515            if (it != null) {
1516                list.addElement(it);
1517            } else {
1518                return null;
1519            }
1520        }
1521
1522        return list;
1523    }
1524
1525
1526    /*
1527     * Walk self, adding constants and data members.
1528     * @return true if all conform, false otherwise.
1529     */
1530    protected boolean addAllMembers (Vector allMembers,
1531                                     boolean onlyConformingConstants,   // AND inner classes.
1532                                     boolean quiet,
1533                                     ContextStack stack) {
1534
1535        boolean result = true;
1536
1537        // Walk all members of this interface...
1538
1539        for (MemberDefinition member = getClassDefinition().getFirstMember();
1540             member != null && result;
1541             member = member.getNextMember())
1542            {
1543                if (!member.isMethod()) {
1544
1545                    try {
1546                        String value = null;
1547
1548                        // Prod it to setValue if it is a constant...
1549
1550                        member.getValue(env);
1551
1552                                // Get the value, if any...
1553
1554                        Node node = member.getValue();
1555
1556                        if (node != null) {
1557                            // We don't want to change the code in CharExpression,
1558                            // which is shared among tools, to return the right string
1559                            // in case the type is char, so we treat it special here.
1560                            if (member.getType().getTypeCode() == TC_CHAR) {
1561                                Integer intValue = (Integer)((IntegerExpression)node).getValue();
1562                                value = "L'" + String.valueOf((char)intValue.intValue()) + "'";
1563                            } else {
1564                                value = node.toString();
1565                            }
1566                        }
1567
1568                        // Are we supposed to allow only conforming constants?
1569
1570                        if (onlyConformingConstants && member.getInnerClass() == null) {
1571
1572                                // Yep, so check it...
1573
1574                            if (value == null || !isConformingConstantType(member)) {
1575                                failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName());
1576                                result = false;
1577                                break;
1578                            }
1579                        }
1580
1581                        // Make member and add to list...
1582
1583                        try {
1584                            Member newMember = new Member(member,value,stack,this);
1585                            allMembers.addElement(newMember);
1586                        } catch (CompilerError e) {
1587                            result = false;
1588                        }
1589
1590                    } catch (ClassNotFound e) {
1591                        classNotFound(stack,e);
1592                        result = false;
1593                    }
1594                }
1595            }
1596
1597        return result;
1598    }
1599    /*
1600     * Walk self, adding constants.
1601     * @return true if all conform, false otherwise.
1602     */
1603    protected boolean addConformingConstants (Vector allMembers,
1604                                              boolean quiet,
1605                                              ContextStack stack) {
1606
1607        boolean result = true;
1608
1609        // Walk all members of this interface...
1610
1611        for (MemberDefinition member = getClassDefinition().getFirstMember();
1612             member != null && result;
1613             member = member.getNextMember())
1614            {
1615                if (!member.isMethod()) {
1616
1617                    try {
1618                        String value = null;
1619
1620                        // Prod it to setValue if it is a constant...
1621
1622                        member.getValue(env);
1623
1624                                // Get the value, if any...
1625
1626                        Node node = member.getValue();
1627
1628                        if (node != null) {
1629                            value = node.toString();
1630                        }
1631
1632
1633                        // Is it a constant?
1634
1635                        if (value != null) {
1636
1637                            // Yes, is it conforming?
1638
1639                            if (!isConformingConstantType(member)) {
1640                                failedConstraint(3,quiet,stack,member.getClassDefinition(),member.getName());
1641                                result = false;
1642                                break;
1643                            }
1644
1645                            // Yes, so make a member and add to list...
1646
1647                            try {
1648                                Member newMember = new Member(member,value,stack,this);
1649                                allMembers.addElement(newMember);
1650                            } catch (CompilerError e) {
1651                                result = false;
1652                            }
1653                        }
1654                    } catch (ClassNotFound e) {
1655                        classNotFound(stack,e);
1656                        result = false;
1657                    }
1658                }
1659            }
1660
1661        return result;
1662    }
1663
1664    protected ValueType[] getMethodExceptions (MemberDefinition member,
1665                                               boolean quiet,
1666                                               ContextStack stack) throws Exception {
1667
1668        boolean result = true;
1669        stack.setNewContextCode(ContextStack.METHOD_EXCEPTION);
1670        ClassDeclaration[] except = member.getExceptions(env);
1671        ValueType[] exceptions = new ValueType[except.length];
1672
1673        try {
1674            for (int i = 0; i < except.length; i++) {
1675                ClassDefinition theClass = except[i].getClassDefinition(env);
1676                try {
1677                    ValueType type = ValueType.forValue(theClass,stack,false);
1678                    if (type != null) {
1679                            exceptions[i] = type;
1680                        } else {
1681                            result = false;
1682                        }
1683                } catch (ClassCastException e1) {
1684                    failedConstraint(22,quiet,stack,getQualifiedName());
1685                    throw new CompilerError("Method: exception " + theClass.getName() + " not a class type!");
1686                } catch (NullPointerException e2) {
1687                    failedConstraint(23,quiet,stack,getQualifiedName());
1688                    throw new CompilerError("Method: caught null pointer exception");
1689                }
1690            }
1691        } catch (ClassNotFound e) {
1692            classNotFound(quiet,stack,e);
1693            result = false;
1694        }
1695
1696        if (!result) {
1697            throw new Exception();
1698        }
1699
1700        // Remove any duplicates (javac seems to allow them, but rmic will
1701        // generate bad ties)...
1702
1703        int dupCount = 0;
1704        for (int i = 0; i < exceptions.length; i++) {
1705            for (int j = 0; j < exceptions.length; j++) {
1706                if (i != j && exceptions[i] != null && exceptions[i] == exceptions[j]) {
1707                    exceptions[j] = null;
1708                    dupCount++;
1709                }
1710            }
1711        }
1712        if (dupCount > 0) {
1713            int offset = 0;
1714            ValueType[] temp = new ValueType[exceptions.length - dupCount];
1715            for (int i = 0; i < exceptions.length; i++) {
1716                if (exceptions[i] != null) {
1717                    temp[offset++] = exceptions[i];
1718                }
1719            }
1720            exceptions = temp;
1721        }
1722
1723        return exceptions;
1724    }
1725
1726
1727    protected static String getVisibilityString (MemberDefinition member) {
1728        String vis = "";
1729        String prefix = "";
1730
1731        if (member.isPublic()) {
1732            vis += "public";
1733            prefix = " ";
1734        } else if (member.isProtected()) {
1735            vis += "protected";
1736            prefix = " ";
1737        } else if (member.isPrivate()) {
1738            vis += "private";
1739            prefix = " ";
1740        }
1741
1742        if (member.isStatic()) {
1743            vis += prefix;
1744            vis += "static";
1745            prefix = " ";
1746        }
1747
1748        if (member.isFinal()) {
1749            vis += prefix;
1750            vis += "final";
1751            prefix = " ";
1752        }
1753
1754        return vis;
1755    }
1756
1757    protected boolean assertNotImpl(Type type,
1758                                    boolean quiet,
1759                                    ContextStack stack,
1760                                    CompoundType enclosing,
1761                                    boolean dataMember) {
1762
1763        if (type.isType(TYPE_IMPLEMENTATION)) {
1764            int constraint = dataMember ? 28 : 21;
1765            failedConstraint(constraint,quiet,stack,type,enclosing.getName());
1766            return false;
1767        }
1768        return true;
1769    }
1770
1771    //_____________________________________________________________________
1772    // Inner Class "Method"
1773    //_____________________________________________________________________
1774
1775    /**
1776     * A CompoundType.Method object encapsulates IIOP-specific information
1777     * about a particular method in the interface represented by the outer
1778     * instance.
1779     */
1780    public class Method implements ContextElement, Cloneable {
1781
1782        /**
1783         * Is this method inherited?
1784         */
1785        public boolean isInherited () {
1786            return declaredBy != enclosing.getIdentifier();
1787        }
1788
1789        /**
1790         * Is this method an attribute?
1791         * Return true if getAttributeKind != ATTRIBUTE_NONE.
1792         */
1793        public boolean isAttribute () {
1794            return attributeKind != ATTRIBUTE_NONE;
1795        }
1796
1797        /**
1798         * Is this method a read-write attribute?
1799         */
1800        public boolean isReadWriteAttribute () {
1801            return attributeKind == ATTRIBUTE_IS_RW ||
1802                attributeKind == ATTRIBUTE_GET_RW;
1803        }
1804
1805        /**
1806         * Return the attribute kind.
1807         */
1808        public int getAttributeKind() {
1809            return attributeKind;
1810        }
1811
1812        /**
1813         * Return the attribute name. Will be null if
1814         * attribute kind == ATTRIBUTE_NONE.
1815         */
1816        public String getAttributeName() {
1817            return attributeName;
1818        }
1819
1820        /**
1821         * For kinds ATTRIBUTE_GET_RW or ATTRIBUTE_IS_RW, return
1822         * the index of the matching ATTRIBUTE_SET method, and
1823         * vice-versa. For all other cases, return -1.
1824         */
1825        public int getAttributePairIndex() {
1826            return attributePairIndex;
1827        }
1828
1829        /**
1830         * Return context element name.
1831         */
1832        public String getElementName() {
1833            return memberDef.toString();
1834        }
1835
1836        /**
1837         * Equality check based on method signature.
1838         */
1839        public boolean equals(Object obj) {
1840            Method other = (Method) obj;
1841
1842            if (getName().equals(other.getName()) &&
1843                arguments.length == other.arguments.length) {
1844
1845                for (int i = 0; i < arguments.length; i++) {
1846                    if (! arguments[i].equals(other.arguments[i])) {
1847                        return false;
1848                    }
1849                }
1850                return true;
1851            }
1852            return false;
1853        }
1854
1855        public int hashCode() {
1856            return getName().hashCode() ^ Arrays.hashCode(arguments);
1857        }
1858
1859        /**
1860         * Return a new Method object that is a legal combination of
1861         * this method object and another one.
1862         *
1863         * This requires determining the exceptions declared by the
1864         * combined method, which must be only those exceptions
1865         * that may thrown by both of the old methods.
1866         */
1867        public Method mergeWith(Method other) {
1868            if (!equals(other)) {
1869                env.error(0, "attempt to merge method failed:", getName(),
1870                          enclosing.getClassDefinition().getName());
1871            }
1872
1873            Vector legalExceptions = new Vector();
1874            try {
1875                collectCompatibleExceptions(
1876                      other.exceptions, exceptions, legalExceptions);
1877                collectCompatibleExceptions(
1878                      exceptions, other.exceptions, legalExceptions);
1879            } catch (ClassNotFound e) {
1880                env.error(0, "class.not.found", e.name,
1881                          enclosing.getClassDefinition().getName());
1882                return null;
1883            }
1884
1885            Method merged = (Method) clone();
1886            merged.exceptions = new ValueType[legalExceptions.size()];
1887            legalExceptions.copyInto(merged.exceptions);
1888            merged.implExceptions = merged.exceptions;
1889
1890            return merged;
1891        }
1892
1893        /**
1894         * Add to the supplied list all exceptions in the "from" array
1895         * that are subclasses of an exception in the "with" array.
1896         */
1897        private void collectCompatibleExceptions(
1898                ValueType[] from, ValueType[] with, Vector list)
1899                throws ClassNotFound {
1900
1901            for (int i = 0; i < from.length; i++) {
1902                ClassDefinition exceptionDef = from[i].getClassDefinition();
1903                if (!list.contains(from[i])) {
1904                    for (int j = 0; j < with.length; j++) {
1905                        if (exceptionDef.subClassOf(
1906                                enclosing.getEnv(),
1907                                with[j].getClassDeclaration())) {
1908                            list.addElement(from[i]);
1909                            break;
1910                        }
1911                    }
1912                }
1913            }
1914        }
1915
1916        /**
1917         * Return the compound type which contains this method.
1918         */
1919        public CompoundType getEnclosing() {
1920            return enclosing;
1921        }
1922
1923        /**
1924         * Return the identifier for the class or interface which
1925         * declares this method.
1926         */
1927        public Identifier getDeclaredBy() {
1928            return declaredBy;
1929        }
1930
1931        /**
1932         * Return the visibility (e.g. "public final") of this member.
1933         */
1934        public String getVisibility() {
1935            return vis;
1936        }
1937
1938        /**
1939         * Methods to check various attributes.
1940         */
1941        public boolean isPublic() {
1942            return memberDef.isPublic();
1943        }
1944
1945        public boolean isProtected() {
1946            return memberDef.isPrivate();
1947        }
1948
1949        public boolean isPrivate() {
1950            return memberDef.isPrivate();
1951        }
1952
1953        public boolean isStatic() {
1954            return memberDef.isStatic();
1955        }
1956
1957        /**
1958         * Return the name of this method.
1959         */
1960        public String getName() {
1961            return name;
1962        }
1963
1964        /**
1965         * IDL_Naming
1966         * Return the IDL name of this method.
1967         */
1968        public String getIDLName() {
1969            return idlName;
1970        }
1971
1972        /**
1973         * Return the type of this method.
1974         */
1975        public sun.tools.java.Type getType() {
1976            return memberDef.getType();
1977        }
1978
1979        /**
1980         * Return true if this is a constructor.
1981         */
1982        public boolean isConstructor () {
1983            return memberDef.isConstructor();
1984        }
1985
1986        /**
1987         * Return true if this is NOT a constructor {@code &&} is not
1988         * an attribute.
1989         */
1990        public boolean isNormalMethod () {
1991            return (!memberDef.isConstructor()) && attributeKind == ATTRIBUTE_NONE;
1992        }
1993
1994        /**
1995         * Get the return type of this method. May be null.
1996         */
1997        public Type getReturnType() {
1998            return returnType;
1999        }
2000
2001        /**
2002         * Return the argument types of this method.
2003         */
2004        public Type[] getArguments() {
2005            return (Type[]) arguments.clone();
2006        }
2007
2008        /**
2009         * Return the names of the argument types of this method.
2010         */
2011        public String[] getArgumentNames() {
2012            return argumentNames;
2013        }
2014
2015        /**
2016         * Return the MemberDefinition from which this method was created.
2017         */
2018        public MemberDefinition getMemberDefinition() {
2019            return memberDef;
2020        }
2021
2022        /**
2023         * Return an array of the exception classes declared to be
2024         * thrown by this remote method.
2025         *
2026         * For methods with the same name and type signature inherited
2027         * from multiple remote interfaces, the array will contain
2028         * the set of exceptions declared in all of the interfaces'
2029         * methods that can be legally thrown in each of them.
2030         */
2031        public ValueType[] getExceptions() {
2032            return (ValueType[]) exceptions.clone();
2033        }
2034
2035        /**
2036         * Same as getExceptions(), except when method is in an
2037         * ImplementationType and the exceptions list is narrower.
2038         */
2039        public ValueType[] getImplExceptions() {
2040            return (ValueType[]) implExceptions.clone();
2041        }
2042
2043        /**
2044         * Return an array containing only those exceptions which
2045         * need to be caught.  Removes java.rmi.RemoteException,
2046         * java.lang.RuntimeException, java.lang.Error, and their
2047         * subclasses, then removes any exceptions which are more
2048         * derived than another in the list. Returns null if no
2049         * exceptions need to be caught.
2050         */
2051        public ValueType[] getUniqueCatchList(ValueType[] list) {
2052            ValueType[] result = list;
2053            int newSize = list.length;
2054
2055            try {
2056
2057                // First, remove RemoteException, RuntimeException, Error, and their subclasses...
2058                for (int i = 0; i < list.length; i++) {
2059                    ClassDeclaration decl = list[i].getClassDeclaration();
2060                    if (env.defRemoteException.superClassOf(env, decl) ||
2061                        env.defRuntimeException.superClassOf(env, decl) ||
2062                        env.defError.superClassOf(env, decl)) {
2063                        list[i] = null;
2064                        newSize--;
2065                    }
2066                }
2067
2068                // Now remove derived types...
2069                for (int i = 0; i < list.length; i++) {
2070                    if (list[i] != null) {
2071                        ClassDefinition current = list[i].getClassDefinition();
2072                        for (int j = 0; j < list.length; j++) {
2073                            if (j != i && list[i] != null && list[j] != null &&
2074                                current.superClassOf(env, list[j].getClassDeclaration())) {
2075                                list[j] = null;
2076                                newSize--;
2077                            }
2078                        }
2079                    }
2080                }
2081
2082            } catch (ClassNotFound e) {
2083                classNotFound(stack,e); // Report error but do not stop.
2084            }
2085
2086            // Create new list if we removed anything...
2087
2088            if (newSize < list.length) {
2089                ValueType[] temp = new ValueType[newSize];
2090                int offset = 0;
2091                for (int i = 0; i < list.length; i++) {
2092                    if (list[i] != null) {
2093                        temp[offset++] = list[i];
2094                    }
2095                }
2096                list = temp;
2097            }
2098
2099            if (list.length == 0) {
2100                return null;
2101            } else {
2102                return list;
2103            }
2104        }
2105
2106        /**
2107         * Return an array containing only those exceptions which need to be
2108         * handled explicitly by the stub.  Removes java.lang.RuntimeException,
2109         * java.lang.Error, and their subclasses, since these are all passed
2110         * back as CORBA system exceptions.  Also removes subclasses of
2111         * java.rmi.RemoteException but not java.rmi.RemoteException itself,
2112         * since this may need to be thrown by the stub.
2113         */
2114        public ValueType[] getFilteredStubExceptions(ValueType[] list) {
2115            ValueType[] result = list;
2116            int newSize = list.length;
2117
2118            try {
2119
2120                for (int i = 0; i < list.length; i++) {
2121                    ClassDeclaration decl = list[i].getClassDeclaration();
2122                    if ((env.defRemoteException.superClassOf(env, decl) &&
2123                         !env.defRemoteException.getClassDeclaration().equals(decl)) ||
2124                        env.defRuntimeException.superClassOf(env, decl) ||
2125                        env.defError.superClassOf(env, decl)) {
2126                        list[i] = null;
2127                        newSize--;
2128                    }
2129                }
2130
2131            } catch (ClassNotFound e) {
2132                classNotFound(stack,e); // Report error but do not stop.
2133            }
2134
2135            // Create new list if we removed anything...
2136
2137            if (newSize < list.length) {
2138                ValueType[] temp = new ValueType[newSize];
2139                int offset = 0;
2140                for (int i = 0; i < list.length; i++) {
2141                    if (list[i] != null) {
2142                        temp[offset++] = list[i];
2143                    }
2144                }
2145                list = temp;
2146            }
2147
2148            return list;
2149        }
2150
2151        /**
2152         * Return the string representation of this method.
2153         */
2154        public String toString() {
2155
2156            if (stringRep == null) {
2157
2158                StringBuffer result = new StringBuffer(returnType.toString());
2159
2160                // Add name...
2161
2162                result.append(" ");
2163                result.append(getName());
2164                result.append(" (");
2165
2166                // Add arguments...
2167
2168                for (int i = 0; i < arguments.length; i++) {
2169                    if (i > 0) {
2170                        result.append(", ");
2171                    }
2172                    result.append(arguments[i]);
2173                    result.append(" ");
2174                    result.append(argumentNames[i]);
2175                }
2176
2177                result.append(")");
2178
2179                // Add exceptions...
2180
2181                for (int i = 0; i < exceptions.length; i++) {
2182                    if (i == 0) {
2183                        result.append(" throws ");
2184                    } else {
2185                        result.append(", ");
2186                    }
2187                    result.append(exceptions[i]);
2188                }
2189
2190                result.append(";");
2191
2192                stringRep = result.toString();
2193            }
2194
2195            return stringRep;
2196        }
2197
2198
2199        /**
2200         * Set attribute kind. May only be called during initialization.
2201         */
2202        public void setAttributeKind(int kind) {
2203            attributeKind = kind;
2204        }
2205
2206        /**
2207         * Set pair index. May only be called during initialization.
2208         */
2209        public void setAttributePairIndex(int index) {
2210            attributePairIndex = index;
2211        }
2212
2213        /**
2214         * Set attribute name. May only be called during initialization.
2215         */
2216        public void setAttributeName(String name) {
2217            attributeName = name;
2218        }
2219
2220        /**
2221         * Set the idl name. May only be called during initialization.
2222         */
2223        public void setIDLName (String idlName) {
2224            this.idlName=idlName;
2225        }
2226
2227        /**
2228         * Set the implExceptions array. May only be called during initialization.
2229         */
2230        public void setImplExceptions (ValueType[] exceptions) {
2231            implExceptions = exceptions;
2232        }
2233
2234        /**
2235         * Set the declaredBy Identifier. May only be called during initialization.
2236         */
2237        public void setDeclaredBy (Identifier by) {
2238            declaredBy = by;
2239        }
2240
2241        /**
2242         * Convert all invalid types to valid ones.
2243         */
2244        protected void swapInvalidTypes () {
2245
2246            // Check return type...
2247
2248            if (returnType.getStatus() != STATUS_VALID) {
2249                returnType = getValidType(returnType);
2250            }
2251
2252            // Check args...
2253
2254            for (int i = 0; i < arguments.length; i++) {
2255                if (arguments[i].getStatus() != STATUS_VALID) {
2256                    arguments[i] = getValidType(arguments[i]);
2257                }
2258            }
2259
2260            // Check exceptions...
2261
2262            for (int i = 0; i < exceptions.length; i++) {
2263                if (exceptions[i].getStatus() != STATUS_VALID) {
2264                    exceptions[i] = (ValueType)getValidType(exceptions[i]);
2265                }
2266            }
2267
2268            // Check implExceptions...
2269
2270            for (int i = 0; i < implExceptions.length; i++) {
2271                if (implExceptions[i].getStatus() != STATUS_VALID) {
2272                    implExceptions[i] = (ValueType)getValidType(implExceptions[i]);
2273                }
2274            }
2275        }
2276
2277        /**
2278         * Release all resources.
2279         */
2280        public void destroy () {
2281            if (memberDef != null) {
2282                memberDef = null;
2283                enclosing = null;
2284                if (exceptions != null) {
2285                    for (int i = 0; i < exceptions.length; i++) {
2286                        if (exceptions[i] != null) exceptions[i].destroy();
2287                        exceptions[i] = null;
2288                    }
2289                    exceptions = null;
2290                }
2291
2292                if (implExceptions != null) {
2293                    for (int i = 0; i < implExceptions.length; i++) {
2294                        if (implExceptions[i] != null) implExceptions[i].destroy();
2295                        implExceptions[i] = null;
2296                    }
2297                    implExceptions = null;
2298                }
2299
2300                if (returnType != null) returnType.destroy();
2301                returnType = null;
2302
2303                if (arguments != null) {
2304                    for (int i = 0; i < arguments.length; i++) {
2305                        if (arguments[i] != null) arguments[i].destroy();
2306                        arguments[i] = null;
2307                    }
2308                    arguments = null;
2309                }
2310
2311                if (argumentNames != null) {
2312                    for (int i = 0; i < argumentNames.length; i++) {
2313                        argumentNames[i] = null;
2314                    }
2315                    argumentNames = null;
2316                }
2317
2318                vis = null;
2319                name = null;
2320                idlName = null;
2321                stringRep = null;
2322                attributeName = null;
2323                declaredBy = null;
2324            }
2325        }
2326
2327        private MemberDefinition memberDef;
2328        private CompoundType enclosing;
2329        private ValueType[] exceptions;
2330        private ValueType[] implExceptions;
2331        private Type returnType;
2332        private Type[] arguments;
2333        private String[] argumentNames;
2334        private String vis;
2335        private String name;
2336        private String idlName;
2337        private String stringRep = null;
2338        private int attributeKind = ATTRIBUTE_NONE;
2339        private String attributeName = null;
2340        private int attributePairIndex = -1;
2341        private Identifier declaredBy = null;
2342
2343        /**
2344         * Make up an argument name for the given type.
2345         */
2346        private String makeArgName (int argNum, Type type) {
2347            return "arg" + argNum;
2348        }
2349
2350        /**
2351         * Create a new Method object corresponding to the given
2352         * method definition.
2353         */
2354        public Method (CompoundType enclosing,
2355                       MemberDefinition memberDef,
2356                       boolean quiet,
2357                       ContextStack stack) throws Exception {
2358
2359            this.enclosing = enclosing;
2360            this.memberDef = memberDef;
2361            vis = getVisibilityString(memberDef);
2362            idlName = null; // See setIDLName()
2363            boolean valid = true;
2364            declaredBy = memberDef.getClassDeclaration().getName();
2365
2366            // Set name...
2367
2368            name = memberDef.getName().toString();
2369
2370            // Update the context...
2371
2372            stack.setNewContextCode(ContextStack.METHOD);
2373            stack.push(this);
2374
2375            // Set return type...
2376
2377            stack.setNewContextCode(ContextStack.METHOD_RETURN);
2378            sun.tools.java.Type methodType = memberDef.getType();
2379            sun.tools.java.Type rtnType = methodType.getReturnType();
2380
2381            if (rtnType == sun.tools.java.Type.tVoid) {
2382                returnType = PrimitiveType.forPrimitive(rtnType,stack);
2383            } else {
2384                returnType = makeType(rtnType,null,stack);
2385                if (returnType == null ||
2386                    !assertNotImpl(returnType,quiet,stack,enclosing,false)) {
2387                    valid = false;
2388                    failedConstraint(24,quiet,stack,enclosing.getName());
2389                }
2390            }
2391
2392            // Set arguments and argument names...
2393
2394            stack.setNewContextCode(ContextStack.METHOD_ARGUMENT);
2395            sun.tools.java.Type[] args = memberDef.getType().getArgumentTypes();
2396            arguments = new Type[args.length];
2397            argumentNames = new String[args.length];
2398            Vector origArgNames = memberDef.getArguments();
2399
2400            for (int i = 0; i < args.length; i++) {
2401                Type type = null;
2402                try {
2403                    type = makeType(args[i],null,stack);
2404                } catch (Exception e) {
2405                }
2406
2407                if (type != null) {
2408                    if (!assertNotImpl(type,quiet,stack,enclosing,false)) {
2409                        valid = false;
2410                    } else {
2411                    arguments[i] = type;
2412                    if (origArgNames != null) {
2413                        LocalMember local = (LocalMember)origArgNames.elementAt(i+1);
2414                        argumentNames[i] = local.getName().toString();
2415                    } else {
2416                        argumentNames[i] = makeArgName(i,type);
2417                    }
2418                    }
2419                } else {
2420                    valid = false;
2421                    failedConstraint(25,false,stack,enclosing.getQualifiedName(),name);
2422                }
2423            }
2424
2425            if (!valid) {
2426                stack.pop(false);
2427                throw new Exception();
2428            }
2429
2430            // Set exceptions...
2431
2432            try {
2433                exceptions = enclosing.getMethodExceptions(memberDef,quiet,stack);
2434                implExceptions = exceptions;
2435                stack.pop(true);
2436            } catch (Exception e) {
2437                stack.pop(false);
2438                throw new Exception();
2439            }
2440        }
2441
2442        /**
2443         * Cloning is supported by returning a shallow copy of this object.
2444         */
2445        protected Object clone() {
2446            try {
2447                return super.clone();
2448            } catch (CloneNotSupportedException e) {
2449                throw new Error("clone failed");
2450            }
2451        }
2452    }
2453
2454    //_____________________________________________________________________
2455    // Inner Class "Member"
2456    //_____________________________________________________________________
2457
2458    /**
2459     * An CompoundType.Member object wraps a Type and a value representing
2460     * a data member, including constants.
2461     */
2462    public class Member implements ContextElement, Cloneable {
2463
2464        /**
2465         * Return context element name.
2466         */
2467        public String getElementName() {
2468            return "\"" + getName() + "\"";
2469        }
2470
2471        /**
2472         * Return the type of this member.
2473         */
2474        public Type getType() {
2475            return type;
2476        }
2477
2478        /**
2479         * Return the name of this member.
2480         */
2481        public String getName() {
2482            return name;
2483        }
2484
2485        /**
2486         * IDL_Naming
2487         * Return the IDL name of this member.
2488         */
2489        public String getIDLName() {
2490            return idlName;
2491        }
2492
2493        /**
2494         * Return the visibility (e.g. "public final") of this member.
2495         */
2496        public String getVisibility() {
2497            return vis;
2498        }
2499
2500        /**
2501         * Methods to check various attributes.
2502         */
2503        public boolean isPublic() {
2504            return member.isPublic();
2505        }
2506
2507        public boolean isPrivate() {
2508            return member.isPrivate();
2509        }
2510
2511        public boolean isStatic() {
2512            return member.isStatic();
2513        }
2514
2515        public boolean isFinal() {
2516            return member.isFinal();
2517        }
2518
2519        public boolean isTransient() {
2520            if (forceTransient) return true;
2521            return member.isTransient();
2522        }
2523
2524        /**
2525         * Return the value of this member. May be null.
2526         */
2527        public String getValue() {
2528            return value;
2529        }
2530
2531        /**
2532         * Return true if this member represents an inner class declaration,
2533         * false otherwise.
2534         */
2535        public boolean isInnerClassDeclaration() {
2536            return innerClassDecl;
2537        }
2538
2539        /**
2540         * Return true if this member represents a constant.
2541         */
2542        public boolean isConstant () {
2543            return constant;
2544        }
2545
2546        /**
2547         * Return the string representation of this constant.
2548         */
2549        public String toString() {
2550
2551            String result = type.toString();
2552
2553            if (value != null) {
2554                result += (" = " + value);
2555            }
2556
2557            return result;
2558        }
2559
2560        /**
2561         * Convert all invalid types to valid ones.
2562         */
2563        protected void swapInvalidTypes () {
2564            if (type.getStatus() != STATUS_VALID) {
2565                type = getValidType(type);
2566            }
2567        }
2568
2569        protected void setTransient() {
2570            if (! isTransient()) {
2571                forceTransient = true;
2572                if (vis.length() > 0) {
2573                    vis = vis + " transient";
2574                } else {
2575                    vis = "transient";
2576                }
2577            }
2578        }
2579
2580        protected MemberDefinition getMemberDefinition() {
2581            return member;
2582        }
2583
2584        /**
2585         * Release all resources.
2586         */
2587        public void destroy () {
2588            if (type != null) {
2589                type.destroy();
2590                type = null;
2591                vis = null;
2592                value = null;
2593                name = null;
2594                idlName = null;
2595                member = null;
2596            }
2597        }
2598
2599        private Type type;
2600        private String vis;
2601        private String value;
2602        private String name;
2603        private String idlName;
2604        private boolean innerClassDecl;
2605        private boolean constant;
2606        private MemberDefinition member;
2607        private boolean forceTransient;
2608
2609        /**
2610         * Create a new Member object.
2611         */
2612        public Member(MemberDefinition member,
2613                      String value,
2614                      ContextStack stack,
2615                      CompoundType enclosing) {
2616            this.member = member;
2617            this.value = value;
2618            forceTransient = false;
2619            innerClassDecl = member.getInnerClass() != null;
2620
2621            // If we are not an inner class, finish initializing now.
2622            // Otherwise, wait until outer class is finished, then
2623            // call init to avoid potential recursion problems...
2624
2625            if (!innerClassDecl) {
2626                init (stack,enclosing);
2627            }
2628        }
2629
2630        public void init (ContextStack stack, CompoundType enclosing) {
2631
2632            constant = false;
2633            name = member.getName().toString();
2634            vis = getVisibilityString(member);
2635            idlName = null;
2636
2637            // Add self to stack...
2638
2639            int contextCode = ContextStack.MEMBER;
2640            stack.setNewContextCode(contextCode);
2641
2642            // Check for special contextCodes...
2643
2644            if (member.isVariable()) {
2645                if (value != null && member.isConstant()) {
2646                    contextCode = ContextStack.MEMBER_CONSTANT;
2647                    this.constant = true;
2648                } else if (member.isStatic()) {
2649                    contextCode = ContextStack.MEMBER_STATIC;
2650                } else if (member.isTransient()) {
2651                    contextCode = ContextStack.MEMBER_TRANSIENT;
2652                }
2653            }
2654
2655            stack.setNewContextCode(contextCode);
2656            stack.push(this);
2657
2658            type = makeType(member.getType(),null,stack);
2659
2660            if (type == null ||
2661                (!innerClassDecl &&
2662                 !member.isStatic() &&
2663                 !member.isTransient() &&
2664                 !assertNotImpl(type,false,stack,enclosing,true))) {
2665                stack.pop(false);
2666                throw new CompilerError("");
2667            }
2668
2669            // Clean up primitive constant values...
2670
2671            if (constant && type.isPrimitive()) {
2672                if (type.isType(TYPE_LONG) || type.isType(TYPE_FLOAT) || type.isType(TYPE_DOUBLE)) {
2673                    int length = value.length();
2674                    char lastChar = value.charAt(length-1);
2675                    if (!Character.isDigit(lastChar)) {
2676                        this.value = value.substring(0,length-1);
2677                    }
2678                } else if (type.isType(TYPE_BOOLEAN)) {
2679                    value = value.toUpperCase();
2680                }
2681            }
2682            if (constant && type.isType(TYPE_STRING)) {
2683                value = "L" + value;
2684            }
2685            stack.pop(true);
2686        }
2687
2688        public void setIDLName (String name) {
2689            this.idlName = name;
2690        }
2691
2692        /**
2693         * Cloning is supported by returning a shallow copy of this object.
2694         */
2695        protected Object clone() {
2696            try {
2697                return super.clone();
2698            } catch (CloneNotSupportedException e) {
2699                throw new Error("clone failed");
2700            }
2701        }
2702    }
2703}
2704