Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/sun/tools/java/Imports.java

/*
 * @(#)Imports.java	1.9 95/09/14 Arthur van Hoff
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

package sun.tools.java;

import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;

/**
 * This class describes the classes and packages imported
 * from a source file. A Hashtable called bindings is maintained
 * to quickly map symbol names to classes. This table is flushed
 * everytime a new import is added.
 *
 * A class name is resolved as follows:
 *  - if it is a qualified name then return the corresponding class
 *  - if the name corresponds to an individually imported class then return that class
 *  - check if the class is defined in any of the imported packages,
 *    if it is then return it, make sure it is defined in only one package
 *  - assume that the class is defined in the current package
 *
 * REMIND: need to check for private classes
 */

public
class Imports implements Constants {
    /**
     * The imported classes
     */
    Hashtable classes = new Hashtable();

    /**
     * The imported package identifiers
     */
    Vector packages = new Vector();

    /**
     * Constructor, always import java.lang.
     */
    public Imports() {
	addPackage(idJavaLang);
    }
	    
    /**
     * Lookup a class, given the current set of imports,
     * AmbiguousClass exception is thrown if the name can be
     * resolved in more than one way. A ClassNotFound exception
     * is thrown if the class is not found in the imported classes
     * and packages.
     */
    public synchronized Identifier resolve(Environment env, Identifier nm) throws ClassNotFound {
	if (nm.isQualified()) {
	    // Don't bother it is already qualified
	    return nm;
	}

	// Check if it was imported before
	Identifier className = (Identifier)classes.get(nm);
	if (className != null) {
	    return className;
	}
	
	// look in one of the imported packages
	for (Enumeration e = packages.elements() ; e.hasMoreElements() ; ) {
	    Identifier id = Identifier.lookup((Identifier)e.nextElement(), nm);

	    if (env.classExists(id)) {
		if ((className == null) || className.equals(id)) {
		    className = id;
		} else {
		    throw new AmbiguousClass(id, className);
		}
	    }
	}

	// Make sure a class was found
	if (className == null) {
	    throw new ClassNotFound(nm);
	}

	// Remember the binding
	classes.put(nm, className);
	return className;
    }

    /**
     * Add a class import
     */
    public synchronized void addClass(Identifier id) throws AmbiguousClass {
	Identifier nm = id.getName();

	// make sure it isn't already imported explicitly
	Identifier className = (Identifier)classes.get(nm);
	if (className != null) {
	    throw new AmbiguousClass(id, className);
	}

	classes.put(nm, id);
    }

    /**
     * Add a package import
     */
    public synchronized void addPackage(Identifier id) {
	packages.addElement(id);
    }
}