1372 lines · 51.6 KB · Java
RawDownload
/* * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.tools.javac; import sun.tools.java.*;import sun.tools.tree.Node;import sun.tools.java.Package; import java.util.*;import java.io.*; /** * Main environment of the batch version of the Java compiler, * this needs more work. * * WARNING: The contents of this source file are not part of any * supported API.  Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */@Deprecatedpublicclass BatchEnvironment extends Environment implements ErrorConsumer {    /**     * The stream where error message are printed.     */    OutputStream out;     /**     * The path we use for finding source files.     */    protected ClassPath sourcePath;     /**     * The path we use for finding class (binary) files.     */    protected ClassPath binaryPath;     /**     * A hashtable of resource contexts.     */    Hashtable packages = new Hashtable(31);     /**     * The classes, in order of appearance.     */    Vector classesOrdered = new Vector();     /**     * The classes, keyed by ClassDeclaration.     */    Hashtable classes = new Hashtable(351);     /**     * flags     */    public int flags;     /**     * Major and minor versions to use for generated class files.     * Environments that extend BatchEnvironment (such as javadoc's     * Env class) get the default values below.     *     * javac itself may override these versions with values determined     * from the command line "-target" option.     */    public short majorVersion = JAVA_DEFAULT_VERSION;    public short minorVersion = JAVA_DEFAULT_MINOR_VERSION; // JCOV    /**     * coverage data file     */    public File covFile;// end JCOV     /**     * The number of errors and warnings     */    public int nerrors;    public int nwarnings;    public int ndeprecations;     /**     * A list of files containing deprecation warnings.     */    Vector deprecationFiles = new Vector();         /**         * writes out error messages         */         ErrorConsumer errorConsumer;     /**     * Old constructors -- these constructors build a BatchEnvironment     * with an old-style class path.     */    public BatchEnvironment(ClassPath path) {        this(System.out, path);    }    public BatchEnvironment(OutputStream out,                            ClassPath path) {        this(out, path, (ErrorConsumer) null);    }    public BatchEnvironment(OutputStream out,                            ClassPath path,                            ErrorConsumer errorConsumer) {        this(out, path, path, errorConsumer);    }     /**     * New constructors -- these constructors build a BatchEnvironment     * with a source path and a binary path.     */    public BatchEnvironment(ClassPath sourcePath,                            ClassPath binaryPath) {        this(System.out, sourcePath, binaryPath);    }    public BatchEnvironment(OutputStream out,                            ClassPath sourcePath,                            ClassPath binaryPath) {        this(out, sourcePath, binaryPath, (ErrorConsumer) null);    }    public BatchEnvironment(OutputStream out,                            ClassPath sourcePath,                            ClassPath binaryPath,                            ErrorConsumer errorConsumer) {        this.out = out;        this.sourcePath = sourcePath;        this.binaryPath = binaryPath;        this.errorConsumer = (errorConsumer == null) ? this : errorConsumer;    }     /**     * Factory     */    static BatchEnvironment create(OutputStream out,                                   String srcPathString,                                   String classPathString,                                   String sysClassPathString,                                   String extDirsString){        ClassPath[] classPaths = classPaths(srcPathString, classPathString,                                            sysClassPathString, extDirsString);        return new BatchEnvironment(out, classPaths[0], classPaths[1]);    }     protected static ClassPath[] classPaths(String srcPathString,                                            String classPathString,                                            String sysClassPathString,                                            String extDirsString) {        // Create our source classpath and our binary classpath        ClassPath sourcePath;        ClassPath binaryPath;        StringBuffer binaryPathBuffer = new StringBuffer();         if (classPathString == null) {            // The env.class.path property is the user's CLASSPATH            // environment variable, and it set by the wrapper (ie,            // javac.exe).            classPathString = System.getProperty("env.class.path");            if (classPathString == null) {                classPathString = ".";            }        }        if (srcPathString == null) {            srcPathString = classPathString;        }        if (sysClassPathString == null) {            sysClassPathString = System.getProperty("sun.boot.class.path");            if (sysClassPathString == null) { // shouldn't happen; recover gracefully                sysClassPathString = classPathString;            }        }        appendPath(binaryPathBuffer, sysClassPathString);         if (extDirsString == null) {            extDirsString = System.getProperty("java.ext.dirs");        }        if (extDirsString != null) {            StringTokenizer st = new StringTokenizer(extDirsString,                                                     File.pathSeparator);            while (st.hasMoreTokens()) {                String dirName = st.nextToken();                File dir = new File(dirName);                if (!dirName.endsWith(File.separator)) {                    dirName += File.separator;                }                if (dir.isDirectory()) {                    String[] files = dir.list();                    for (int i = 0; i < files.length; ++i) {                        String name = files[i];                        if (name.endsWith(".jar")) {                            appendPath(binaryPathBuffer, dirName + name);                        }                    }                }            }        }         appendPath(binaryPathBuffer, classPathString);         sourcePath = new ClassPath(srcPathString);        binaryPath = new ClassPath(binaryPathBuffer.toString());         return new ClassPath[]{sourcePath, binaryPath};    }     private static void appendPath(StringBuffer buf, String str) {        if (str.length() > 0) {            if (buf.length() > 0) {                buf.append(File.pathSeparator);            }            buf.append(str);        }    }     /**     * Return flags     */    public int getFlags() {        return flags;    }     /**     * Return major version to use for generated class files     */    public short getMajorVersion() {        return majorVersion;    }     /**     * Return minor version to use for generated class files     */    public short getMinorVersion() {        return minorVersion;    } // JCOV    /**     * Return coverage data file     */    public File getcovFile() {        return covFile;    }// end JCOV     /**     * Return an enumeration of all the currently defined classes     * in order of appearance to getClassDeclaration().     */    public Enumeration getClasses() {        return classesOrdered.elements();    }     /**     * A set of Identifiers for all packages exempt from the "exists"     * check in Imports#resolve().  These are the current packages for     * all classes being compiled as of the first call to isExemptPackage.     */    private Set exemptPackages;     /**     * Tells whether an Identifier refers to a package which should be     * exempt from the "exists" check in Imports#resolve().     */    public boolean isExemptPackage(Identifier id) {        if (exemptPackages == null) {            // Collect a list of the packages of all classes currently            // being compiled.            setExemptPackages();        }         return exemptPackages.contains(id);    }     /**     * Set the set of packages which are exempt from the exists check     * in Imports#resolve().     */    private void setExemptPackages() {        // The JLS gives us the freedom to define "accessibility" of        // a package in whatever manner we wish.  After the evaluation        // of bug 4093217, we have decided to consider a package P        // accessible if either:        //        // 1. The directory corresponding to P exists on the classpath.        // 2. For any class C currently being compiled, C belongs to        //    package P.        // 3. For any class C currently being compiled, C belongs to        //    package Q and Q is a subpackage of P.        //        // In order to implement this, we collect the current packages        // (and prefixes) of all packages we have found so far.  These        // will be exempt from the "exists" check in        // sun.tools.java.Imports#resolve().         exemptPackages = new HashSet(101);         // Add all of the current packages and their prefixes to our set.        for (Enumeration e = getClasses(); e.hasMoreElements(); ) {            ClassDeclaration c = (ClassDeclaration) e.nextElement();            if (c.getStatus() == CS_PARSED) {                SourceClass def = (SourceClass) c.getClassDefinition();                if (def.isLocal())                    continue;                 Identifier pkg = def.getImports().getCurrentPackage();                 // Add the name of this package and all of its prefixes                // to our set.                while (pkg != idNull && exemptPackages.add(pkg)) {                    pkg = pkg.getQualifier();                }            }        }         // Before we go any further, we make sure java.lang is        // accessible and that it is not ambiguous.  These checks        // are performed for "ordinary" packages in        // sun.tools.java.Imports#resolve().  The reason we perform        // them specially for java.lang is that we want to report        // the error once, and outside of any particular file.         // Check to see if java.lang is accessible.        if (!exemptPackages.contains(idJavaLang)) {            // Add java.lang to the set of exempt packages.            exemptPackages.add(idJavaLang);             try {                if (!getPackage(idJavaLang).exists()) {                    // java.lang doesn't exist.                    error(0, "package.not.found.strong", idJavaLang);                    return;                }            } catch (IOException ee) {                // We got an IO exception checking to see if the package                // java.lang exists.                error(0, "io.exception.package", idJavaLang);            }        }         // Next we ensure that java.lang is not both a class and        // a package.  (Fix for 4101529)        //        // This change has been backed out because, on WIN32, it        // failed to take character case into account.  It will        // be put back in later.        //        // Identifier resolvedName =        //   resolvePackageQualifiedName(idJavaLang);        // Identifier topClassName = resolvedName.getTopName();        //     //if (Imports.importable(topClassName, env)) {        // if (Imports.importable(topClassName, this)) {        //    // It is a package and a class.  Emit the error.        //    error(0, "package.class.conflict.strong",        //            idJavaLang, topClassName);        //    return;        // }    }     /**     * Get a class, given the fully qualified class name     */    public ClassDeclaration getClassDeclaration(Identifier nm) {        return getClassDeclaration(Type.tClass(nm));    }     public ClassDeclaration getClassDeclaration(Type t) {        ClassDeclaration c = (ClassDeclaration)classes.get(t);        if (c == null) {            classes.put(t, c = new ClassDeclaration(t.getClassName()));            classesOrdered.addElement(c);        }        return c;    }     /**     * Check if a class exists     * Applies only to package members (non-nested classes).     */    public boolean classExists(Identifier nm) {        if (nm.isInner()) {            nm = nm.getTopName();       // just in case        }        Type t = Type.tClass(nm);        try {            ClassDeclaration c = (ClassDeclaration)classes.get(t);            return (c != null) ? c.getName().equals(nm) :                getPackage(nm.getQualifier()).classExists(nm.getName());        } catch (IOException e) {            return true;        }    }     /**     * Generate a new name similar to the given one.     * Do it in such a way that repeated compilations of     * the same source generate the same series of names.     */     // This code does not perform as stated above.    // Correction below is part of fix for bug id 4056065.    //    // NOTE: The method 'generateName' has now been folded into its    // single caller, 'makeClassDefinition', which appears later in    // this file.     /*--------------------------*    public Identifier generateName(ClassDefinition outerClass, Identifier nm) {        Identifier outerNm = outerClass.getName();        Identifier flat = outerNm.getFlatName();        Identifier stem = Identifier.lookup(outerNm.getQualifier(),                                            flat.getHead());        for (int i = 1; ; i++) {            String name = i + (nm.equals(idNull) ? "" : SIG_INNERCLASS + nm);            Identifier nm1 = Identifier.lookupInner(stem,                                                    Identifier.lookup(name));            if (classes.get(Type.tClass(nm1)) == null)                return nm1;        }    }    *--------------------------*/     /**     * Get the package path for a package     */    public Package getPackage(Identifier pkg) throws IOException {        Package p = (Package)packages.get(pkg);        if (p == null) {            packages.put(pkg, p = new Package(sourcePath, binaryPath, pkg));        }        return p;    }     /**     * Parse a source file     */    public void parseFile(ClassFile file) throws FileNotFoundException {        long tm = System.currentTimeMillis();        InputStream input;        BatchParser p;         if (tracing) dtEnter("parseFile: PARSING SOURCE " + file);         Environment env = new Environment(this, file);         try {            input = file.getInputStream();            env.setCharacterEncoding(getCharacterEncoding());            //      p = new BatchParser(e, new BufferedInputStream(input));            p = new BatchParser(env, input);        } catch(IOException ex) {            if (tracing) dtEvent("parseFile: IO EXCEPTION " + file);            throw new FileNotFoundException();        }         try {            p.parseFile();        } catch(Exception e) {            throw new CompilerError(e);        }         try {            input.close();        } catch (IOException ex) {            // We're turn with the input, so ignore this.        }         if (verbose()) {            tm = System.currentTimeMillis() - tm;            output(Main.getText("benv.parsed_in", file.getPath(),                                Long.toString(tm)));        }         if (p.classes.size() == 0) {            // The JLS allows a file to contain no compilation units --            // that is, it allows a file to contain no classes or interfaces.

Lines 1–500 of 1372.