--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Wed Sep 03 10:46:25 2008 -0700
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2005-2008 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import com.sun.tools.javac.util.Context;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Caching implementation of FSInfo
+ */
+public class CacheFSInfo extends FSInfo {
+
+ /**
+ * Register a Context.Factory to create a singleton CacheFSInfo.
+ */
+ public static void preRegister(final Context context) {
+ context.put(FSInfo.class, new Context.Factory<FSInfo>() {
+ public FSInfo make() {
+ if (singleton == null)
+ singleton = new CacheFSInfo();
+ context.put(FSInfo.class, singleton);
+ return singleton;
+ }
+ });
+ }
+
+ static CacheFSInfo singleton;
+
+ public void clearCache() {
+ cache.clear();
+ }
+
+ @Override
+ public File getCanonicalFile(File file) {
+ Entry e = getEntry(file);
+ return e.canonicalFile;
+ }
+
+ @Override
+ public boolean exists(File file) {
+ Entry e = getEntry(file);
+ return e.exists;
+ }
+
+ @Override
+ public boolean isDirectory(File file) {
+ Entry e = getEntry(file);
+ return e.isDirectory;
+ }
+
+ @Override
+ public boolean isFile(File file) {
+ Entry e = getEntry(file);
+ return e.isFile;
+ }
+
+ @Override
+ public List<File> getJarClassPath(File file) throws IOException {
+ // don't bother to lock the cache, because it is thread-safe, and
+ // because the worst that can happen would be to create two identical
+ // jar class paths together and have one overwrite the other.
+ Entry e = getEntry(file);
+ if (e.jarClassPath == null)
+ e.jarClassPath = super.getJarClassPath(file);
+ return e.jarClassPath;
+ }
+
+ private Entry getEntry(File file) {
+ // don't bother to lock the cache, because it is thread-safe, and
+ // because the worst that can happen would be to create two identical
+ // entries together and have one overwrite the other.
+ Entry e = cache.get(file);
+ if (e == null) {
+ e = new Entry();
+ e.canonicalFile = super.getCanonicalFile(file);
+ e.exists = super.exists(file);
+ e.isDirectory = super.isDirectory(file);
+ e.isFile = super.isFile(file);
+ cache.put(file, e);
+ }
+ return e;
+ }
+
+ // could also be a Map<File,SoftReference<Entry>> ?
+ private Map<File,Entry> cache = new ConcurrentHashMap<File,Entry>();
+
+ private static class Entry {
+ File canonicalFile;
+ boolean exists;
+ boolean isFile;
+ boolean isDirectory;
+ List<File> jarClassPath;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java Wed Sep 03 10:46:25 2008 -0700
@@ -0,0 +1,89 @@
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Get meta-info about files. Default direct (non-caching) implementation.
+ * @see CacheFSInfo
+ */
+public class FSInfo {
+
+ /** Get the FSInfo instance for this context.
+ * @param context the context
+ * @return the Paths instance for this context
+ */
+ public static FSInfo instance(Context context) {
+ FSInfo instance = context.get(FSInfo.class);
+ if (instance == null)
+ instance = new FSInfo();
+ return instance;
+ }
+
+ protected FSInfo() {
+ }
+
+ protected FSInfo(Context context) {
+ context.put(FSInfo.class, this);
+ }
+
+ public File getCanonicalFile(File file) {
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ return file.getAbsoluteFile();
+ }
+ }
+
+ public boolean exists(File file) {
+ return file.exists();
+ }
+
+ public boolean isDirectory(File file) {
+ return file.isDirectory();
+ }
+
+ public boolean isFile(File file) {
+ return file.isFile();
+ }
+
+ public List<File> getJarClassPath(File file) throws IOException {
+ String parent = file.getParent();
+ JarFile jarFile = new JarFile(file);
+ try {
+ Manifest man = jarFile.getManifest();
+ if (man == null)
+ return Collections.emptyList();
+
+ Attributes attr = man.getMainAttributes();
+ if (attr == null)
+ return Collections.emptyList();
+
+ String path = attr.getValue(Attributes.Name.CLASS_PATH);
+ if (path == null)
+ return Collections.emptyList();
+
+ List<File> list = new ArrayList<File>();
+
+ for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) {
+ String elt = st.nextToken();
+ File f = (parent == null ? new File(elt) : new File(parent, elt));
+ list.add(f);
+ }
+
+ return list;
+ } finally {
+ jarFile.close();
+ }
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Aug 29 11:10:12 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Wed Sep 03 10:46:25 2008 -0700
@@ -55,7 +55,6 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.ZipFile;
import javax.lang.model.SourceVersion;
@@ -88,10 +87,6 @@
boolean useZipFileIndex;
- private static boolean CHECK_ZIP_TIMESTAMP = false;
- private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
-
-
public static char[] toArray(CharBuffer buffer) {
if (buffer.hasArray())
return ((CharBuffer)buffer.compact().flip()).array();
@@ -110,6 +105,8 @@
private Options options;
+ private FSInfo fsInfo;
+
private final File uninited = new File("U N I N I T E D");
private final Set<JavaFileObject.Kind> sourceOrClass =
@@ -172,9 +169,9 @@
}
options = Options.instance(context);
+ fsInfo = FSInfo.instance(context);
useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
- CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null;
mmappedIO = options.get("mmappedIO") != null;
ignoreSymbolFile = options.get("ignore.symbol.file") != null;
@@ -289,20 +286,7 @@
ListBuffer<JavaFileObject> l) {
Archive archive = archives.get(directory);
- boolean isFile = false;
- if (CHECK_ZIP_TIMESTAMP) {
- Boolean isf = isDirectory.get(directory);
- if (isf == null) {
- isFile = directory.isFile();
- isDirectory.put(directory, isFile);
- }
- else {
- isFile = directory.isFile();
- }
- }
- else {
- isFile = directory.isFile();
- }
+ boolean isFile = fsInfo.isFile(directory);
if (archive != null || isFile) {
if (archive == null) {
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Fri Aug 29 11:10:12 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Wed Sep 03 10:46:25 2008 -0700
@@ -31,19 +31,11 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Iterator;
-import java.util.StringTokenizer;
import java.util.zip.ZipFile;
-import java.util.ArrayList;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
import javax.tools.JavaFileManager.Location;
import com.sun.tools.javac.code.Lint;
@@ -90,21 +82,8 @@
/** Handler for -Xlint options */
private Lint lint;
- private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
- private static Map<File, PathEntry> pathExistanceCache = new ConcurrentHashMap<File, PathEntry>();
- private static Map<File, java.util.List<File>> manifestEntries = new ConcurrentHashMap<File, java.util.List<File>>();
- private static Map<File, Boolean> isDirectory = new ConcurrentHashMap<File, Boolean>();
- private static Lock lock = new ReentrantLock();
-
- public static void clearPathExistanceCache() {
- pathExistanceCache.clear();
- }
-
- static class PathEntry {
- boolean exists = false;
- boolean isFile = false;
- File cannonicalPath = null;
- }
+ /** Access to (possibly cached) file info */
+ private FSInfo fsInfo;
protected Paths(Context context) {
context.put(pathsKey, this);
@@ -116,6 +95,7 @@
log = Log.instance(context);
options = Options.instance(context);
lint = Lint.instance(context);
+ fsInfo = FSInfo.instance(context);
}
/** Whether to warn about non-existent path elements */
@@ -294,51 +274,17 @@
}
public void addFile(File file, boolean warn) {
- boolean foundInCache = false;
- PathEntry pe = null;
- if (!NON_BATCH_MODE) {
- pe = pathExistanceCache.get(file);
- if (pe != null) {
- foundInCache = true;
- }
- else {
- pe = new PathEntry();
- }
- }
- else {
- pe = new PathEntry();
- }
-
- File canonFile;
- try {
- if (!foundInCache) {
- pe.cannonicalPath = file.getCanonicalFile();
- }
- else {
- canonFile = pe.cannonicalPath;
- }
- } catch (IOException e) {
- pe.cannonicalPath = canonFile = file;
- }
-
- if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) {
+ File canonFile = fsInfo.getCanonicalFile(file);
+ if (contains(file) || canonicalValues.contains(canonFile)) {
/* Discard duplicates and avoid infinite recursion */
return;
}
- if (!foundInCache) {
- pe.exists = file.exists();
- pe.isFile = file.isFile();
- if (!NON_BATCH_MODE) {
- pathExistanceCache.put(file, pe);
- }
- }
-
- if (! pe.exists) {
+ if (! fsInfo.exists(file)) {
/* No such file or directory exists */
if (warn)
log.warning("path.element.not.found", file);
- } else if (pe.isFile) {
+ } else if (fsInfo.isFile(file)) {
/* File is an ordinary file. */
if (!isArchive(file)) {
/* Not a recognized extension; open it to see if
@@ -360,9 +306,9 @@
/* Now what we have left is either a directory or a file name
confirming to archive naming convention */
super.add(file);
- canonicalValues.add(pe.cannonicalPath);
+ canonicalValues.add(canonFile);
- if (expandJarClassPaths && file.exists() && file.isFile())
+ if (expandJarClassPaths && fsInfo.exists(file) && fsInfo.isFile(file))
addJarClassPath(file, warn);
}
@@ -372,58 +318,8 @@
// filenames, but if we do, we should redo all path-related code.
private void addJarClassPath(File jarFile, boolean warn) {
try {
- java.util.List<File> manifestsList = manifestEntries.get(jarFile);
- if (!NON_BATCH_MODE) {
- lock.lock();
- try {
- if (manifestsList != null) {
- for (File entr : manifestsList) {
- addFile(entr, warn);
- }
- return;
- }
- }
- finally {
- lock.unlock();
- }
- }
-
- if (!NON_BATCH_MODE) {
- manifestsList = new ArrayList<File>();
- manifestEntries.put(jarFile, manifestsList);
- }
-
- String jarParent = jarFile.getParent();
- JarFile jar = new JarFile(jarFile);
-
- try {
- Manifest man = jar.getManifest();
- if (man == null) return;
-
- Attributes attr = man.getMainAttributes();
- if (attr == null) return;
-
- String path = attr.getValue(Attributes.Name.CLASS_PATH);
- if (path == null) return;
-
- for (StringTokenizer st = new StringTokenizer(path);
- st.hasMoreTokens();) {
- String elt = st.nextToken();
- File f = (jarParent == null ? new File(elt) : new File(jarParent, elt));
- addFile(f, warn);
-
- if (!NON_BATCH_MODE) {
- lock.lock();
- try {
- manifestsList.add(f);
- }
- finally {
- lock.unlock();
- }
- }
- }
- } finally {
- jar.close();
+ for (File f: fsInfo.getJarClassPath(jarFile)) {
+ addFile(f, warn);
}
} catch (IOException e) {
log.error("error.reading.file", jarFile, e.getLocalizedMessage());
@@ -554,24 +450,9 @@
}
/** Is this the name of an archive file? */
- private static boolean isArchive(File file) {
+ private boolean isArchive(File file) {
String n = file.getName().toLowerCase();
- boolean isFile = false;
- if (!NON_BATCH_MODE) {
- Boolean isf = isDirectory.get(file);
- if (isf == null) {
- isFile = file.isFile();
- isDirectory.put(file, isFile);
- }
- else {
- isFile = isf;
- }
- }
- else {
- isFile = file.isFile();
- }
-
- return isFile
+ return fsInfo.isFile(file)
&& (n.endsWith(".jar") || n.endsWith(".zip"));
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Aug 29 11:10:12 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Wed Sep 03 10:46:25 2008 -0700
@@ -31,6 +31,7 @@
import java.util.MissingResourceException;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.CacheFSInfo;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.JavacOption.Option;
@@ -368,6 +369,12 @@
context.put(Log.outKey, out);
+ // allow System property in following line as a Mustang legacy
+ boolean batchMode = (options.get("nonBatchMode") == null
+ && System.getProperty("nonBatchMode") == null);
+ if (batchMode)
+ CacheFSInfo.preRegister(context);
+
fileManager = context.get(JavaFileManager.class);
comp = JavaCompiler.instance(context);