/* * 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. Load more
/* * 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. */ @Deprecated public class 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.