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

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