aoqi@0: /* aoqi@0: * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * Licensed Materials - Property of IBM aoqi@0: * RMI-IIOP v1.0 aoqi@0: * Copyright IBM Corp. 1998 1999 All Rights Reserved aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: package sun.rmi.rmic.iiop; aoqi@0: aoqi@0: import java.util.Arrays; aoqi@0: import java.util.Vector; aoqi@0: import sun.tools.java.Identifier; aoqi@0: import sun.tools.java.ClassNotFound; aoqi@0: import sun.tools.java.ClassDefinition; aoqi@0: import sun.tools.java.ClassDeclaration; aoqi@0: import sun.tools.java.MemberDefinition; aoqi@0: import sun.tools.java.CompilerError; aoqi@0: import sun.tools.tree.Node; aoqi@0: import sun.tools.tree.LocalMember; aoqi@0: import sun.tools.tree.CharExpression; aoqi@0: import sun.tools.tree.IntegerExpression; aoqi@0: import sun.rmi.rmic.IndentingWriter; aoqi@0: import java.io.IOException; aoqi@0: import java.util.HashSet; aoqi@0: import java.util.Enumeration; aoqi@0: import java.io.File; aoqi@0: aoqi@0: /** aoqi@0: * A CompoundType is an abstract base class for all IIOP class and aoqi@0: * interface types. aoqi@0: * aoqi@0: * @author Bryan Atsatt aoqi@0: */ aoqi@0: public abstract class CompoundType extends Type { aoqi@0: aoqi@0: protected Method[] methods; aoqi@0: protected InterfaceType[] interfaces; aoqi@0: protected Member[] members; aoqi@0: protected ClassDefinition classDef; aoqi@0: protected ClassDeclaration classDecl; aoqi@0: aoqi@0: protected boolean isCORBAObject = false; aoqi@0: protected boolean isIDLEntity = false; aoqi@0: protected boolean isAbstractBase = false; aoqi@0: protected boolean isValueBase = false; aoqi@0: protected boolean isCORBAUserException = false; aoqi@0: protected boolean isException = false; aoqi@0: protected boolean isCheckedException = false; aoqi@0: protected boolean isRemoteExceptionOrSubclass = false; aoqi@0: protected String idlExceptionName; aoqi@0: protected String qualifiedIDLExceptionName; aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Public Interfaces aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type implements aoqi@0: * org.omg.CORBA.Object. aoqi@0: */ aoqi@0: public boolean isCORBAObject () { aoqi@0: return isCORBAObject; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type implements aoqi@0: * org.omg.CORBA.portable.IDLEntity. aoqi@0: */ aoqi@0: public boolean isIDLEntity () { aoqi@0: return isIDLEntity; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type implements aoqi@0: * org.omg.CORBA.portable.ValueBase. aoqi@0: */ aoqi@0: public boolean isValueBase () { aoqi@0: return isValueBase; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is a CORBA aoqi@0: * abstract interface. aoqi@0: */ aoqi@0: public boolean isAbstractBase () { aoqi@0: return isAbstractBase; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is an exception. aoqi@0: */ aoqi@0: public boolean isException () { aoqi@0: return isException; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is a "checked" exception. aoqi@0: * Result if valid iff isException() returns true. aoqi@0: */ aoqi@0: public boolean isCheckedException () { aoqi@0: return isCheckedException; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is a java.rmi.RemoteException aoqi@0: * or one of its subclasses. Result if valid iff isException() aoqi@0: * returns true. aoqi@0: */ aoqi@0: public boolean isRemoteExceptionOrSubclass () { aoqi@0: return isRemoteExceptionOrSubclass; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type is exactly aoqi@0: * org.omg.CORBA.UserException. aoqi@0: */ aoqi@0: public boolean isCORBAUserException () { aoqi@0: return isCORBAUserException; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this type implements aoqi@0: * isIDLEntity() && isException(). aoqi@0: */ aoqi@0: public boolean isIDLEntityException () { aoqi@0: return isIDLEntity() && isException(); aoqi@0: } aoqi@0: /** aoqi@0: * Return true if isIDLEntity() && !isValueBase() aoqi@0: * && !isAbstractBase() && !isCORBAObject() aoqi@0: * && !isIDLEntityException(). aoqi@0: */ aoqi@0: public boolean isBoxed () { aoqi@0: return (isIDLEntity() && !isValueBase() && aoqi@0: !isAbstractBase() && !isCORBAObject() && aoqi@0: !isIDLEntityException()); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * If this type represents an exception, return the aoqi@0: * IDL name including the "Ex" mangling, otherwise aoqi@0: * return null. aoqi@0: */ aoqi@0: public String getIDLExceptionName () { aoqi@0: return idlExceptionName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * If this type represents an exception, return the aoqi@0: * qualified IDL name including the "Ex" mangling, aoqi@0: * otherwise return null. aoqi@0: * @param global If true, prepends "::". aoqi@0: */ aoqi@0: public String getQualifiedIDLExceptionName (boolean global) { aoqi@0: if (qualifiedIDLExceptionName != null && aoqi@0: global && aoqi@0: getIDLModuleNames().length > 0) { aoqi@0: return IDL_NAME_SEPARATOR + qualifiedIDLExceptionName; aoqi@0: } else { aoqi@0: return qualifiedIDLExceptionName; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return signature for this type (e.g. com.acme.Dynamite aoqi@0: * would return "com.acme.Dynamite", byte = "B") aoqi@0: */ aoqi@0: public String getSignature() { aoqi@0: String sig = classDecl.getType().getTypeSignature(); aoqi@0: if (sig.endsWith(";")) { aoqi@0: sig = sig.substring(0,sig.length()-1); aoqi@0: } aoqi@0: return sig; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the ClassDeclaration for this type. aoqi@0: */ aoqi@0: public ClassDeclaration getClassDeclaration() { aoqi@0: return classDecl; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the ClassDefinition for this type. aoqi@0: */ aoqi@0: public ClassDefinition getClassDefinition() { aoqi@0: return classDef; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the parent class of this type. Returns null if this aoqi@0: * type is an interface or if there is no parent. aoqi@0: */ aoqi@0: public ClassType getSuperclass() { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array of interfaces directly implemented by this type. aoqi@0: *

aoqi@0: * The order of the array returned is arbitrary. aoqi@0: */ aoqi@0: public InterfaceType[] getInterfaces() { aoqi@0: if( interfaces != null ) { aoqi@0: return (InterfaceType[]) interfaces.clone(); aoqi@0: } aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array of Type.Method objects representing all aoqi@0: * of the methods implemented directly by this type. aoqi@0: */ aoqi@0: public Method[] getMethods() { aoqi@0: if( methods != null ) { aoqi@0: return (Method[]) methods.clone(); aoqi@0: } aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array of Type.Member objects representing all of aoqi@0: * the data members directly implemented by this interface. aoqi@0: */ aoqi@0: public Member[] getMembers() { aoqi@0: if( members != null ) { aoqi@0: return (Member[]) members.clone(); aoqi@0: } aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Create a CompoundType object for the given class. aoqi@0: * aoqi@0: * If the class is not a properly formed or if some other error occurs, the aoqi@0: * return value will be null, and errors will have been reported to the aoqi@0: * supplied BatchEnvironment. aoqi@0: */ aoqi@0: public static CompoundType forCompound (ClassDefinition classDef, aoqi@0: ContextStack stack) { aoqi@0: CompoundType result = null; aoqi@0: aoqi@0: try { aoqi@0: result = (CompoundType) makeType(classDef.getType(),classDef,stack); aoqi@0: } catch (ClassCastException e) {} aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Subclass/Internal Interfaces aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * Release all resources. aoqi@0: */ aoqi@0: protected void destroy () { aoqi@0: if (!destroyed) { aoqi@0: super.destroy(); aoqi@0: aoqi@0: if (methods != null) { aoqi@0: for (int i = 0; i < methods.length; i++) { aoqi@0: if (methods[i] != null) methods[i].destroy(); aoqi@0: } aoqi@0: methods = null; aoqi@0: } aoqi@0: aoqi@0: if (interfaces != null) { aoqi@0: for (int i = 0; i < interfaces.length; i++) { aoqi@0: if (interfaces[i] != null) interfaces[i].destroy(); aoqi@0: } aoqi@0: interfaces = null; aoqi@0: } aoqi@0: aoqi@0: if (members != null) { aoqi@0: for (int i = 0; i < members.length; i++) { aoqi@0: if (members[i] != null) members[i].destroy(); aoqi@0: } aoqi@0: members = null; aoqi@0: } aoqi@0: aoqi@0: classDef = null; aoqi@0: classDecl = null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Load a Class instance. Return null if fail. aoqi@0: */ aoqi@0: protected Class loadClass() { aoqi@0: aoqi@0: Class ourClass = null; aoqi@0: aoqi@0: // To avoid getting out-of-date Class instances, and aoqi@0: // to ensure that there is an instance, we must compile aoqi@0: // any classes that we've seen and which are not yet aoqi@0: // compiled. We can't just compile this class, 'cuz it aoqi@0: // may have dependencies on classes which have not been aoqi@0: // compiled... aoqi@0: aoqi@0: try { aoqi@0: env.getMain().compileAllClasses(env); aoqi@0: } catch (Exception e1) { aoqi@0: for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) { aoqi@0: ClassDeclaration c = (ClassDeclaration)e.nextElement(); aoqi@0: } aoqi@0: failedConstraint(26,false,stack,"required classes"); aoqi@0: env.flushErrors(); aoqi@0: } aoqi@0: aoqi@0: // Now try to get the Class... aoqi@0: // The outer try block is there for people who might want to use aoqi@0: // the compiler at run-time of their AS. aoqi@0: // They could set and use their own context class loader for loading aoqi@0: // classes directly. aoqi@0: try { aoqi@0: ClassLoader cl = Thread.currentThread().getContextClassLoader(); aoqi@0: ourClass = cl.loadClass(getQualifiedName()); aoqi@0: } catch(ClassNotFoundException cfe) { aoqi@0: aoqi@0: try { aoqi@0: ourClass = env.classPathLoader.loadClass(getQualifiedName()); aoqi@0: } catch (NullPointerException e) { aoqi@0: // This should never happen aoqi@0: } catch (ClassNotFoundException e) { aoqi@0: // Fall through to the next case (which is to look in the aoqi@0: // output directory for generated files) aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* This piece of code used to cause the compiler to ignore jar files aoqi@0: on its classpath aoqi@0: try { aoqi@0: ourClass = Util.loadClass(getQualifiedName(),null,null); aoqi@0: } catch (ClassNotFoundException e) { aoqi@0: } catch (LinkageError e) { aoqi@0: } aoqi@0: */ aoqi@0: aoqi@0: if (ourClass == null) { aoqi@0: aoqi@0: // Try one last thing. If the class was compiled into aoqi@0: // a directory that's not in the classpath, the load aoqi@0: // will fail. Let's get the bits off the disk and load aoqi@0: // it directly... aoqi@0: aoqi@0: if (env.loader == null) { aoqi@0: File destDir = env.getMain().getDestinationDir(); aoqi@0: if (destDir == null) { aoqi@0: destDir = new File("."); aoqi@0: } aoqi@0: env.loader = new DirectoryLoader(destDir); aoqi@0: } aoqi@0: aoqi@0: try { aoqi@0: ourClass = env.loader.loadClass(getQualifiedName()); aoqi@0: } catch (Exception e) {} aoqi@0: } aoqi@0: aoqi@0: return ourClass; aoqi@0: } aoqi@0: aoqi@0: // Print "extends XX" aoqi@0: aoqi@0: protected boolean printExtends (IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: ClassType parent = getSuperclass(); aoqi@0: aoqi@0: if (parent != null && (!useIDLNames || aoqi@0: (!parent.isType(TYPE_ANY) && !parent.isType(TYPE_CORBA_OBJECT)))) { aoqi@0: writer.p(" extends "); aoqi@0: parent.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // Print "implements XX, YY" aoqi@0: aoqi@0: protected void printImplements (IndentingWriter writer, aoqi@0: String prefix, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: InterfaceType[] interfaces = getInterfaces(); aoqi@0: aoqi@0: String adjective = " implements"; aoqi@0: aoqi@0: if (isInterface()) { aoqi@0: adjective = " extends"; aoqi@0: } aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: adjective = ":"; aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < interfaces.length; i++) { aoqi@0: if (!useIDLNames || (!interfaces[i].isType(TYPE_ANY) && !interfaces[i].isType(TYPE_CORBA_OBJECT))) { aoqi@0: if (i == 0) { aoqi@0: writer.p(prefix + adjective + " "); aoqi@0: } else { aoqi@0: writer.p(", "); aoqi@0: } aoqi@0: interfaces[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Print members aoqi@0: aoqi@0: protected void printMembers ( IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: CompoundType.Member[] members = getMembers(); aoqi@0: aoqi@0: for (int i = 0; i < members.length; i++) { aoqi@0: if (!members[i].isInnerClassDeclaration()) { aoqi@0: Type it = members[i].getType(); aoqi@0: String visibility = members[i].getVisibility(); aoqi@0: String name; aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: name = members[i].getIDLName(); aoqi@0: } else { aoqi@0: name = members[i].getName(); aoqi@0: } aoqi@0: aoqi@0: String value = members[i].getValue(); aoqi@0: aoqi@0: writer.p(visibility); aoqi@0: if (visibility.length() > 0) { aoqi@0: writer.p(" "); aoqi@0: } aoqi@0: it.printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: writer.p(" " + name); aoqi@0: aoqi@0: if (value != null) { aoqi@0: writer.pln(" = " + value + ";"); aoqi@0: } else { aoqi@0: writer.pln(";"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Print methods aoqi@0: aoqi@0: protected void printMethods ( IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: CompoundType.Method[] methods = getMethods(); aoqi@0: aoqi@0: for (int m = 0; m < methods.length; m++) { aoqi@0: CompoundType.Method theMethod = methods[m]; aoqi@0: printMethod(theMethod,writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Print a method... aoqi@0: aoqi@0: protected void printMethod (CompoundType.Method it, aoqi@0: IndentingWriter writer, aoqi@0: boolean useQualifiedNames, aoqi@0: boolean useIDLNames, aoqi@0: boolean globalIDLNames) throws IOException { aoqi@0: aoqi@0: aoqi@0: // Write visibility... aoqi@0: aoqi@0: String visibility = it.getVisibility(); aoqi@0: aoqi@0: writer.p(visibility); aoqi@0: if (visibility.length() > 0) { aoqi@0: writer.p(" "); aoqi@0: } aoqi@0: aoqi@0: // Write return type... aoqi@0: aoqi@0: it.getReturnType().printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: aoqi@0: // Write method name... aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: writer.p(" " + it.getIDLName()); aoqi@0: } else { aoqi@0: writer.p(" " + it.getName()); aoqi@0: } aoqi@0: aoqi@0: // Write arguments... aoqi@0: aoqi@0: writer.p(" ("); aoqi@0: Type[] args = it.getArguments(); aoqi@0: String[] argNames = it.getArgumentNames(); aoqi@0: aoqi@0: for (int i = 0; i < args.length; i++) { aoqi@0: if (i > 0) { aoqi@0: writer.p(", "); aoqi@0: } aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: writer.p("in "); aoqi@0: } aoqi@0: aoqi@0: args[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: writer.p(" " + argNames[i]); aoqi@0: } aoqi@0: writer.p(")"); aoqi@0: aoqi@0: // Write exceptions... aoqi@0: aoqi@0: ClassType[] exceptions; aoqi@0: aoqi@0: if (isType(TYPE_IMPLEMENTATION)) { aoqi@0: exceptions = it.getImplExceptions(); aoqi@0: } else { aoqi@0: exceptions = it.getExceptions(); aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: if (i == 0) { aoqi@0: if (useIDLNames) { aoqi@0: writer.p(" raises ("); aoqi@0: } else { aoqi@0: writer.p(" throws "); aoqi@0: } aoqi@0: } else { aoqi@0: writer.p(", "); aoqi@0: } aoqi@0: aoqi@0: if (useIDLNames) { aoqi@0: if (useQualifiedNames) { aoqi@0: writer.p(exceptions[i].getQualifiedIDLExceptionName(globalIDLNames)); aoqi@0: } else { aoqi@0: writer.p(exceptions[i].getIDLExceptionName()); aoqi@0: } aoqi@0: writer.p(" [a.k.a. "); aoqi@0: exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: writer.p("]"); aoqi@0: } else { aoqi@0: exceptions[i].printTypeName(writer,useQualifiedNames,useIDLNames,globalIDLNames); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (useIDLNames && exceptions.length > 0) { aoqi@0: writer.p(")"); aoqi@0: } aoqi@0: aoqi@0: if (it.isInherited()) { aoqi@0: writer.p(" // Inherited from "); aoqi@0: writer.p(it.getDeclaredBy()); aoqi@0: } aoqi@0: aoqi@0: writer.pln(";"); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Create a CompoundType instance for the given class. NOTE: This constructor aoqi@0: * is ONLY for SpecialClassType and SpecialInterfaceType. aoqi@0: */ aoqi@0: protected CompoundType(ContextStack stack, int typeCode, ClassDefinition classDef) { aoqi@0: super(stack,typeCode); aoqi@0: this.classDef = classDef; aoqi@0: classDecl = classDef.getClassDeclaration(); aoqi@0: interfaces = new InterfaceType[0]; aoqi@0: methods = new Method[0]; aoqi@0: members = new Member[0]; aoqi@0: aoqi@0: // If we are an inner class/interface, reset the type codes... aoqi@0: aoqi@0: if (classDef.isInnerClass()) { aoqi@0: setTypeCode(typeCode | TM_INNER); aoqi@0: } aoqi@0: aoqi@0: // Set special flags... aoqi@0: aoqi@0: setFlags(); aoqi@0: } aoqi@0: aoqi@0: private void setFlags() { aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: // Set our special interface flags... aoqi@0: aoqi@0: isCORBAObject = env.defCorbaObject.implementedBy(env,classDecl); aoqi@0: isIDLEntity = env.defIDLEntity.implementedBy(env,classDecl); aoqi@0: isValueBase = env.defValueBase.implementedBy(env,classDecl); aoqi@0: isAbstractBase = isInterface() && // Interface, not a class. aoqi@0: isIDLEntity && // Implements IDLEntity. aoqi@0: !isValueBase && // Does not implement ValueBase. aoqi@0: !isCORBAObject; // Does not implement org.omg.CORBA.Object; aoqi@0: isCORBAUserException = (classDecl.getName() == idCorbaUserException); aoqi@0: aoqi@0: // Is this an exception? aoqi@0: aoqi@0: if (env.defThrowable.implementedBy(env, classDecl)) { aoqi@0: aoqi@0: // Yes... aoqi@0: aoqi@0: isException = true; aoqi@0: aoqi@0: // Is it a checked exception? aoqi@0: aoqi@0: if (env.defRuntimeException.implementedBy(env,classDecl) || aoqi@0: env.defError.implementedBy(env,classDecl)) { aoqi@0: isCheckedException = false; aoqi@0: } else { aoqi@0: isCheckedException = true; aoqi@0: } aoqi@0: aoqi@0: // Is it java.rmi.RemoteException or a subclass? aoqi@0: aoqi@0: if (env.defRemoteException.implementedBy(env,classDecl)) { aoqi@0: isRemoteExceptionOrSubclass = true; aoqi@0: } else { aoqi@0: isRemoteExceptionOrSubclass = false; aoqi@0: } aoqi@0: } else { aoqi@0: isException = false; aoqi@0: } aoqi@0: } catch (ClassNotFound e) { aoqi@0: classNotFound(stack,e); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Create a CompoundType instance for the given class. The resulting aoqi@0: * object is not yet completely initialized. aoqi@0: */ aoqi@0: protected CompoundType(ContextStack stack, ClassDefinition classDef, aoqi@0: int typeCode) { aoqi@0: super(stack,typeCode); aoqi@0: this.classDef = classDef; aoqi@0: classDecl = classDef.getClassDeclaration(); aoqi@0: aoqi@0: // If we are an inner class/interface, reset the type codes... aoqi@0: aoqi@0: if (classDef.isInnerClass()) { aoqi@0: setTypeCode(typeCode | TM_INNER); aoqi@0: } aoqi@0: aoqi@0: // Set special flags... aoqi@0: aoqi@0: setFlags(); aoqi@0: aoqi@0: // Set names... aoqi@0: aoqi@0: Identifier id = classDef.getName(); aoqi@0: String idlName; aoqi@0: String[] idlModuleNames; aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: // These can fail if we get case-sensitive name matches... aoqi@0: aoqi@0: idlName = IDLNames.getClassOrInterfaceName(id,env); aoqi@0: idlModuleNames = IDLNames.getModuleNames(id,isBoxed(),env); aoqi@0: aoqi@0: setNames(id,idlModuleNames,idlName); aoqi@0: aoqi@0: // Is this an exception? aoqi@0: aoqi@0: if (isException()) { aoqi@0: aoqi@0: // Yes, so set our mangled exception names... aoqi@0: aoqi@0: isException = true; aoqi@0: idlExceptionName = IDLNames.getExceptionName(getIDLName()); aoqi@0: qualifiedIDLExceptionName = aoqi@0: IDLNames.getQualifiedName(getIDLModuleNames(),idlExceptionName); aoqi@0: } aoqi@0: aoqi@0: // Set interfaces, methods and members... aoqi@0: aoqi@0: interfaces = null; // set in initialize() aoqi@0: methods = null; // set in initialize() aoqi@0: members = null; // set in initialize() aoqi@0: aoqi@0: } catch (Exception e) { aoqi@0: failedConstraint(7,false,stack,id.toString(),e.getMessage()); aoqi@0: throw new CompilerError(""); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Initialize this instance. aoqi@0: */ aoqi@0: protected boolean initialize ( Vector directInterfaces, aoqi@0: Vector directMethods, aoqi@0: Vector directMembers, aoqi@0: ContextStack stack, aoqi@0: boolean quiet) { aoqi@0: aoqi@0: boolean result = true; aoqi@0: aoqi@0: // Initialize our arrays... aoqi@0: aoqi@0: if (directInterfaces != null && directInterfaces.size() > 0) { aoqi@0: interfaces = new InterfaceType[directInterfaces.size()]; aoqi@0: directInterfaces.copyInto(interfaces); aoqi@0: } else { aoqi@0: interfaces = new InterfaceType[0]; aoqi@0: } aoqi@0: aoqi@0: if (directMethods != null && directMethods.size() > 0) { aoqi@0: methods = new Method[directMethods.size()]; aoqi@0: directMethods.copyInto(methods); aoqi@0: aoqi@0: // Now set the idl names for each... aoqi@0: aoqi@0: try { aoqi@0: IDLNames.setMethodNames(this, methods,env); aoqi@0: } catch (Exception e) { aoqi@0: failedConstraint(13,quiet,stack,getQualifiedName(),e.getMessage()); aoqi@0: result = false; aoqi@0: } aoqi@0: aoqi@0: } else { aoqi@0: methods = new Method[0]; aoqi@0: } aoqi@0: aoqi@0: if (directMembers != null && directMembers.size() > 0) { aoqi@0: members = new Member[directMembers.size()]; aoqi@0: directMembers.copyInto(members); aoqi@0: aoqi@0: // If we have any un-initialized inner classes, now is the time aoqi@0: // to init them... aoqi@0: aoqi@0: for (int i = 0; i < members.length; i++) { aoqi@0: if (members[i].isInnerClassDeclaration()) { aoqi@0: try { aoqi@0: members[i].init(stack,this); aoqi@0: } catch (CompilerError e) { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Now set the idl names for each... aoqi@0: aoqi@0: try { aoqi@0: IDLNames.setMemberNames(this, members,methods,env); aoqi@0: } catch (Exception e) { aoqi@0: int constraint = classDef.isInterface() ? 19 : 20; aoqi@0: failedConstraint(constraint,quiet,stack,getQualifiedName(),e.getMessage()); aoqi@0: result = false; aoqi@0: } aoqi@0: aoqi@0: } else { aoqi@0: members = new Member[0]; aoqi@0: } aoqi@0: aoqi@0: // Set our repositoryID... aoqi@0: aoqi@0: if (result) { aoqi@0: result = setRepositoryID(); aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Return Type or null if error. classDef may be null. aoqi@0: */ aoqi@0: protected static Type makeType (sun.tools.java.Type theType, aoqi@0: ClassDefinition classDef, aoqi@0: ContextStack stack) { aoqi@0: aoqi@0: if (stack.anyErrors()) return null; aoqi@0: aoqi@0: // See if we can find this type in the cache. If so, return it... aoqi@0: aoqi@0: String key = theType.toString(); aoqi@0: aoqi@0: Type result = getType(key,stack); aoqi@0: aoqi@0: if (result != null) { aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: // Gotta try with context... aoqi@0: aoqi@0: result = getType(key + stack.getContextCodeString(),stack); aoqi@0: aoqi@0: if (result != null) { aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: // Gotta map it... aoqi@0: aoqi@0: BatchEnvironment env = stack.getEnv(); aoqi@0: int typeCode = theType.getTypeCode(); aoqi@0: switch (typeCode) { aoqi@0: case TC_BOOLEAN: aoqi@0: case TC_BYTE: aoqi@0: case TC_CHAR: aoqi@0: case TC_SHORT: aoqi@0: case TC_INT: aoqi@0: case TC_LONG: aoqi@0: case TC_FLOAT: aoqi@0: case TC_DOUBLE: aoqi@0: { aoqi@0: // Primitive... aoqi@0: aoqi@0: result = PrimitiveType.forPrimitive(theType,stack); aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: case TC_ARRAY: aoqi@0: { aoqi@0: // Array. aoqi@0: aoqi@0: result = ArrayType.forArray(theType,stack); aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: case TC_CLASS: aoqi@0: { aoqi@0: try { aoqi@0: // First, make sure we have the class definition... aoqi@0: aoqi@0: ClassDefinition theClass = classDef; aoqi@0: aoqi@0: if (theClass == null) { aoqi@0: theClass = env.getClassDeclaration(theType).getClassDefinition(env); aoqi@0: } aoqi@0: aoqi@0: // Is it an interface or a class? aoqi@0: aoqi@0: if (theClass.isInterface()) { aoqi@0: aoqi@0: // An interface. Is it a special case? aoqi@0: aoqi@0: result = SpecialInterfaceType.forSpecial(theClass,stack); aoqi@0: aoqi@0: if (result == null) { aoqi@0: aoqi@0: // No, does it implement java.rmi.Remote? aoqi@0: aoqi@0: if (env.defRemote.implementedBy(env,theClass.getClassDeclaration())) { aoqi@0: aoqi@0: // Yep, so just see if we can create an instance of RemoteType aoqi@0: // from it... aoqi@0: aoqi@0: boolean parentIsValue = stack.isParentAValue(); aoqi@0: result = RemoteType.forRemote(theClass,stack,parentIsValue); aoqi@0: aoqi@0: // If we did not succeed AND we are in a value context, then aoqi@0: // go ahead and make an NC type out of it... aoqi@0: aoqi@0: if (result == null && parentIsValue) { aoqi@0: result = NCInterfaceType.forNCInterface(theClass,stack); aoqi@0: } aoqi@0: } else { aoqi@0: aoqi@0: // Nope, is it an AbstractType? aoqi@0: aoqi@0: result = AbstractType.forAbstract(theClass,stack,true); aoqi@0: aoqi@0: if (result == null) { aoqi@0: aoqi@0: // No, so treat it as a non-conforming interface type... aoqi@0: aoqi@0: result = NCInterfaceType.forNCInterface(theClass,stack); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } else { aoqi@0: aoqi@0: // A class. Is it a special case? aoqi@0: aoqi@0: result = SpecialClassType.forSpecial(theClass,stack); aoqi@0: aoqi@0: if (result == null) { aoqi@0: aoqi@0: ClassDeclaration classDecl = theClass.getClassDeclaration(); aoqi@0: aoqi@0: // Nope, does it implement java.rmi.Remote? aoqi@0: aoqi@0: if (env.defRemote.implementedBy(env,classDecl)) { aoqi@0: aoqi@0: // Yep, so just see if we can create an instance of aoqi@0: // ImplementationType from it... aoqi@0: aoqi@0: boolean parentIsValue = stack.isParentAValue(); aoqi@0: result = ImplementationType.forImplementation(theClass,stack,parentIsValue); aoqi@0: aoqi@0: // If we did not succeed AND inValue is true, then aoqi@0: // go ahead and make an NC type out of it... aoqi@0: aoqi@0: if (result == null && parentIsValue) { aoqi@0: result = NCClassType.forNCClass(theClass,stack); aoqi@0: } aoqi@0: } else { aoqi@0: aoqi@0: // No, does it implement Serializable? aoqi@0: aoqi@0: if (env.defSerializable.implementedBy(env,classDecl)) { aoqi@0: aoqi@0: // Yep, so just see if we can create an instance of ValueType aoqi@0: // from it... aoqi@0: aoqi@0: result = ValueType.forValue(theClass,stack,true); aoqi@0: } aoqi@0: aoqi@0: if (result == null) { aoqi@0: aoqi@0: // Treat it as a non-conforming class type... aoqi@0: aoqi@0: result = NCClassType.forNCClass(theClass,stack); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } catch (ClassNotFound e) { aoqi@0: classNotFound(stack,e); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: default: throw new CompilerError("Unknown typecode (" + typeCode + ") for " + theType.getTypeSignature()); aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Check if exception is RemoteException or one of its parents. aoqi@0: */ aoqi@0: public static boolean isRemoteException (ClassType ex, aoqi@0: BatchEnvironment env) { aoqi@0: sun.tools.java.Type exceptionType = ex.getClassDeclaration().getType(); aoqi@0: aoqi@0: if (exceptionType.equals(env.typeRemoteException) || aoqi@0: exceptionType.equals(env.typeIOException) || aoqi@0: exceptionType.equals(env.typeException) || aoqi@0: exceptionType.equals(env.typeThrowable)) { aoqi@0: aoqi@0: return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Check if method is conforming. aoqi@0: */ aoqi@0: protected boolean isConformingRemoteMethod (Method method, boolean quiet) aoqi@0: throws ClassNotFound { aoqi@0: aoqi@0: // Do we have one exception that is RemoteException or aoqi@0: // a superclass of RemoteException? aoqi@0: aoqi@0: boolean haveRemote = false; aoqi@0: ClassType[] exceptions = method.getExceptions(); aoqi@0: aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: aoqi@0: // Is it a conforming exception? aoqi@0: aoqi@0: if (isRemoteException(exceptions[i],env)) { aoqi@0: aoqi@0: // Got it. aoqi@0: aoqi@0: haveRemote = true; aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Do we have our exception? aoqi@0: aoqi@0: if (!haveRemote) { aoqi@0: aoqi@0: // No, so report failure... aoqi@0: aoqi@0: failedConstraint(5,quiet,stack,method.getEnclosing(), method.toString()); aoqi@0: } aoqi@0: aoqi@0: // Are any of the arguments exceptions which implement IDLEntity? aoqi@0: // If so, report failure... aoqi@0: aoqi@0: boolean noIDLEntity = !isIDLEntityException(method.getReturnType(),method,quiet); aoqi@0: if (noIDLEntity) { aoqi@0: Type[] args = method.getArguments(); aoqi@0: for (int i = 0; i < args.length; i++) { aoqi@0: if (isIDLEntityException(args[i],method,quiet)) { aoqi@0: noIDLEntity = false; aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return (haveRemote && noIDLEntity); aoqi@0: } aoqi@0: aoqi@0: protected boolean isIDLEntityException(Type type, CompoundType.Method method,boolean quiet) aoqi@0: throws ClassNotFound { aoqi@0: if (type.isArray()) { aoqi@0: type = type.getElementType(); aoqi@0: } aoqi@0: if (type.isCompound()){ aoqi@0: if (((CompoundType)type).isIDLEntityException()) { aoqi@0: failedConstraint(18,quiet,stack,method.getEnclosing(), method.toString()); aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Convert all invalid types to valid ones. aoqi@0: */ aoqi@0: protected void swapInvalidTypes () { aoqi@0: aoqi@0: // Walk all interfaces and check them... aoqi@0: aoqi@0: for (int i = 0; i < interfaces.length; i++) { aoqi@0: if (interfaces[i].getStatus() != STATUS_VALID) { aoqi@0: interfaces[i] = (InterfaceType)getValidType(interfaces[i]); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Update methods... aoqi@0: aoqi@0: for (int i = 0; i < methods.length; i++) { aoqi@0: methods[i].swapInvalidTypes(); aoqi@0: } aoqi@0: aoqi@0: // Update members... aoqi@0: aoqi@0: for (int i = 0; i < members.length; i++) { aoqi@0: members[i].swapInvalidTypes(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Add matching types to list. Return true if this type has not aoqi@0: * been previously checked, false otherwise. aoqi@0: */ aoqi@0: protected boolean addTypes (int typeCodeFilter, aoqi@0: HashSet checked, aoqi@0: Vector matching) { aoqi@0: aoqi@0: // Check self. aoqi@0: aoqi@0: boolean result = super.addTypes(typeCodeFilter,checked,matching); aoqi@0: aoqi@0: // Have we been checked before? aoqi@0: aoqi@0: if (result) { aoqi@0: aoqi@0: // Nope, so walk parent(s) and check them... aoqi@0: aoqi@0: ClassType parent = getSuperclass(); aoqi@0: aoqi@0: if (parent != null) { aoqi@0: parent.addTypes(typeCodeFilter,checked,matching); aoqi@0: } aoqi@0: aoqi@0: // Walk all interfaces and check them... aoqi@0: aoqi@0: //if (interfaces == null) System.out.println("NULL for " +getQualifiedName() + " interfaces"); aoqi@0: for (int i = 0; i < interfaces.length; i++) { aoqi@0: aoqi@0: // Now recurse and add it and any referenced types... aoqi@0: aoqi@0: //if (interfaces[i] == null) System.out.println("NULL for " +getQualifiedName() + " interfaces[" + i + "]"); aoqi@0: interfaces[i].addTypes(typeCodeFilter,checked,matching); aoqi@0: } aoqi@0: aoqi@0: // Walk all methods and check arguments... aoqi@0: aoqi@0: //if (methods == null) System.out.println("NULL for " +getQualifiedName() + " methods"); aoqi@0: for (int i = 0; i < methods.length; i++) { aoqi@0: aoqi@0: // Add return type... aoqi@0: //if (methods[i] == null) System.out.println("NULL for " +getQualifiedName() + " methods[" + i + "]"); aoqi@0: //if (methods[i].getReturnType() == null) System.out.println("NULL for " +getQualifiedName() + methods[i]); aoqi@0: methods[i].getReturnType().addTypes(typeCodeFilter,checked,matching); aoqi@0: aoqi@0: // Add args... aoqi@0: aoqi@0: Type[] args = methods[i].getArguments(); aoqi@0: //if (args == null) System.out.println("NULL for " + getQualifiedName() + " args"); aoqi@0: aoqi@0: for (int j = 0; j < args.length; j++) { aoqi@0: aoqi@0: Type arg = args[j]; aoqi@0: //if (arg == null) System.out.println("NULL for " + getQualifiedName() + " arg[" +j+"]"); aoqi@0: aoqi@0: // Add argument... aoqi@0: aoqi@0: arg.addTypes(typeCodeFilter,checked,matching); aoqi@0: } aoqi@0: aoqi@0: // Add exceptions... aoqi@0: aoqi@0: ClassType[] exceptions = methods[i].getExceptions(); aoqi@0: //if (exceptions == null) System.out.println("NULL for " + getQualifiedName() + " exceptions"); aoqi@0: aoqi@0: for (int j = 0; j < exceptions.length; j++) { aoqi@0: aoqi@0: ClassType ex = exceptions[j]; aoqi@0: aoqi@0: // Add argument... aoqi@0: aoqi@0: ex.addTypes(typeCodeFilter,checked,matching); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Walk all members and add em... aoqi@0: aoqi@0: //if (members == null) System.out.println("NULL for " +getQualifiedName() + " members"); aoqi@0: for (int i = 0; i < members.length; i++) { aoqi@0: //if (members[i] == null) System.out.println("NULL for " +getQualifiedName() + " members[" + i + "]"); aoqi@0: Type cType = members[i].getType(); aoqi@0: //if (cType == null) System.out.println("NULL for " + getQualifiedName() + " cType"); aoqi@0: aoqi@0: // Add it... aoqi@0: aoqi@0: cType.addTypes(typeCodeFilter,checked,matching); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Return true if theType is a conforming constant type. aoqi@0: */ aoqi@0: private boolean isConformingConstantType (MemberDefinition member) { aoqi@0: return isConformingConstantType(member.getType(),member); aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Return true if theType is a conforming constant type. aoqi@0: */ aoqi@0: private boolean isConformingConstantType (sun.tools.java.Type theType,MemberDefinition member) { aoqi@0: aoqi@0: // Constraint 3: Constants must be either primitives or String. aoqi@0: aoqi@0: boolean result = true; aoqi@0: int typeCode = theType.getTypeCode(); aoqi@0: switch (typeCode) { aoqi@0: case TC_BOOLEAN: aoqi@0: case TC_BYTE: aoqi@0: case TC_CHAR: aoqi@0: case TC_SHORT: aoqi@0: case TC_INT: aoqi@0: case TC_LONG: aoqi@0: case TC_FLOAT: aoqi@0: case TC_DOUBLE: // Primitive, so OK... aoqi@0: { aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: case TC_CLASS: // Must be java.lang.String aoqi@0: { aoqi@0: if (theType.getClassName() != idJavaLangString) { aoqi@0: failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); aoqi@0: result = false; aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: case TC_ARRAY: // Array constants are not allowed. aoqi@0: { aoqi@0: failedConstraint(3,false,stack,member.getClassDefinition(),member.getName()); aoqi@0: result = false; aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: default: aoqi@0: throw new Error("unexpected type code: " + typeCode); aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /* aoqi@0: * Update any method from 'currentMethods' which is defined in a aoqi@0: * parent class so that it's 'declaredBy' field specifies the aoqi@0: * parent. aoqi@0: * @param current The class or interface to gather methods from. aoqi@0: * @param currentMethods The list into which to put the methods. aoqi@0: * for contraint 6. aoqi@0: * @param quiet true if silent errors. aoqi@0: * @param stack the context stack. aoqi@0: * @return currentMethods or null if failed a constraint check. aoqi@0: */ aoqi@0: protected Vector updateParentClassMethods(ClassDefinition current, aoqi@0: Vector currentMethods, aoqi@0: boolean quiet, aoqi@0: ContextStack stack) aoqi@0: throws ClassNotFound { aoqi@0: aoqi@0: ClassDeclaration parentDecl = current.getSuperClass(env); aoqi@0: aoqi@0: while (parentDecl != null) { aoqi@0: aoqi@0: ClassDefinition parentDef = parentDecl.getClassDefinition(env); aoqi@0: Identifier currentID = parentDecl.getName(); aoqi@0: aoqi@0: if ( currentID == idJavaLangObject ) break; aoqi@0: aoqi@0: // Walk all members of this class and update any that aoqi@0: // already exist in currentMethods... aoqi@0: aoqi@0: for (MemberDefinition member = parentDef.getFirstMember(); aoqi@0: member != null; aoqi@0: member = member.getNextMember()) { aoqi@0: aoqi@0: if (member.isMethod() && aoqi@0: !member.isInitializer() && aoqi@0: !member.isConstructor() && aoqi@0: !member.isPrivate()) { aoqi@0: aoqi@0: // It's a method. Is it valid? aoqi@0: aoqi@0: Method method; aoqi@0: try { aoqi@0: method = new Method((CompoundType)this,member,quiet,stack); aoqi@0: } catch (Exception e) { aoqi@0: // Don't report anything here, it's already been reported... aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: // Have we already seen it? aoqi@0: aoqi@0: int index = currentMethods.indexOf(method); aoqi@0: if (index >= 0) { aoqi@0: aoqi@0: // Yes, so update it... aoqi@0: aoqi@0: Method currentMethod = (Method)currentMethods.elementAt(index); aoqi@0: currentMethod.setDeclaredBy(currentID); aoqi@0: } aoqi@0: else currentMethods.addElement(method); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Update parent and keep walking up the chain... aoqi@0: aoqi@0: parentDecl = parentDef.getSuperClass(env); aoqi@0: } aoqi@0: aoqi@0: return currentMethods; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * Add all of the public and protected methods defined in aoqi@0: * current (other than initializers) to allMethods. If a sub-interface aoqi@0: * re-declares an inherited method, it will not be added. aoqi@0: * @param current The class or interface to gather methods from. aoqi@0: * @param directMethods The list into which to put the methods. aoqi@0: * @param noMultiInheritedMethods A flag to enable/disable checking aoqi@0: * for contraint 6. aoqi@0: * @param quiet true if silent errors. aoqi@0: * @param stack the context stack. aoqi@0: * @return directMethods or null if failed a constraint check. aoqi@0: */ aoqi@0: protected Vector addAllMethods (ClassDefinition current, Vector directMethods, aoqi@0: boolean noMultiInheritedMethods, aoqi@0: boolean quiet, aoqi@0: ContextStack stack) aoqi@0: throws ClassNotFound { aoqi@0: aoqi@0: // Constraint 6: Multiple inherited interfaces may not aoqi@0: // declare the same method. aoqi@0: aoqi@0: ClassDeclaration[] interfaces = current.getInterfaces(); aoqi@0: aoqi@0: // We want to add members starting at the _least_ derived aoqi@0: // interfaces. To do so, recurse until we have no more aoqi@0: // interfaces... aoqi@0: aoqi@0: for (int i = 0; i < interfaces.length; i++) { aoqi@0: aoqi@0: Vector result = addAllMethods(interfaces[i].getClassDefinition(env), aoqi@0: directMethods, aoqi@0: noMultiInheritedMethods,quiet,stack); aoqi@0: if (result == null) { aoqi@0: return null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Walk all members of this interface, adding any unique methods aoqi@0: // other than initializers and private methods... aoqi@0: aoqi@0: for (MemberDefinition member = current.getFirstMember(); aoqi@0: member != null; aoqi@0: member = member.getNextMember()) aoqi@0: { aoqi@0: if (member.isMethod() && aoqi@0: !member.isInitializer() && aoqi@0: !member.isPrivate()) { aoqi@0: aoqi@0: // It's a method. Is it valid? aoqi@0: aoqi@0: Method method; aoqi@0: try { aoqi@0: method = new Method((CompoundType)this,member,quiet,stack); aoqi@0: } catch (Exception e) { aoqi@0: // Don't report anything here, it's already been reported... aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: // Have we already seen it? aoqi@0: aoqi@0: if (!directMethods.contains(method)) { aoqi@0: aoqi@0: // Nope, so add it... aoqi@0: aoqi@0: directMethods.addElement(method); aoqi@0: aoqi@0: } else { aoqi@0: aoqi@0: // Yes. This is an error unless we are looking at the aoqi@0: // target interface (or this is a ValueType). Are we? aoqi@0: aoqi@0: if (noMultiInheritedMethods && current != classDef && aoqi@0: !stack.isParentAValue() && !stack.getContext().isValue()) { aoqi@0: aoqi@0: // Nope. Say so and signal error by returning null.. aoqi@0: aoqi@0: Method existingMethod = (Method) directMethods.elementAt(directMethods.indexOf(method)); aoqi@0: ClassDefinition existingMemberClassDef = existingMethod.getMemberDefinition().getClassDefinition(); aoqi@0: aoqi@0: // There are more legal cases to consider here. aoqi@0: // If the two methods belong to interfaces that inherit from each other aoqi@0: // then it is just a redefinition which is legal. aoqi@0: if ( current != existingMemberClassDef && aoqi@0: ! inheritsFrom(current, existingMemberClassDef) && aoqi@0: ! inheritsFrom(existingMemberClassDef, current)) aoqi@0: { aoqi@0: //Identifier int1 = existingMethod.getEnclosing().getIdentifier(); aoqi@0: //Identifier int2 = current.getName(); aoqi@0: //String message = int1.toString() + " and " + int2.toString(); aoqi@0: String message = existingMemberClassDef.getName() + " and " + current.getName(); aoqi@0: failedConstraint(6,quiet,stack,classDef,message,method); aoqi@0: return null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Bug fix 5014329 aoqi@0: aoqi@0: // find a matching method. aoqi@0: int index = directMethods.indexOf(method); aoqi@0: Method other = (Method) directMethods.get(index); aoqi@0: aoqi@0: // merge the two methods, such that the new method aoqi@0: // will contain only those exception that can be thrown aoqi@0: // by both these methods, not just one of them. aoqi@0: Method newMethod = method.mergeWith(other); aoqi@0: aoqi@0: // replace the old method with the new. aoqi@0: directMethods.set(index, newMethod); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return directMethods; aoqi@0: } aoqi@0: aoqi@0: // This should really be a method on ClassDefinition, but it takes too long to change the shared source. aoqi@0: // Works for both, classes and interfaces. aoqi@0: protected boolean inheritsFrom(ClassDefinition def, ClassDefinition otherDef) { aoqi@0: if (def == otherDef) aoqi@0: return true; aoqi@0: aoqi@0: ClassDefinition superDef; aoqi@0: if (def.getSuperClass() != null) { aoqi@0: superDef = def.getSuperClass().getClassDefinition(); aoqi@0: if (inheritsFrom(superDef, otherDef)) aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: ClassDeclaration[] interfaces = def.getInterfaces(); aoqi@0: for (int i=0; i 0) { aoqi@0: int offset = 0; aoqi@0: ValueType[] temp = new ValueType[exceptions.length - dupCount]; aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: if (exceptions[i] != null) { aoqi@0: temp[offset++] = exceptions[i]; aoqi@0: } aoqi@0: } aoqi@0: exceptions = temp; aoqi@0: } aoqi@0: aoqi@0: return exceptions; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: protected static String getVisibilityString (MemberDefinition member) { aoqi@0: String vis = ""; aoqi@0: String prefix = ""; aoqi@0: aoqi@0: if (member.isPublic()) { aoqi@0: vis += "public"; aoqi@0: prefix = " "; aoqi@0: } else if (member.isProtected()) { aoqi@0: vis += "protected"; aoqi@0: prefix = " "; aoqi@0: } else if (member.isPrivate()) { aoqi@0: vis += "private"; aoqi@0: prefix = " "; aoqi@0: } aoqi@0: aoqi@0: if (member.isStatic()) { aoqi@0: vis += prefix; aoqi@0: vis += "static"; aoqi@0: prefix = " "; aoqi@0: } aoqi@0: aoqi@0: if (member.isFinal()) { aoqi@0: vis += prefix; aoqi@0: vis += "final"; aoqi@0: prefix = " "; aoqi@0: } aoqi@0: aoqi@0: return vis; aoqi@0: } aoqi@0: aoqi@0: protected boolean assertNotImpl(Type type, aoqi@0: boolean quiet, aoqi@0: ContextStack stack, aoqi@0: CompoundType enclosing, aoqi@0: boolean dataMember) { aoqi@0: aoqi@0: if (type.isType(TYPE_IMPLEMENTATION)) { aoqi@0: int constraint = dataMember ? 28 : 21; aoqi@0: failedConstraint(constraint,quiet,stack,type,enclosing.getName()); aoqi@0: return false; aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Inner Class "Method" aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * A CompoundType.Method object encapsulates IIOP-specific information aoqi@0: * about a particular method in the interface represented by the outer aoqi@0: * instance. aoqi@0: */ aoqi@0: public class Method implements ContextElement, Cloneable { aoqi@0: aoqi@0: /** aoqi@0: * Is this method inherited? aoqi@0: */ aoqi@0: public boolean isInherited () { aoqi@0: return declaredBy != enclosing.getIdentifier(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Is this method an attribute? aoqi@0: * Return true if getAttributeKind != ATTRIBUTE_NONE. aoqi@0: */ aoqi@0: public boolean isAttribute () { aoqi@0: return attributeKind != ATTRIBUTE_NONE; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Is this method a read-write attribute? aoqi@0: */ aoqi@0: public boolean isReadWriteAttribute () { aoqi@0: return attributeKind == ATTRIBUTE_IS_RW || aoqi@0: attributeKind == ATTRIBUTE_GET_RW; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the attribute kind. aoqi@0: */ aoqi@0: public int getAttributeKind() { aoqi@0: return attributeKind; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the attribute name. Will be null if aoqi@0: * attribute kind == ATTRIBUTE_NONE. aoqi@0: */ aoqi@0: public String getAttributeName() { aoqi@0: return attributeName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * For kinds ATTRIBUTE_GET_RW or ATTRIBUTE_IS_RW, return aoqi@0: * the index of the matching ATTRIBUTE_SET method, and aoqi@0: * vice-versa. For all other cases, return -1. aoqi@0: */ aoqi@0: public int getAttributePairIndex() { aoqi@0: return attributePairIndex; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return context element name. aoqi@0: */ aoqi@0: public String getElementName() { aoqi@0: return memberDef.toString(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Equality check based on method signature. aoqi@0: */ aoqi@0: public boolean equals(Object obj) { aoqi@0: Method other = (Method) obj; aoqi@0: aoqi@0: if (getName().equals(other.getName()) && aoqi@0: arguments.length == other.arguments.length) { aoqi@0: aoqi@0: for (int i = 0; i < arguments.length; i++) { aoqi@0: if (! arguments[i].equals(other.arguments[i])) { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: public int hashCode() { aoqi@0: return getName().hashCode() ^ Arrays.hashCode(arguments); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return a new Method object that is a legal combination of aoqi@0: * this method object and another one. aoqi@0: * aoqi@0: * This requires determining the exceptions declared by the aoqi@0: * combined method, which must be only those exceptions aoqi@0: * that may thrown by both of the old methods. aoqi@0: */ aoqi@0: public Method mergeWith(Method other) { aoqi@0: if (!equals(other)) { aoqi@0: env.error(0, "attempt to merge method failed:", getName(), aoqi@0: enclosing.getClassDefinition().getName()); aoqi@0: } aoqi@0: aoqi@0: Vector legalExceptions = new Vector(); aoqi@0: try { aoqi@0: collectCompatibleExceptions( aoqi@0: other.exceptions, exceptions, legalExceptions); aoqi@0: collectCompatibleExceptions( aoqi@0: exceptions, other.exceptions, legalExceptions); aoqi@0: } catch (ClassNotFound e) { aoqi@0: env.error(0, "class.not.found", e.name, aoqi@0: enclosing.getClassDefinition().getName()); aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: Method merged = (Method) clone(); aoqi@0: merged.exceptions = new ValueType[legalExceptions.size()]; aoqi@0: legalExceptions.copyInto(merged.exceptions); aoqi@0: merged.implExceptions = merged.exceptions; aoqi@0: aoqi@0: return merged; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Add to the supplied list all exceptions in the "from" array aoqi@0: * that are subclasses of an exception in the "with" array. aoqi@0: */ aoqi@0: private void collectCompatibleExceptions( aoqi@0: ValueType[] from, ValueType[] with, Vector list) aoqi@0: throws ClassNotFound { aoqi@0: aoqi@0: for (int i = 0; i < from.length; i++) { aoqi@0: ClassDefinition exceptionDef = from[i].getClassDefinition(); aoqi@0: if (!list.contains(from[i])) { aoqi@0: for (int j = 0; j < with.length; j++) { aoqi@0: if (exceptionDef.subClassOf( aoqi@0: enclosing.getEnv(), aoqi@0: with[j].getClassDeclaration())) { aoqi@0: list.addElement(from[i]); aoqi@0: break; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the compound type which contains this method. aoqi@0: */ aoqi@0: public CompoundType getEnclosing() { aoqi@0: return enclosing; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the identifier for the class or interface which aoqi@0: * declares this method. aoqi@0: */ aoqi@0: public Identifier getDeclaredBy() { aoqi@0: return declaredBy; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the visibility (e.g. "public final") of this member. aoqi@0: */ aoqi@0: public String getVisibility() { aoqi@0: return vis; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Methods to check various attributes. aoqi@0: */ aoqi@0: public boolean isPublic() { aoqi@0: return memberDef.isPublic(); aoqi@0: } aoqi@0: aoqi@0: public boolean isProtected() { aoqi@0: return memberDef.isPrivate(); aoqi@0: } aoqi@0: aoqi@0: public boolean isPrivate() { aoqi@0: return memberDef.isPrivate(); aoqi@0: } aoqi@0: aoqi@0: public boolean isStatic() { aoqi@0: return memberDef.isStatic(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the name of this method. aoqi@0: */ aoqi@0: public String getName() { aoqi@0: return name; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * IDL_Naming aoqi@0: * Return the IDL name of this method. aoqi@0: */ aoqi@0: public String getIDLName() { aoqi@0: return idlName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the type of this method. aoqi@0: */ aoqi@0: public sun.tools.java.Type getType() { aoqi@0: return memberDef.getType(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this is a constructor. aoqi@0: */ aoqi@0: public boolean isConstructor () { aoqi@0: return memberDef.isConstructor(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this is NOT a constructor && is not aoqi@0: * an attribute. aoqi@0: */ aoqi@0: public boolean isNormalMethod () { aoqi@0: return (!memberDef.isConstructor()) && attributeKind == ATTRIBUTE_NONE; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Get the return type of this method. May be null. aoqi@0: */ aoqi@0: public Type getReturnType() { aoqi@0: return returnType; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the argument types of this method. aoqi@0: */ aoqi@0: public Type[] getArguments() { aoqi@0: return (Type[]) arguments.clone(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the names of the argument types of this method. aoqi@0: */ aoqi@0: public String[] getArgumentNames() { aoqi@0: return argumentNames; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the MemberDefinition from which this method was created. aoqi@0: */ aoqi@0: public MemberDefinition getMemberDefinition() { aoqi@0: return memberDef; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array of the exception classes declared to be aoqi@0: * thrown by this remote method. aoqi@0: * aoqi@0: * For methods with the same name and type signature inherited aoqi@0: * from multiple remote interfaces, the array will contain aoqi@0: * the set of exceptions declared in all of the interfaces' aoqi@0: * methods that can be legally thrown in each of them. aoqi@0: */ aoqi@0: public ValueType[] getExceptions() { aoqi@0: return (ValueType[]) exceptions.clone(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Same as getExceptions(), except when method is in an aoqi@0: * ImplementationType and the exceptions list is narrower. aoqi@0: */ aoqi@0: public ValueType[] getImplExceptions() { aoqi@0: return (ValueType[]) implExceptions.clone(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array containing only those exceptions which aoqi@0: * need to be caught. Removes java.rmi.RemoteException, aoqi@0: * java.lang.RuntimeException, java.lang.Error, and their aoqi@0: * subclasses, then removes any exceptions which are more aoqi@0: * derived than another in the list. Returns null if no aoqi@0: * exceptions need to be caught. aoqi@0: */ aoqi@0: public ValueType[] getUniqueCatchList(ValueType[] list) { aoqi@0: ValueType[] result = list; aoqi@0: int newSize = list.length; aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: // First, remove RemoteException, RuntimeException, Error, and their subclasses... aoqi@0: for (int i = 0; i < list.length; i++) { aoqi@0: ClassDeclaration decl = list[i].getClassDeclaration(); aoqi@0: if (env.defRemoteException.superClassOf(env, decl) || aoqi@0: env.defRuntimeException.superClassOf(env, decl) || aoqi@0: env.defError.superClassOf(env, decl)) { aoqi@0: list[i] = null; aoqi@0: newSize--; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Now remove derived types... aoqi@0: for (int i = 0; i < list.length; i++) { aoqi@0: if (list[i] != null) { aoqi@0: ClassDefinition current = list[i].getClassDefinition(); aoqi@0: for (int j = 0; j < list.length; j++) { aoqi@0: if (j != i && list[i] != null && list[j] != null && aoqi@0: current.superClassOf(env, list[j].getClassDeclaration())) { aoqi@0: list[j] = null; aoqi@0: newSize--; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } catch (ClassNotFound e) { aoqi@0: classNotFound(stack,e); // Report error but do not stop. aoqi@0: } aoqi@0: aoqi@0: // Create new list if we removed anything... aoqi@0: aoqi@0: if (newSize < list.length) { aoqi@0: ValueType[] temp = new ValueType[newSize]; aoqi@0: int offset = 0; aoqi@0: for (int i = 0; i < list.length; i++) { aoqi@0: if (list[i] != null) { aoqi@0: temp[offset++] = list[i]; aoqi@0: } aoqi@0: } aoqi@0: list = temp; aoqi@0: } aoqi@0: aoqi@0: if (list.length == 0) { aoqi@0: return null; aoqi@0: } else { aoqi@0: return list; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return an array containing only those exceptions which need to be aoqi@0: * handled explicitly by the stub. Removes java.lang.RuntimeException, aoqi@0: * java.lang.Error, and their subclasses, since these are all passed aoqi@0: * back as CORBA system exceptions. Also removes subclasses of aoqi@0: * java.rmi.RemoteException but not java.rmi.RemoteException itself, aoqi@0: * since this may need to be thrown by the stub. aoqi@0: */ aoqi@0: public ValueType[] getFilteredStubExceptions(ValueType[] list) { aoqi@0: ValueType[] result = list; aoqi@0: int newSize = list.length; aoqi@0: aoqi@0: try { aoqi@0: aoqi@0: for (int i = 0; i < list.length; i++) { aoqi@0: ClassDeclaration decl = list[i].getClassDeclaration(); aoqi@0: if ((env.defRemoteException.superClassOf(env, decl) && aoqi@0: !env.defRemoteException.getClassDeclaration().equals(decl)) || aoqi@0: env.defRuntimeException.superClassOf(env, decl) || aoqi@0: env.defError.superClassOf(env, decl)) { aoqi@0: list[i] = null; aoqi@0: newSize--; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } catch (ClassNotFound e) { aoqi@0: classNotFound(stack,e); // Report error but do not stop. aoqi@0: } aoqi@0: aoqi@0: // Create new list if we removed anything... aoqi@0: aoqi@0: if (newSize < list.length) { aoqi@0: ValueType[] temp = new ValueType[newSize]; aoqi@0: int offset = 0; aoqi@0: for (int i = 0; i < list.length; i++) { aoqi@0: if (list[i] != null) { aoqi@0: temp[offset++] = list[i]; aoqi@0: } aoqi@0: } aoqi@0: list = temp; aoqi@0: } aoqi@0: aoqi@0: return list; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the string representation of this method. aoqi@0: */ aoqi@0: public String toString() { aoqi@0: aoqi@0: if (stringRep == null) { aoqi@0: aoqi@0: StringBuffer result = new StringBuffer(returnType.toString()); aoqi@0: aoqi@0: // Add name... aoqi@0: aoqi@0: result.append(" "); aoqi@0: result.append(getName()); aoqi@0: result.append(" ("); aoqi@0: aoqi@0: // Add arguments... aoqi@0: aoqi@0: for (int i = 0; i < arguments.length; i++) { aoqi@0: if (i > 0) { aoqi@0: result.append(", "); aoqi@0: } aoqi@0: result.append(arguments[i]); aoqi@0: result.append(" "); aoqi@0: result.append(argumentNames[i]); aoqi@0: } aoqi@0: aoqi@0: result.append(")"); aoqi@0: aoqi@0: // Add exceptions... aoqi@0: aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: if (i == 0) { aoqi@0: result.append(" throws "); aoqi@0: } else { aoqi@0: result.append(", "); aoqi@0: } aoqi@0: result.append(exceptions[i]); aoqi@0: } aoqi@0: aoqi@0: result.append(";"); aoqi@0: aoqi@0: stringRep = result.toString(); aoqi@0: } aoqi@0: aoqi@0: return stringRep; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Set attribute kind. May only be called during initialization. aoqi@0: */ aoqi@0: public void setAttributeKind(int kind) { aoqi@0: attributeKind = kind; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set pair index. May only be called during initialization. aoqi@0: */ aoqi@0: public void setAttributePairIndex(int index) { aoqi@0: attributePairIndex = index; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set attribute name. May only be called during initialization. aoqi@0: */ aoqi@0: public void setAttributeName(String name) { aoqi@0: attributeName = name; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the idl name. May only be called during initialization. aoqi@0: */ aoqi@0: public void setIDLName (String idlName) { aoqi@0: this.idlName=idlName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the implExceptions array. May only be called during initialization. aoqi@0: */ aoqi@0: public void setImplExceptions (ValueType[] exceptions) { aoqi@0: implExceptions = exceptions; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the declaredBy Identifier. May only be called during initialization. aoqi@0: */ aoqi@0: public void setDeclaredBy (Identifier by) { aoqi@0: declaredBy = by; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Convert all invalid types to valid ones. aoqi@0: */ aoqi@0: protected void swapInvalidTypes () { aoqi@0: aoqi@0: // Check return type... aoqi@0: aoqi@0: if (returnType.getStatus() != STATUS_VALID) { aoqi@0: returnType = getValidType(returnType); aoqi@0: } aoqi@0: aoqi@0: // Check args... aoqi@0: aoqi@0: for (int i = 0; i < arguments.length; i++) { aoqi@0: if (arguments[i].getStatus() != STATUS_VALID) { aoqi@0: arguments[i] = getValidType(arguments[i]); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Check exceptions... aoqi@0: aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: if (exceptions[i].getStatus() != STATUS_VALID) { aoqi@0: exceptions[i] = (ValueType)getValidType(exceptions[i]); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Check implExceptions... aoqi@0: aoqi@0: for (int i = 0; i < implExceptions.length; i++) { aoqi@0: if (implExceptions[i].getStatus() != STATUS_VALID) { aoqi@0: implExceptions[i] = (ValueType)getValidType(implExceptions[i]); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Release all resources. aoqi@0: */ aoqi@0: public void destroy () { aoqi@0: if (memberDef != null) { aoqi@0: memberDef = null; aoqi@0: enclosing = null; aoqi@0: if (exceptions != null) { aoqi@0: for (int i = 0; i < exceptions.length; i++) { aoqi@0: if (exceptions[i] != null) exceptions[i].destroy(); aoqi@0: exceptions[i] = null; aoqi@0: } aoqi@0: exceptions = null; aoqi@0: } aoqi@0: aoqi@0: if (implExceptions != null) { aoqi@0: for (int i = 0; i < implExceptions.length; i++) { aoqi@0: if (implExceptions[i] != null) implExceptions[i].destroy(); aoqi@0: implExceptions[i] = null; aoqi@0: } aoqi@0: implExceptions = null; aoqi@0: } aoqi@0: aoqi@0: if (returnType != null) returnType.destroy(); aoqi@0: returnType = null; aoqi@0: aoqi@0: if (arguments != null) { aoqi@0: for (int i = 0; i < arguments.length; i++) { aoqi@0: if (arguments[i] != null) arguments[i].destroy(); aoqi@0: arguments[i] = null; aoqi@0: } aoqi@0: arguments = null; aoqi@0: } aoqi@0: aoqi@0: if (argumentNames != null) { aoqi@0: for (int i = 0; i < argumentNames.length; i++) { aoqi@0: argumentNames[i] = null; aoqi@0: } aoqi@0: argumentNames = null; aoqi@0: } aoqi@0: aoqi@0: vis = null; aoqi@0: name = null; aoqi@0: idlName = null; aoqi@0: stringRep = null; aoqi@0: attributeName = null; aoqi@0: declaredBy = null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private MemberDefinition memberDef; aoqi@0: private CompoundType enclosing; aoqi@0: private ValueType[] exceptions; aoqi@0: private ValueType[] implExceptions; aoqi@0: private Type returnType; aoqi@0: private Type[] arguments; aoqi@0: private String[] argumentNames; aoqi@0: private String vis; aoqi@0: private String name; aoqi@0: private String idlName; aoqi@0: private String stringRep = null; aoqi@0: private int attributeKind = ATTRIBUTE_NONE; aoqi@0: private String attributeName = null; aoqi@0: private int attributePairIndex = -1; aoqi@0: private Identifier declaredBy = null; aoqi@0: aoqi@0: /** aoqi@0: * Make up an argument name for the given type. aoqi@0: */ aoqi@0: private String makeArgName (int argNum, Type type) { aoqi@0: return "arg" + argNum; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Create a new Method object corresponding to the given aoqi@0: * method definition. aoqi@0: */ aoqi@0: public Method (CompoundType enclosing, aoqi@0: MemberDefinition memberDef, aoqi@0: boolean quiet, aoqi@0: ContextStack stack) throws Exception { aoqi@0: aoqi@0: this.enclosing = enclosing; aoqi@0: this.memberDef = memberDef; aoqi@0: vis = getVisibilityString(memberDef); aoqi@0: idlName = null; // See setIDLName() aoqi@0: boolean valid = true; aoqi@0: declaredBy = memberDef.getClassDeclaration().getName(); aoqi@0: aoqi@0: // Set name... aoqi@0: aoqi@0: name = memberDef.getName().toString(); aoqi@0: aoqi@0: // Update the context... aoqi@0: aoqi@0: stack.setNewContextCode(ContextStack.METHOD); aoqi@0: stack.push(this); aoqi@0: aoqi@0: // Set return type... aoqi@0: aoqi@0: stack.setNewContextCode(ContextStack.METHOD_RETURN); aoqi@0: sun.tools.java.Type methodType = memberDef.getType(); aoqi@0: sun.tools.java.Type rtnType = methodType.getReturnType(); aoqi@0: aoqi@0: if (rtnType == sun.tools.java.Type.tVoid) { aoqi@0: returnType = PrimitiveType.forPrimitive(rtnType,stack); aoqi@0: } else { aoqi@0: returnType = makeType(rtnType,null,stack); aoqi@0: if (returnType == null || aoqi@0: !assertNotImpl(returnType,quiet,stack,enclosing,false)) { aoqi@0: valid = false; aoqi@0: failedConstraint(24,quiet,stack,enclosing.getName()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Set arguments and argument names... aoqi@0: aoqi@0: stack.setNewContextCode(ContextStack.METHOD_ARGUMENT); aoqi@0: sun.tools.java.Type[] args = memberDef.getType().getArgumentTypes(); aoqi@0: arguments = new Type[args.length]; aoqi@0: argumentNames = new String[args.length]; aoqi@0: Vector origArgNames = memberDef.getArguments(); aoqi@0: aoqi@0: for (int i = 0; i < args.length; i++) { aoqi@0: Type type = null; aoqi@0: try { aoqi@0: type = makeType(args[i],null,stack); aoqi@0: } catch (Exception e) { aoqi@0: } aoqi@0: aoqi@0: if (type != null) { aoqi@0: if (!assertNotImpl(type,quiet,stack,enclosing,false)) { aoqi@0: valid = false; aoqi@0: } else { aoqi@0: arguments[i] = type; aoqi@0: if (origArgNames != null) { aoqi@0: LocalMember local = (LocalMember)origArgNames.elementAt(i+1); aoqi@0: argumentNames[i] = local.getName().toString(); aoqi@0: } else { aoqi@0: argumentNames[i] = makeArgName(i,type); aoqi@0: } aoqi@0: } aoqi@0: } else { aoqi@0: valid = false; aoqi@0: failedConstraint(25,false,stack,enclosing.getQualifiedName(),name); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (!valid) { aoqi@0: stack.pop(false); aoqi@0: throw new Exception(); aoqi@0: } aoqi@0: aoqi@0: // Set exceptions... aoqi@0: aoqi@0: try { aoqi@0: exceptions = enclosing.getMethodExceptions(memberDef,quiet,stack); aoqi@0: implExceptions = exceptions; aoqi@0: stack.pop(true); aoqi@0: } catch (Exception e) { aoqi@0: stack.pop(false); aoqi@0: throw new Exception(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Cloning is supported by returning a shallow copy of this object. aoqi@0: */ aoqi@0: protected Object clone() { aoqi@0: try { aoqi@0: return super.clone(); aoqi@0: } catch (CloneNotSupportedException e) { aoqi@0: throw new Error("clone failed"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: //_____________________________________________________________________ aoqi@0: // Inner Class "Member" aoqi@0: //_____________________________________________________________________ aoqi@0: aoqi@0: /** aoqi@0: * An CompoundType.Member object wraps a Type and a value representing aoqi@0: * a data member, including constants. aoqi@0: */ aoqi@0: public class Member implements ContextElement, Cloneable { aoqi@0: aoqi@0: /** aoqi@0: * Return context element name. aoqi@0: */ aoqi@0: public String getElementName() { aoqi@0: return "\"" + getName() + "\""; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the type of this member. aoqi@0: */ aoqi@0: public Type getType() { aoqi@0: return type; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the name of this member. aoqi@0: */ aoqi@0: public String getName() { aoqi@0: return name; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * IDL_Naming aoqi@0: * Return the IDL name of this member. aoqi@0: */ aoqi@0: public String getIDLName() { aoqi@0: return idlName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the visibility (e.g. "public final") of this member. aoqi@0: */ aoqi@0: public String getVisibility() { aoqi@0: return vis; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Methods to check various attributes. aoqi@0: */ aoqi@0: public boolean isPublic() { aoqi@0: return member.isPublic(); aoqi@0: } aoqi@0: aoqi@0: public boolean isPrivate() { aoqi@0: return member.isPrivate(); aoqi@0: } aoqi@0: aoqi@0: public boolean isStatic() { aoqi@0: return member.isStatic(); aoqi@0: } aoqi@0: aoqi@0: public boolean isFinal() { aoqi@0: return member.isFinal(); aoqi@0: } aoqi@0: aoqi@0: public boolean isTransient() { aoqi@0: if (forceTransient) return true; aoqi@0: return member.isTransient(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the value of this member. May be null. aoqi@0: */ aoqi@0: public String getValue() { aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this member represents an inner class declaration, aoqi@0: * false otherwise. aoqi@0: */ aoqi@0: public boolean isInnerClassDeclaration() { aoqi@0: return innerClassDecl; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return true if this member represents a constant. aoqi@0: */ aoqi@0: public boolean isConstant () { aoqi@0: return constant; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Return the string representation of this constant. aoqi@0: */ aoqi@0: public String toString() { aoqi@0: aoqi@0: String result = type.toString(); aoqi@0: aoqi@0: if (value != null) { aoqi@0: result += (" = " + value); aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Convert all invalid types to valid ones. aoqi@0: */ aoqi@0: protected void swapInvalidTypes () { aoqi@0: if (type.getStatus() != STATUS_VALID) { aoqi@0: type = getValidType(type); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void setTransient() { aoqi@0: if (! isTransient()) { aoqi@0: forceTransient = true; aoqi@0: if (vis.length() > 0) { aoqi@0: vis = vis + " transient"; aoqi@0: } else { aoqi@0: vis = "transient"; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected MemberDefinition getMemberDefinition() { aoqi@0: return member; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Release all resources. aoqi@0: */ aoqi@0: public void destroy () { aoqi@0: if (type != null) { aoqi@0: type.destroy(); aoqi@0: type = null; aoqi@0: vis = null; aoqi@0: value = null; aoqi@0: name = null; aoqi@0: idlName = null; aoqi@0: member = null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private Type type; aoqi@0: private String vis; aoqi@0: private String value; aoqi@0: private String name; aoqi@0: private String idlName; aoqi@0: private boolean innerClassDecl; aoqi@0: private boolean constant; aoqi@0: private MemberDefinition member; aoqi@0: private boolean forceTransient; aoqi@0: aoqi@0: /** aoqi@0: * Create a new Member object. aoqi@0: */ aoqi@0: public Member(MemberDefinition member, aoqi@0: String value, aoqi@0: ContextStack stack, aoqi@0: CompoundType enclosing) { aoqi@0: this.member = member; aoqi@0: this.value = value; aoqi@0: forceTransient = false; aoqi@0: innerClassDecl = member.getInnerClass() != null; aoqi@0: aoqi@0: // If we are not an inner class, finish initializing now. aoqi@0: // Otherwise, wait until outer class is finished, then aoqi@0: // call init to avoid potential recursion problems... aoqi@0: aoqi@0: if (!innerClassDecl) { aoqi@0: init (stack,enclosing); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void init (ContextStack stack, CompoundType enclosing) { aoqi@0: aoqi@0: constant = false; aoqi@0: name = member.getName().toString(); aoqi@0: vis = getVisibilityString(member); aoqi@0: idlName = null; aoqi@0: aoqi@0: // Add self to stack... aoqi@0: aoqi@0: int contextCode = ContextStack.MEMBER; aoqi@0: stack.setNewContextCode(contextCode); aoqi@0: aoqi@0: // Check for special contextCodes... aoqi@0: aoqi@0: if (member.isVariable()) { aoqi@0: if (value != null && member.isConstant()) { aoqi@0: contextCode = ContextStack.MEMBER_CONSTANT; aoqi@0: this.constant = true; aoqi@0: } else if (member.isStatic()) { aoqi@0: contextCode = ContextStack.MEMBER_STATIC; aoqi@0: } else if (member.isTransient()) { aoqi@0: contextCode = ContextStack.MEMBER_TRANSIENT; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: stack.setNewContextCode(contextCode); aoqi@0: stack.push(this); aoqi@0: aoqi@0: type = makeType(member.getType(),null,stack); aoqi@0: aoqi@0: if (type == null || aoqi@0: (!innerClassDecl && aoqi@0: !member.isStatic() && aoqi@0: !member.isTransient() && aoqi@0: !assertNotImpl(type,false,stack,enclosing,true))) { aoqi@0: stack.pop(false); aoqi@0: throw new CompilerError(""); aoqi@0: } aoqi@0: aoqi@0: // Clean up primitive constant values... aoqi@0: aoqi@0: if (constant && type.isPrimitive()) { aoqi@0: if (type.isType(TYPE_LONG) || type.isType(TYPE_FLOAT) || type.isType(TYPE_DOUBLE)) { aoqi@0: int length = value.length(); aoqi@0: char lastChar = value.charAt(length-1); aoqi@0: if (!Character.isDigit(lastChar)) { aoqi@0: this.value = value.substring(0,length-1); aoqi@0: } aoqi@0: } else if (type.isType(TYPE_BOOLEAN)) { aoqi@0: value = value.toUpperCase(); aoqi@0: } aoqi@0: } aoqi@0: if (constant && type.isType(TYPE_STRING)) { aoqi@0: value = "L" + value; aoqi@0: } aoqi@0: stack.pop(true); aoqi@0: } aoqi@0: aoqi@0: public void setIDLName (String name) { aoqi@0: this.idlName = name; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Cloning is supported by returning a shallow copy of this object. aoqi@0: */ aoqi@0: protected Object clone() { aoqi@0: try { aoqi@0: return super.clone(); aoqi@0: } catch (CloneNotSupportedException e) { aoqi@0: throw new Error("clone failed"); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: }