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