--- a/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Mon Jun 16 22:23:33 2008 -0700
@@ -26,20 +26,14 @@
package com.sun.tools.apt.main;
import java.io.*;
-import java.nio.CharBuffer;
-import java.util.Set;
-import java.util.HashSet;
import java.util.Map;
-import java.util.HashMap;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.parser.*;
-import com.sun.tools.javac.comp.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.code.Symbol.*;
--- a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Mon Jun 16 22:23:33 2008 -0700
@@ -44,7 +44,7 @@
import java.io.File;
import java.net.MalformedURLException;
-import com.sun.tools.javac.util.Paths;
+import com.sun.tools.javac.file.Paths;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Jun 16 22:23:33 2008 -0700
@@ -36,12 +36,12 @@
import javax.lang.model.type.TypeMirror;
import javax.tools.*;
-import com.sun.source.tree.Tree;
import com.sun.source.tree.*;
import com.sun.source.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.*;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.model.*;
import com.sun.tools.javac.parser.Parser;
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java Mon Jun 16 22:23:33 2008 -0700
@@ -31,7 +31,6 @@
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
@@ -42,13 +41,13 @@
import javax.tools.*;
import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavacOption.OptionKind;
import com.sun.tools.javac.main.JavacOption;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.RecognizedOptions.GrumpyHelper;
import com.sun.tools.javac.main.RecognizedOptions;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.Pair;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2005-2006 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.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.CharsetDecoder;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.JavaFileObject;
+
+import static javax.tools.JavaFileObject.Kind.*;
+
+public abstract class BaseFileObject implements JavaFileObject {
+
+ public JavaFileObject.Kind getKind() {
+ String n = getName();
+ if (n.endsWith(CLASS.extension))
+ return CLASS;
+ else if (n.endsWith(SOURCE.extension))
+ return SOURCE;
+ else if (n.endsWith(HTML.extension))
+ return HTML;
+ else
+ return OTHER;
+ }
+
+ @Override
+ public String toString() {
+ return getPath();
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getPath() {
+ return getName();
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ abstract public String getName();
+
+ public NestingKind getNestingKind() { return null; }
+
+ public Modifier getAccessLevel() { return null; }
+
+ public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
+ }
+
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ throw new UnsupportedOperationException();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,1718 @@
+/*
+ * Copyright 2005-2006 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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.ref.SoftReference;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.main.JavacOption;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.RecognizedOptions;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static com.sun.tools.javac.main.OptionName.*;
+import static javax.tools.StandardLocation.*;
+
+/**
+ * This class provides access to the source, class and other files
+ * used by the compiler and related tools.
+ */
+public class JavacFileManager implements StandardJavaFileManager {
+
+ private static final String[] symbolFileLocation = { "lib", "ct.sym" };
+ private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
+
+ boolean useZipFileIndex;
+
+ private static int symbolFilePrefixLength = 0;
+ static {
+ try {
+ symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
+ } catch (java.io.UnsupportedEncodingException uee) {
+ // Can't happen...UTF-8 is always supported.
+ }
+ }
+
+ 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();
+ else
+ return buffer.toString().toCharArray();
+ }
+
+ /**
+ * The log to be used for error reporting.
+ */
+ protected Log log;
+
+ /** Encapsulates knowledge of paths
+ */
+ private Paths paths;
+
+ private Options options;
+
+ private final File uninited = new File("U N I N I T E D");
+
+ private final Set<JavaFileObject.Kind> sourceOrClass =
+ EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
+
+ /** The standard output directory, primarily used for classes.
+ * Initialized by the "-d" option.
+ * If classOutDir = null, files are written into same directory as the sources
+ * they were generated from.
+ */
+ private File classOutDir = uninited;
+
+ /** The output directory, used when generating sources while processing annotations.
+ * Initialized by the "-s" option.
+ */
+ private File sourceOutDir = uninited;
+
+ protected boolean mmappedIO;
+ protected boolean ignoreSymbolFile;
+
+ /**
+ * User provided charset (through javax.tools).
+ */
+ protected Charset charset;
+
+ /**
+ * Register a Context.Factory to create a JavacFileManager.
+ */
+ public static void preRegister(final Context context) {
+ context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
+ public JavaFileManager make() {
+ return new JavacFileManager(context, true, null);
+ }
+ });
+ }
+
+ /**
+ * Create a JavacFileManager using a given context, optionally registering
+ * it as the JavaFileManager for that context.
+ */
+ public JavacFileManager(Context context, boolean register, Charset charset) {
+ if (register)
+ context.put(JavaFileManager.class, this);
+ byteBufferCache = new ByteBufferCache();
+ this.charset = charset;
+ setContext(context);
+ }
+
+ /**
+ * Set the context for JavacFileManager.
+ */
+ public void setContext(Context context) {
+ log = Log.instance(context);
+ if (paths == null) {
+ paths = Paths.instance(context);
+ } else {
+ // Reuse the Paths object as it stores the locations that
+ // have been set with setLocation, etc.
+ paths.setContext(context);
+ }
+
+ options = Options.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;
+ }
+
+ public JavaFileObject getFileForInput(String name) {
+ return getRegularFile(new File(name));
+ }
+
+ public JavaFileObject getRegularFile(File file) {
+ return new RegularFileObject(file);
+ }
+
+ public JavaFileObject getFileForOutput(String classname,
+ JavaFileObject.Kind kind,
+ JavaFileObject sibling)
+ throws IOException
+ {
+ return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
+ ListBuffer<File> files = new ListBuffer<File>();
+ for (String name : names)
+ files.append(new File(nullCheck(name)));
+ return getJavaFileObjectsFromFiles(files.toList());
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
+ return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
+ }
+
+ protected JavaFileObject.Kind getKind(String extension) {
+ if (extension.equals(JavaFileObject.Kind.CLASS.extension))
+ return JavaFileObject.Kind.CLASS;
+ else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
+ return JavaFileObject.Kind.SOURCE;
+ else if (extension.equals(JavaFileObject.Kind.HTML.extension))
+ return JavaFileObject.Kind.HTML;
+ else
+ return JavaFileObject.Kind.OTHER;
+ }
+
+ private static boolean isValidName(String name) {
+ // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
+ // but the set of keywords depends on the source level, and we don't want
+ // impls of JavaFileManager to have to be dependent on the source level.
+ // Therefore we simply check that the argument is a sequence of identifiers
+ // separated by ".".
+ for (String s : name.split("\\.", -1)) {
+ if (!SourceVersion.isIdentifier(s))
+ return false;
+ }
+ return true;
+ }
+
+ private static void validateClassName(String className) {
+ if (!isValidName(className))
+ throw new IllegalArgumentException("Invalid class name: " + className);
+ }
+
+ private static void validatePackageName(String packageName) {
+ if (packageName.length() > 0 && !isValidName(packageName))
+ throw new IllegalArgumentException("Invalid packageName name: " + packageName);
+ }
+
+ public static void testName(String name,
+ boolean isValidPackageName,
+ boolean isValidClassName)
+ {
+ try {
+ validatePackageName(name);
+ if (!isValidPackageName)
+ throw new AssertionError("Invalid package name accepted: " + name);
+ printAscii("Valid package name: \"%s\"", name);
+ } catch (IllegalArgumentException e) {
+ if (isValidPackageName)
+ throw new AssertionError("Valid package name rejected: " + name);
+ printAscii("Invalid package name: \"%s\"", name);
+ }
+ try {
+ validateClassName(name);
+ if (!isValidClassName)
+ throw new AssertionError("Invalid class name accepted: " + name);
+ printAscii("Valid class name: \"%s\"", name);
+ } catch (IllegalArgumentException e) {
+ if (isValidClassName)
+ throw new AssertionError("Valid class name rejected: " + name);
+ printAscii("Invalid class name: \"%s\"", name);
+ }
+ }
+ private static void printAscii(String format, Object... args) {
+ String message;
+ try {
+ final String ascii = "US-ASCII";
+ message = new String(String.format(null, format, args).getBytes(ascii), ascii);
+ } catch (java.io.UnsupportedEncodingException ex) {
+ throw new AssertionError(ex);
+ }
+ System.out.println(message);
+ }
+
+ /** Return external representation of name,
+ * converting '.' to File.separatorChar.
+ */
+ private static String externalizeFileName(CharSequence name) {
+ return name.toString().replace('.', File.separatorChar);
+ }
+
+ private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
+ return externalizeFileName(n) + kind.extension;
+ }
+
+ private static String baseName(String fileName) {
+ return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
+ }
+
+ /**
+ * Insert all files in subdirectory `subdirectory' of `directory' which end
+ * in one of the extensions in `extensions' into packageSym.
+ */
+ private void listDirectory(File directory,
+ String subdirectory,
+ Set<JavaFileObject.Kind> fileKinds,
+ boolean recurse,
+ 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();
+ }
+
+ if (archive != null || isFile) {
+ if (archive == null) {
+ try {
+ archive = openArchive(directory);
+ } catch (IOException ex) {
+ log.error("error.reading.file",
+ directory, ex.getLocalizedMessage());
+ return;
+ }
+ }
+ if (subdirectory.length() != 0) {
+ if (!useZipFileIndex) {
+ subdirectory = subdirectory.replace('\\', '/');
+ if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
+ }
+ else {
+ if (File.separatorChar == '/') {
+ subdirectory = subdirectory.replace('\\', '/');
+ }
+ else {
+ subdirectory = subdirectory.replace('/', '\\');
+ }
+
+ if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
+ }
+ }
+
+ List<String> files = archive.getFiles(subdirectory);
+ if (files != null) {
+ for (String file; !files.isEmpty(); files = files.tail) {
+ file = files.head;
+ if (isValidFile(file, fileKinds)) {
+ l.append(archive.getFileObject(subdirectory, file));
+ }
+ }
+ }
+ if (recurse) {
+ for (String s: archive.getSubdirectories()) {
+ if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
+ // Because the archive map is a flat list of directories,
+ // the enclosing loop will pick up all child subdirectories.
+ // Therefore, there is no need to recurse deeper.
+ listDirectory(directory, s, fileKinds, false, l);
+ }
+ }
+ }
+ } else {
+ File d = subdirectory.length() != 0
+ ? new File(directory, subdirectory)
+ : directory;
+ if (!caseMapCheck(d, subdirectory))
+ return;
+
+ File[] files = d.listFiles();
+ if (files == null)
+ return;
+
+ for (File f: files) {
+ String fname = f.getName();
+ if (f.isDirectory()) {
+ if (recurse && SourceVersion.isIdentifier(fname)) {
+ listDirectory(directory,
+ subdirectory + File.separator + fname,
+ fileKinds,
+ recurse,
+ l);
+ }
+ } else {
+ if (isValidFile(fname, fileKinds)) {
+ JavaFileObject fe =
+ new RegularFileObject(fname, new File(d, fname));
+ l.append(fe);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
+ int lastDot = s.lastIndexOf(".");
+ String extn = (lastDot == -1 ? s : s.substring(lastDot));
+ JavaFileObject.Kind kind = getKind(extn);
+ return fileKinds.contains(kind);
+ }
+
+ private static final boolean fileSystemIsCaseSensitive =
+ File.separatorChar == '/';
+
+ /** Hack to make Windows case sensitive. Test whether given path
+ * ends in a string of characters with the same case as given name.
+ * Ignore file separators in both path and name.
+ */
+ private boolean caseMapCheck(File f, String name) {
+ if (fileSystemIsCaseSensitive) return true;
+ // Note that getCanonicalPath() returns the case-sensitive
+ // spelled file name.
+ String path;
+ try {
+ path = f.getCanonicalPath();
+ } catch (IOException ex) {
+ return false;
+ }
+ char[] pcs = path.toCharArray();
+ char[] ncs = name.toCharArray();
+ int i = pcs.length - 1;
+ int j = ncs.length - 1;
+ while (i >= 0 && j >= 0) {
+ while (i >= 0 && pcs[i] == File.separatorChar) i--;
+ while (j >= 0 && ncs[j] == File.separatorChar) j--;
+ if (i >= 0 && j >= 0) {
+ if (pcs[i] != ncs[j]) return false;
+ i--;
+ j--;
+ }
+ }
+ return j < 0;
+ }
+
+ /**
+ * An archive provides a flat directory structure of a ZipFile by
+ * mapping directory names to lists of files (basenames).
+ */
+ public interface Archive {
+ void close() throws IOException;
+
+ boolean contains(String name);
+
+ JavaFileObject getFileObject(String subdirectory, String file);
+
+ List<String> getFiles(String subdirectory);
+
+ Set<String> getSubdirectories();
+ }
+
+ public class ZipArchive implements Archive {
+ protected final Map<String,List<String>> map;
+ protected final ZipFile zdir;
+ public ZipArchive(ZipFile zdir) throws IOException {
+ this.zdir = zdir;
+ this.map = new HashMap<String,List<String>>();
+ for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
+ ZipEntry entry;
+ try {
+ entry = e.nextElement();
+ } catch (InternalError ex) {
+ IOException io = new IOException();
+ io.initCause(ex); // convenience constructors added in Mustang :-(
+ throw io;
+ }
+ addZipEntry(entry);
+ }
+ }
+
+ void addZipEntry(ZipEntry entry) {
+ String name = entry.getName();
+ int i = name.lastIndexOf('/');
+ String dirname = name.substring(0, i+1);
+ String basename = name.substring(i+1);
+ if (basename.length() == 0)
+ return;
+ List<String> list = map.get(dirname);
+ if (list == null)
+ list = List.nil();
+ list = list.prepend(basename);
+ map.put(dirname, list);
+ }
+
+ public boolean contains(String name) {
+ int i = name.lastIndexOf('/');
+ String dirname = name.substring(0, i+1);
+ String basename = name.substring(i+1);
+ if (basename.length() == 0)
+ return false;
+ List<String> list = map.get(dirname);
+ return (list != null && list.contains(basename));
+ }
+
+ public List<String> getFiles(String subdirectory) {
+ return map.get(subdirectory);
+ }
+
+ public JavaFileObject getFileObject(String subdirectory, String file) {
+ ZipEntry ze = zdir.getEntry(subdirectory + file);
+ return new ZipFileObject(file, zdir, ze);
+ }
+
+ public Set<String> getSubdirectories() {
+ return map.keySet();
+ }
+
+ public void close() throws IOException {
+ zdir.close();
+ }
+ }
+
+ public class SymbolArchive extends ZipArchive {
+ final File origFile;
+ public SymbolArchive(File orig, ZipFile zdir) throws IOException {
+ super(zdir);
+ this.origFile = orig;
+ }
+
+ @Override
+ void addZipEntry(ZipEntry entry) {
+ // called from super constructor, may not refer to origFile.
+ String name = entry.getName();
+ if (!name.startsWith(symbolFilePrefix))
+ return;
+ name = name.substring(symbolFilePrefix.length());
+ int i = name.lastIndexOf('/');
+ String dirname = name.substring(0, i+1);
+ String basename = name.substring(i+1);
+ if (basename.length() == 0)
+ return;
+ List<String> list = map.get(dirname);
+ if (list == null)
+ list = List.nil();
+ list = list.prepend(basename);
+ map.put(dirname, list);
+ }
+
+ @Override
+ public JavaFileObject getFileObject(String subdirectory, String file) {
+ return super.getFileObject(symbolFilePrefix + subdirectory, file);
+ }
+ }
+
+ public class MissingArchive implements Archive {
+ final File zipFileName;
+ public MissingArchive(File name) {
+ zipFileName = name;
+ }
+ public boolean contains(String name) {
+ return false;
+ }
+
+ public void close() {
+ }
+
+ public JavaFileObject getFileObject(String subdirectory, String file) {
+ return null;
+ }
+
+ public List<String> getFiles(String subdirectory) {
+ return List.nil();
+ }
+
+ public Set<String> getSubdirectories() {
+ return Collections.emptySet();
+ }
+ }
+
+ /** A directory of zip files already opened.
+ */
+ Map<File, Archive> archives = new HashMap<File,Archive>();
+
+ /** Open a new zip file directory.
+ */
+ protected Archive openArchive(File zipFileName) throws IOException {
+ Archive archive = archives.get(zipFileName);
+ if (archive == null) {
+ File origZipFileName = zipFileName;
+ if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
+ File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
+ if (new File(file.getName()).equals(new File("jre")))
+ file = file.getParentFile();
+ // file == ${jdk.home}
+ for (String name : symbolFileLocation)
+ file = new File(file, name);
+ // file == ${jdk.home}/lib/ct.sym
+ if (file.exists())
+ zipFileName = file;
+ }
+
+ try {
+
+ ZipFile zdir = null;
+
+ boolean usePreindexedCache = false;
+ String preindexCacheLocation = null;
+
+ if (!useZipFileIndex) {
+ zdir = new ZipFile(zipFileName);
+ }
+ else {
+ usePreindexedCache = options.get("usezipindex") != null;
+ preindexCacheLocation = options.get("java.io.tmpdir");
+ String optCacheLoc = options.get("cachezipindexdir");
+
+ if (optCacheLoc != null && optCacheLoc.length() != 0) {
+ if (optCacheLoc.startsWith("\"")) {
+ if (optCacheLoc.endsWith("\"")) {
+ optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
+ }
+ else {
+ optCacheLoc = optCacheLoc.substring(1);
+ }
+ }
+
+ File cacheDir = new File(optCacheLoc);
+ if (cacheDir.exists() && cacheDir.canWrite()) {
+ preindexCacheLocation = optCacheLoc;
+ if (!preindexCacheLocation.endsWith("/") &&
+ !preindexCacheLocation.endsWith(File.separator)) {
+ preindexCacheLocation += File.separator;
+ }
+ }
+ }
+ }
+
+ if (origZipFileName == zipFileName) {
+ if (!useZipFileIndex) {
+ archive = new ZipArchive(zdir);
+ } else {
+ archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
+ usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
+ }
+ }
+ else {
+ if (!useZipFileIndex) {
+ archive = new SymbolArchive(origZipFileName, zdir);
+ }
+ else {
+ archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
+ usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
+ }
+ }
+ } catch (FileNotFoundException ex) {
+ archive = new MissingArchive(zipFileName);
+ } catch (IOException ex) {
+ log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
+ archive = new MissingArchive(zipFileName);
+ }
+
+ archives.put(origZipFileName, archive);
+ }
+ return archive;
+ }
+
+ /** Flush any output resources.
+ */
+ public void flush() {
+ contentCache.clear();
+ }
+
+ /**
+ * Close the JavaFileManager, releasing resources.
+ */
+ public void close() {
+ for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
+ Archive a = i.next();
+ i.remove();
+ try {
+ a.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
+
+ private String defaultEncodingName;
+ private String getDefaultEncodingName() {
+ if (defaultEncodingName == null) {
+ defaultEncodingName =
+ new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+ }
+ return defaultEncodingName;
+ }
+
+ protected String getEncodingName() {
+ String encName = options.get(OptionName.ENCODING);
+ if (encName == null)
+ return getDefaultEncodingName();
+ else
+ return encName;
+ }
+
+ protected Source getSource() {
+ String sourceName = options.get(OptionName.SOURCE);
+ Source source = null;
+ if (sourceName != null)
+ source = Source.lookup(sourceName);
+ return (source != null ? source : Source.DEFAULT);
+ }
+
+ /**
+ * Make a byte buffer from an input stream.
+ */
+ private ByteBuffer makeByteBuffer(InputStream in)
+ throws IOException {
+ int limit = in.available();
+ if (mmappedIO && in instanceof FileInputStream) {
+ // Experimental memory mapped I/O
+ FileInputStream fin = (FileInputStream)in;
+ return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
+ }
+ if (limit < 1024) limit = 1024;
+ ByteBuffer result = byteBufferCache.get(limit);
+ int position = 0;
+ while (in.available() != 0) {
+ if (position >= limit)
+ // expand buffer
+ result = ByteBuffer.
+ allocate(limit <<= 1).
+ put((ByteBuffer)result.flip());
+ int count = in.read(result.array(),
+ position,
+ limit - position);
+ if (count < 0) break;
+ result.position(position += count);
+ }
+ return (ByteBuffer)result.flip();
+ }
+
+ /**
+ * A single-element cache of direct byte buffers.
+ */
+ private static class ByteBufferCache {
+ private ByteBuffer cached;
+ ByteBuffer get(int capacity) {
+ if (capacity < 20480) capacity = 20480;
+ ByteBuffer result =
+ (cached != null && cached.capacity() >= capacity)
+ ? (ByteBuffer)cached.clear()
+ : ByteBuffer.allocate(capacity + capacity>>1);
+ cached = null;
+ return result;
+ }
+ void put(ByteBuffer x) {
+ cached = x;
+ }
+ }
+ private final ByteBufferCache byteBufferCache;
+
+ private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+ Charset charset = (this.charset == null)
+ ? Charset.forName(encodingName)
+ : this.charset;
+ CharsetDecoder decoder = charset.newDecoder();
+
+ CodingErrorAction action;
+ if (ignoreEncodingErrors)
+ action = CodingErrorAction.REPLACE;
+ else
+ action = CodingErrorAction.REPORT;
+
+ return decoder
+ .onMalformedInput(action)
+ .onUnmappableCharacter(action);
+ }
+
+ /**
+ * Decode a ByteBuffer into a CharBuffer.
+ */
+ private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
+ String encodingName = getEncodingName();
+ CharsetDecoder decoder;
+ try {
+ decoder = getDecoder(encodingName, ignoreEncodingErrors);
+ } catch (IllegalCharsetNameException e) {
+ log.error("unsupported.encoding", encodingName);
+ return (CharBuffer)CharBuffer.allocate(1).flip();
+ } catch (UnsupportedCharsetException e) {
+ log.error("unsupported.encoding", encodingName);
+ return (CharBuffer)CharBuffer.allocate(1).flip();
+ }
+
+ // slightly overestimate the buffer size to avoid reallocation.
+ float factor =
+ decoder.averageCharsPerByte() * 0.8f +
+ decoder.maxCharsPerByte() * 0.2f;
+ CharBuffer dest = CharBuffer.
+ allocate(10 + (int)(inbuf.remaining()*factor));
+
+ while (true) {
+ CoderResult result = decoder.decode(inbuf, dest, true);
+ dest.flip();
+
+ if (result.isUnderflow()) { // done reading
+ // make sure there is at least one extra character
+ if (dest.limit() == dest.capacity()) {
+ dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
+ dest.flip();
+ }
+ return dest;
+ } else if (result.isOverflow()) { // buffer too small; expand
+ int newCapacity =
+ 10 + dest.capacity() +
+ (int)(inbuf.remaining()*decoder.maxCharsPerByte());
+ dest = CharBuffer.allocate(newCapacity).put(dest);
+ } else if (result.isMalformed() || result.isUnmappable()) {
+ // bad character in input
+
+ // report coding error (warn only pre 1.5)
+ if (!getSource().allowEncodingErrors()) {
+ log.error(new SimpleDiagnosticPosition(dest.limit()),
+ "illegal.char.for.encoding",
+ charset == null ? encodingName : charset.name());
+ } else {
+ log.warning(new SimpleDiagnosticPosition(dest.limit()),
+ "illegal.char.for.encoding",
+ charset == null ? encodingName : charset.name());
+ }
+
+ // skip past the coding error
+ inbuf.position(inbuf.position() + result.length());
+
+ // undo the flip() to prepare the output buffer
+ // for more translation
+ dest.position(dest.limit());
+ dest.limit(dest.capacity());
+ dest.put((char)0xfffd); // backward compatible
+ } else {
+ throw new AssertionError(result);
+ }
+ }
+ // unreached
+ }
+
+ public ClassLoader getClassLoader(Location location) {
+ nullCheck(location);
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null)
+ return null;
+ ListBuffer<URL> lb = new ListBuffer<URL>();
+ for (File f: path) {
+ try {
+ lb.append(f.toURI().toURL());
+ } catch (MalformedURLException e) {
+ throw new AssertionError(e);
+ }
+ }
+ return new URLClassLoader(lb.toArray(new URL[lb.size()]),
+ getClass().getClassLoader());
+ }
+
+ public Iterable<JavaFileObject> list(Location location,
+ String packageName,
+ Set<JavaFileObject.Kind> kinds,
+ boolean recurse)
+ throws IOException
+ {
+ // validatePackageName(packageName);
+ nullCheck(packageName);
+ nullCheck(kinds);
+
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null)
+ return List.nil();
+ String subdirectory = externalizeFileName(packageName);
+ ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
+
+ for (File directory : path)
+ listDirectory(directory, subdirectory, kinds, recurse, results);
+
+ return results.toList();
+ }
+
+ public String inferBinaryName(Location location, JavaFileObject file) {
+ file.getClass(); // null check
+ location.getClass(); // null check
+ // Need to match the path semantics of list(location, ...)
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null) {
+ //System.err.println("Path for " + location + " is null");
+ return null;
+ }
+ //System.err.println("Path for " + location + " is " + path);
+
+ if (file instanceof RegularFileObject) {
+ RegularFileObject r = (RegularFileObject) file;
+ String rPath = r.getPath();
+ //System.err.println("RegularFileObject " + file + " " +r.getPath());
+ for (File dir: path) {
+ //System.err.println("dir: " + dir);
+ String dPath = dir.getPath();
+ if (!dPath.endsWith(File.separator))
+ dPath += File.separator;
+ if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
+ && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
+ String relativeName = rPath.substring(dPath.length());
+ return removeExtension(relativeName).replace(File.separatorChar, '.');
+ }
+ }
+ } else if (file instanceof ZipFileObject) {
+ ZipFileObject z = (ZipFileObject) file;
+ String entryName = z.getZipEntryName();
+ if (entryName.startsWith(symbolFilePrefix))
+ entryName = entryName.substring(symbolFilePrefix.length());
+ return removeExtension(entryName).replace('/', '.');
+ } else if (file instanceof ZipFileIndexFileObject) {
+ ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
+ String entryName = z.getZipEntryName();
+ if (entryName.startsWith(symbolFilePrefix))
+ entryName = entryName.substring(symbolFilePrefix.length());
+ return removeExtension(entryName).replace(File.separatorChar, '.');
+ } else
+ throw new IllegalArgumentException(file.getClass().getName());
+ // System.err.println("inferBinaryName failed for " + file);
+ return null;
+ }
+ // where
+ private static String removeExtension(String fileName) {
+ int lastDot = fileName.lastIndexOf(".");
+ return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+ }
+
+ public boolean isSameFile(FileObject a, FileObject b) {
+ nullCheck(a);
+ nullCheck(b);
+ if (!(a instanceof BaseFileObject))
+ throw new IllegalArgumentException("Not supported: " + a);
+ if (!(b instanceof BaseFileObject))
+ throw new IllegalArgumentException("Not supported: " + b);
+ return a.equals(b);
+ }
+
+ public boolean handleOption(String current, Iterator<String> remaining) {
+ for (JavacOption o: javacFileManagerOptions) {
+ if (o.matches(current)) {
+ if (o.hasArg()) {
+ if (remaining.hasNext()) {
+ if (!o.process(options, current, remaining.next()))
+ return true;
+ }
+ } else {
+ if (!o.process(options, current))
+ return true;
+ }
+ // operand missing, or process returned false
+ throw new IllegalArgumentException(current);
+ }
+ }
+
+ return false;
+ }
+ // where
+ private static JavacOption[] javacFileManagerOptions =
+ RecognizedOptions.getJavacFileManagerOptions(
+ new RecognizedOptions.GrumpyHelper());
+
+ public int isSupportedOption(String option) {
+ for (JavacOption o : javacFileManagerOptions) {
+ if (o.matches(option))
+ return o.hasArg() ? 1 : 0;
+ }
+ return -1;
+ }
+
+ public boolean hasLocation(Location location) {
+ return getLocation(location) != null;
+ }
+
+ public JavaFileObject getJavaFileForInput(Location location,
+ String className,
+ JavaFileObject.Kind kind)
+ throws IOException
+ {
+ nullCheck(location);
+ // validateClassName(className);
+ nullCheck(className);
+ nullCheck(kind);
+ if (!sourceOrClass.contains(kind))
+ throw new IllegalArgumentException("Invalid kind " + kind);
+ return getFileForInput(location, externalizeFileName(className, kind));
+ }
+
+ public FileObject getFileForInput(Location location,
+ String packageName,
+ String relativeName)
+ throws IOException
+ {
+ nullCheck(location);
+ // validatePackageName(packageName);
+ nullCheck(packageName);
+ if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
+ throw new IllegalArgumentException("Invalid relative name: " + relativeName);
+ String name = packageName.length() == 0
+ ? relativeName
+ : new File(externalizeFileName(packageName), relativeName).getPath();
+ return getFileForInput(location, name);
+ }
+
+ private JavaFileObject getFileForInput(Location location, String name) throws IOException {
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null)
+ return null;
+
+ for (File dir: path) {
+ if (dir.isDirectory()) {
+ File f = new File(dir, name.replace('/', File.separatorChar));
+ if (f.exists())
+ return new RegularFileObject(f);
+ } else {
+ Archive a = openArchive(dir);
+ if (a.contains(name)) {
+ int i = name.lastIndexOf('/');
+ String dirname = name.substring(0, i+1);
+ String basename = name.substring(i+1);
+ return a.getFileObject(dirname, basename);
+ }
+
+ }
+ }
+ return null;
+
+ }
+
+ public JavaFileObject getJavaFileForOutput(Location location,
+ String className,
+ JavaFileObject.Kind kind,
+ FileObject sibling)
+ throws IOException
+ {
+ nullCheck(location);
+ // validateClassName(className);
+ nullCheck(className);
+ nullCheck(kind);
+ if (!sourceOrClass.contains(kind))
+ throw new IllegalArgumentException("Invalid kind " + kind);
+ return getFileForOutput(location, externalizeFileName(className, kind), sibling);
+ }
+
+ public FileObject getFileForOutput(Location location,
+ String packageName,
+ String relativeName,
+ FileObject sibling)
+ throws IOException
+ {
+ nullCheck(location);
+ // validatePackageName(packageName);
+ nullCheck(packageName);
+ if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
+ throw new IllegalArgumentException("relativeName is invalid");
+ String name = packageName.length() == 0
+ ? relativeName
+ : new File(externalizeFileName(packageName), relativeName).getPath();
+ return getFileForOutput(location, name, sibling);
+ }
+
+ private JavaFileObject getFileForOutput(Location location,
+ String fileName,
+ FileObject sibling)
+ throws IOException
+ {
+ File dir;
+ if (location == CLASS_OUTPUT) {
+ if (getClassOutDir() != null) {
+ dir = getClassOutDir();
+ } else {
+ File siblingDir = null;
+ if (sibling != null && sibling instanceof RegularFileObject) {
+ siblingDir = ((RegularFileObject)sibling).f.getParentFile();
+ }
+ return new RegularFileObject(new File(siblingDir, baseName(fileName)));
+ }
+ } else if (location == SOURCE_OUTPUT) {
+ dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
+ } else {
+ Iterable<? extends File> path = paths.getPathForLocation(location);
+ dir = null;
+ for (File f: path) {
+ dir = f;
+ break;
+ }
+ }
+
+ File file = (dir == null ? new File(fileName) : new File(dir, fileName));
+ return new RegularFileObject(file);
+
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
+ Iterable<? extends File> files)
+ {
+ ArrayList<RegularFileObject> result;
+ if (files instanceof Collection)
+ result = new ArrayList<RegularFileObject>(((Collection)files).size());
+ else
+ result = new ArrayList<RegularFileObject>();
+ for (File f: files)
+ result.add(new RegularFileObject(nullCheck(f)));
+ return result;
+ }
+
+ public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
+ return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
+ }
+
+ public void setLocation(Location location,
+ Iterable<? extends File> path)
+ throws IOException
+ {
+ nullCheck(location);
+ paths.lazy();
+
+ final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
+
+ if (location == CLASS_OUTPUT)
+ classOutDir = getOutputLocation(dir, D);
+ else if (location == SOURCE_OUTPUT)
+ sourceOutDir = getOutputLocation(dir, S);
+ else
+ paths.setPathForLocation(location, path);
+ }
+ // where
+ private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
+ if (path == null)
+ return null;
+ Iterator<? extends File> pathIter = path.iterator();
+ if (!pathIter.hasNext())
+ throw new IllegalArgumentException("empty path for directory");
+ File dir = pathIter.next();
+ if (pathIter.hasNext())
+ throw new IllegalArgumentException("path too long for directory");
+ if (!dir.exists())
+ throw new FileNotFoundException(dir + ": does not exist");
+ else if (!dir.isDirectory())
+ throw new IOException(dir + ": not a directory");
+ return dir;
+ }
+
+ private File getOutputLocation(File dir, OptionName defaultOptionName) {
+ if (dir != null)
+ return dir;
+ String arg = options.get(defaultOptionName);
+ if (arg == null)
+ return null;
+ return new File(arg);
+ }
+
+ public Iterable<? extends File> getLocation(Location location) {
+ nullCheck(location);
+ paths.lazy();
+ if (location == CLASS_OUTPUT) {
+ return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
+ } else if (location == SOURCE_OUTPUT) {
+ return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
+ } else
+ return paths.getPathForLocation(location);
+ }
+
+ private File getClassOutDir() {
+ if (classOutDir == uninited)
+ classOutDir = getOutputLocation(null, D);
+ return classOutDir;
+ }
+
+ private File getSourceOutDir() {
+ if (sourceOutDir == uninited)
+ sourceOutDir = getOutputLocation(null, S);
+ return sourceOutDir;
+ }
+
+ /**
+ * Enforces the specification of a "relative" URI as used in
+ * {@linkplain #getFileForInput(Location,String,URI)
+ * getFileForInput}. This method must follow the rules defined in
+ * that method, do not make any changes without consulting the
+ * specification.
+ */
+ protected static boolean isRelativeUri(URI uri) {
+ if (uri.isAbsolute())
+ return false;
+ String path = uri.normalize().getPath();
+ if (path.length() == 0 /* isEmpty() is mustang API */)
+ return false;
+ char first = path.charAt(0);
+ return first != '.' && first != '/';
+ }
+
+ /**
+ * Converts a relative file name to a relative URI. This is
+ * different from File.toURI as this method does not canonicalize
+ * the file before creating the URI. Furthermore, no schema is
+ * used.
+ * @param file a relative file name
+ * @return a relative URI
+ * @throws IllegalArgumentException if the file name is not
+ * relative according to the definition given in {@link
+ * javax.tools.JavaFileManager#getFileForInput}
+ */
+ public static String getRelativeName(File file) {
+ if (!file.isAbsolute()) {
+ String result = file.getPath().replace(File.separatorChar, '/');
+ if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
+ return result;
+ }
+ throw new IllegalArgumentException("Invalid relative path: " + file);
+ }
+
+ @SuppressWarnings("deprecation") // bug 6410637
+ public static String getJavacFileName(FileObject file) {
+ if (file instanceof BaseFileObject)
+ return ((BaseFileObject)file).getPath();
+ URI uri = file.toUri();
+ String scheme = uri.getScheme();
+ if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
+ return uri.getPath();
+ else
+ return uri.toString();
+ }
+
+ @SuppressWarnings("deprecation") // bug 6410637
+ public static String getJavacBaseFileName(FileObject file) {
+ if (file instanceof BaseFileObject)
+ return ((BaseFileObject)file).getName();
+ URI uri = file.toUri();
+ String scheme = uri.getScheme();
+ if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
+ String path = uri.getPath();
+ if (path == null)
+ return null;
+ if (scheme != null && scheme.equals("jar"))
+ path = path.substring(path.lastIndexOf('!') + 1);
+ return path.substring(path.lastIndexOf('/') + 1);
+ } else {
+ return uri.toString();
+ }
+ }
+
+ private static <T> T nullCheck(T o) {
+ o.getClass(); // null check
+ return o;
+ }
+
+ private static <T> Iterable<T> nullCheck(Iterable<T> it) {
+ for (T t : it)
+ t.getClass(); // null check
+ return it;
+ }
+
+ /**
+ * A subclass of JavaFileObject representing regular files.
+ */
+ private class RegularFileObject extends BaseFileObject {
+ /** Have the parent directories been created?
+ */
+ private boolean hasParents=false;
+
+ /** The file's name.
+ */
+ private String name;
+
+ /** The underlying file.
+ */
+ final File f;
+
+ public RegularFileObject(File f) {
+ this(f.getName(), f);
+ }
+
+ public RegularFileObject(String name, File f) {
+ if (f.isDirectory())
+ throw new IllegalArgumentException("directories not supported");
+ this.name = name;
+ this.f = f;
+ }
+
+ public InputStream openInputStream() throws IOException {
+ return new FileInputStream(f);
+ }
+
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+ }
+
+ public OutputStream openOutputStream() throws IOException {
+ ensureParentDirectoriesExist();
+ return new FileOutputStream(f);
+ }
+
+ public Writer openWriter() throws IOException {
+ ensureParentDirectoriesExist();
+ return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
+ }
+
+ private void ensureParentDirectoriesExist() throws IOException {
+ if (!hasParents) {
+ File parent = f.getParentFile();
+ if (parent != null && !parent.exists()) {
+ if (!parent.mkdirs()) {
+ // if the mkdirs failed, it may be because another process concurrently
+ // created the directory, so check if the directory got created
+ // anyway before throwing an exception
+ if (!parent.exists() || !parent.isDirectory())
+ throw new IOException("could not create parent directories");
+ }
+ }
+ hasParents = true;
+ }
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getName() {
+ return name;
+ }
+
+ public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
+ cn.getClass(); // null check
+ if (kind == Kind.OTHER && getKind() != kind)
+ return false;
+ String n = cn + kind.extension;
+ if (name.equals(n))
+ return true;
+ if (name.equalsIgnoreCase(n)) {
+ try {
+ // allow for Windows
+ return (f.getCanonicalFile().getName().equals(n));
+ } catch (IOException e) {
+ }
+ }
+ return false;
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getPath() {
+ return f.getPath();
+ }
+
+ public long getLastModified() {
+ return f.lastModified();
+ }
+
+ public boolean delete() {
+ return f.delete();
+ }
+
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ SoftReference<CharBuffer> r = contentCache.get(this);
+ CharBuffer cb = (r == null ? null : r.get());
+ if (cb == null) {
+ InputStream in = new FileInputStream(f);
+ try {
+ ByteBuffer bb = makeByteBuffer(in);
+ JavaFileObject prev = log.useSource(this);
+ try {
+ cb = decode(bb, ignoreEncodingErrors);
+ } finally {
+ log.useSource(prev);
+ }
+ byteBufferCache.put(bb); // save for next time
+ if (!ignoreEncodingErrors)
+ contentCache.put(this, new SoftReference<CharBuffer>(cb));
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RegularFileObject))
+ return false;
+ RegularFileObject o = (RegularFileObject) other;
+ try {
+ return f.equals(o.f)
+ || f.getCanonicalFile().equals(o.f.getCanonicalFile());
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return f.hashCode();
+ }
+
+ public URI toUri() {
+ try {
+ // Do no use File.toURI to avoid file system access
+ String path = f.getAbsolutePath().replace(File.separatorChar, '/');
+ return new URI("file://" + path).normalize();
+ } catch (URISyntaxException ex) {
+ return f.toURI();
+ }
+ }
+
+ }
+
+ /**
+ * A subclass of JavaFileObject representing zip entries.
+ */
+ public class ZipFileObject extends BaseFileObject {
+
+ /** The entry's name.
+ */
+ private String name;
+
+ /** The zipfile containing the entry.
+ */
+ ZipFile zdir;
+
+ /** The underlying zip entry object.
+ */
+ ZipEntry entry;
+
+ public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
+ this.name = name;
+ this.zdir = zdir;
+ this.entry = entry;
+ }
+
+ public InputStream openInputStream() throws IOException {
+ return zdir.getInputStream(entry);
+ }
+
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+ }
+
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getName() {
+ return name;
+ }
+
+ public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
+ cn.getClass(); // null check
+ if (k == Kind.OTHER && getKind() != k)
+ return false;
+ return name.equals(cn + k.extension);
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getPath() {
+ return zdir.getName() + "(" + entry + ")";
+ }
+
+ public long getLastModified() {
+ return entry.getTime();
+ }
+
+ public boolean delete() {
+ throw new UnsupportedOperationException();
+ }
+
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ SoftReference<CharBuffer> r = contentCache.get(this);
+ CharBuffer cb = (r == null ? null : r.get());
+ if (cb == null) {
+ InputStream in = zdir.getInputStream(entry);
+ try {
+ ByteBuffer bb = makeByteBuffer(in);
+ JavaFileObject prev = log.useSource(this);
+ try {
+ cb = decode(bb, ignoreEncodingErrors);
+ } finally {
+ log.useSource(prev);
+ }
+ byteBufferCache.put(bb); // save for next time
+ if (!ignoreEncodingErrors)
+ contentCache.put(this, new SoftReference<CharBuffer>(cb));
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof ZipFileObject))
+ return false;
+ ZipFileObject o = (ZipFileObject) other;
+ return zdir.equals(o.zdir) || name.equals(o.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return zdir.hashCode() + name.hashCode();
+ }
+
+ public String getZipName() {
+ return zdir.getName();
+ }
+
+ public String getZipEntryName() {
+ return entry.getName();
+ }
+
+ public URI toUri() {
+ String zipName = new File(getZipName()).toURI().normalize().getPath();
+ String entryName = getZipEntryName();
+ return URI.create("jar:" + zipName + "!" + entryName);
+ }
+
+ }
+
+ /**
+ * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
+ */
+ public class ZipFileIndexFileObject extends BaseFileObject {
+
+ /** The entry's name.
+ */
+ private String name;
+
+ /** The zipfile containing the entry.
+ */
+ ZipFileIndex zfIndex;
+
+ /** The underlying zip entry object.
+ */
+ ZipFileIndexEntry entry;
+
+ /** The InputStream for this zip entry (file.)
+ */
+ InputStream inputStream = null;
+
+ /** The name of the zip file where this entry resides.
+ */
+ String zipName;
+
+ JavacFileManager defFileManager = null;
+
+ public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
+ super();
+ this.name = entry.getFileName();
+ this.zfIndex = zfIndex;
+ this.entry = entry;
+ this.zipName = zipFileName;
+ defFileManager = fileManager;
+ }
+
+ public InputStream openInputStream() throws IOException {
+
+ if (inputStream == null) {
+ inputStream = new ByteArrayInputStream(read());
+ }
+ return inputStream;
+ }
+
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
+ }
+
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getName() {
+ return name;
+ }
+
+ public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
+ cn.getClass(); // null check
+ if (k == Kind.OTHER && getKind() != k)
+ return false;
+ return name.equals(cn + k.extension);
+ }
+
+ /** @deprecated see bug 6410637 */
+ @Deprecated
+ public String getPath() {
+ return zipName + "(" + entry.getName() + ")";
+ }
+
+ public long getLastModified() {
+ return entry.getLastModified();
+ }
+
+ public boolean delete() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof ZipFileIndexFileObject))
+ return false;
+ ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
+ return entry.equals(o.entry);
+ }
+
+ @Override
+ public int hashCode() {
+ return zipName.hashCode() + (name.hashCode() << 10);
+ }
+
+ public String getZipName() {
+ return zipName;
+ }
+
+ public String getZipEntryName() {
+ return entry.getName();
+ }
+
+ public URI toUri() {
+ String zipName = new File(getZipName()).toURI().normalize().getPath();
+ String entryName = getZipEntryName();
+ if (File.separatorChar != '/') {
+ entryName = entryName.replace(File.separatorChar, '/');
+ }
+ return URI.create("jar:" + zipName + "!" + entryName);
+ }
+
+ private byte[] read() throws IOException {
+ if (entry == null) {
+ entry = zfIndex.getZipIndexEntry(name);
+ if (entry == null)
+ throw new FileNotFoundException();
+ }
+ return zfIndex.read(entry);
+ }
+
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
+ CharBuffer cb = (r == null ? null : r.get());
+ if (cb == null) {
+ InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
+ try {
+ ByteBuffer bb = makeByteBuffer(in);
+ JavaFileObject prev = log.useSource(this);
+ try {
+ cb = decode(bb, ignoreEncodingErrors);
+ } finally {
+ log.useSource(prev);
+ }
+ byteBufferCache.put(bb); // save for next time
+ if (!ignoreEncodingErrors)
+ defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+ }
+
+ public class ZipFileIndexArchive implements Archive {
+ private final ZipFileIndex zfIndex;
+ private JavacFileManager fileManager;
+
+ public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
+ this.fileManager = fileManager;
+ this.zfIndex = zdir;
+ }
+
+ public boolean contains(String name) {
+ return zfIndex.contains(name);
+ }
+
+ public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
+ return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
+ }
+
+ public JavaFileObject getFileObject(String subdirectory, String file) {
+ String fullZipFileName = subdirectory + file;
+ ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
+ JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
+ return ret;
+ }
+
+ public Set<String> getSubdirectories() {
+ return zfIndex.getAllDirectories();
+ }
+
+ public void close() throws IOException {
+ zfIndex.close();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Old199.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2006 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 javax.tools.FileObject;
+
+/**
+ * Provides an easy migration to JSR 199 v3.3. The class is
+ * deprecated as we should remove it as soon as possible.
+ *
+ * <p><b>This is NOT part of any API supported by Sun Microsystems.
+ * If you write code that depends on this, you do so at your own
+ * risk. This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ *
+ * @author Peter von der Ah\u00e9
+ */
+@Deprecated
+public class Old199 {
+
+ private Old199() {}
+
+ public static String getPath(FileObject jfo) {
+ return JavacFileManager.getJavacFileName(jfo);
+ }
+
+ public static String getName(FileObject jfo) {
+ return JavacFileManager.getJavacBaseFileName(jfo);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2003-2006 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.HashMap;
+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;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/** This class converts command line arguments, environment variables
+ * and system properties (in File.pathSeparator-separated String form)
+ * into a boot class path, user class path, and source path (in
+ * Collection<String> form).
+ *
+ * <p><b>This is NOT part of any API supported by Sun Microsystems. If
+ * you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class Paths {
+
+ /** The context key for the todo list */
+ protected static final Context.Key<Paths> pathsKey =
+ new Context.Key<Paths>();
+
+ /** Get the Paths instance for this context.
+ * @param context the context
+ * @return the Paths instance for this context
+ */
+ public static Paths instance(Context context) {
+ Paths instance = context.get(pathsKey);
+ if (instance == null)
+ instance = new Paths(context);
+ return instance;
+ }
+
+ /** The log to use for warning output */
+ private Log log;
+
+ /** Collection of command-line options */
+ private Options options;
+
+ /** 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;
+ }
+
+ protected Paths(Context context) {
+ context.put(pathsKey, this);
+ pathsForLocation = new HashMap<Location,Path>(16);
+ setContext(context);
+ }
+
+ void setContext(Context context) {
+ log = Log.instance(context);
+ options = Options.instance(context);
+ lint = Lint.instance(context);
+ }
+
+ /** Whether to warn about non-existent path elements */
+ private boolean warn;
+
+ private Map<Location, Path> pathsForLocation;
+
+ private boolean inited = false; // TODO? caching bad?
+
+ /**
+ * rt.jar as found on the default bootclass path. If the user specified a
+ * bootclasspath, null is used.
+ */
+ private File bootClassPathRtJar = null;
+
+ Path getPathForLocation(Location location) {
+ Path path = pathsForLocation.get(location);
+ if (path == null)
+ setPathForLocation(location, null);
+ return pathsForLocation.get(location);
+ }
+
+ void setPathForLocation(Location location, Iterable<? extends File> path) {
+ // TODO? if (inited) throw new IllegalStateException
+ // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
+ Path p;
+ if (path == null) {
+ if (location == CLASS_PATH)
+ p = computeUserClassPath();
+ else if (location == PLATFORM_CLASS_PATH)
+ p = computeBootClassPath();
+ else if (location == ANNOTATION_PROCESSOR_PATH)
+ p = computeAnnotationProcessorPath();
+ else if (location == SOURCE_PATH)
+ p = computeSourcePath();
+ else
+ // no defaults for other paths
+ p = null;
+ } else {
+ p = new Path();
+ for (File f: path)
+ p.addFile(f, warn); // TODO: is use of warn appropriate?
+ }
+ pathsForLocation.put(location, p);
+ }
+
+ protected void lazy() {
+ if (!inited) {
+ warn = lint.isEnabled(Lint.LintCategory.PATH);
+
+ pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
+ pathsForLocation.put(CLASS_PATH, computeUserClassPath());
+ pathsForLocation.put(SOURCE_PATH, computeSourcePath());
+
+ inited = true;
+ }
+ }
+
+ public Collection<File> bootClassPath() {
+ lazy();
+ return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
+ }
+ public Collection<File> userClassPath() {
+ lazy();
+ return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
+ }
+ public Collection<File> sourcePath() {
+ lazy();
+ Path p = getPathForLocation(SOURCE_PATH);
+ return p == null || p.size() == 0
+ ? null
+ : Collections.unmodifiableCollection(p);
+ }
+
+ boolean isBootClassPathRtJar(File file) {
+ return file.equals(bootClassPathRtJar);
+ }
+
+ private static class PathIterator implements Iterable<String> {
+ private int pos = 0;
+ private final String path;
+ private final String emptyPathDefault;
+
+ public PathIterator(String path, String emptyPathDefault) {
+ this.path = path;
+ this.emptyPathDefault = emptyPathDefault;
+ }
+ public PathIterator(String path) { this(path, null); }
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ public boolean hasNext() {
+ return pos <= path.length();
+ }
+ public String next() {
+ int beg = pos;
+ int end = path.indexOf(File.pathSeparator, beg);
+ if (end == -1)
+ end = path.length();
+ pos = end + 1;
+
+ if (beg == end && emptyPathDefault != null)
+ return emptyPathDefault;
+ else
+ return path.substring(beg, end);
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ private class Path extends LinkedHashSet<File> {
+ private static final long serialVersionUID = 0;
+
+ private boolean expandJarClassPaths = false;
+ private Set<File> canonicalValues = new HashSet<File>();
+
+ public Path expandJarClassPaths(boolean x) {
+ expandJarClassPaths = x;
+ return this;
+ }
+
+ /** What to use when path element is the empty string */
+ private String emptyPathDefault = null;
+
+ public Path emptyPathDefault(String x) {
+ emptyPathDefault = x;
+ return this;
+ }
+
+ public Path() { super(); }
+
+ public Path addDirectories(String dirs, boolean warn) {
+ if (dirs != null)
+ for (String dir : new PathIterator(dirs))
+ addDirectory(dir, warn);
+ return this;
+ }
+
+ public Path addDirectories(String dirs) {
+ return addDirectories(dirs, warn);
+ }
+
+ private void addDirectory(String dir, boolean warn) {
+ if (! new File(dir).isDirectory()) {
+ if (warn)
+ log.warning("dir.path.element.not.found", dir);
+ return;
+ }
+
+ File[] files = new File(dir).listFiles();
+ if (files == null)
+ return;
+
+ for (File direntry : files) {
+ if (isArchive(direntry))
+ addFile(direntry, warn);
+ }
+ }
+
+ public Path addFiles(String files, boolean warn) {
+ if (files != null)
+ for (String file : new PathIterator(files, emptyPathDefault))
+ addFile(file, warn);
+ return this;
+ }
+
+ public Path addFiles(String files) {
+ return addFiles(files, warn);
+ }
+
+ public Path addFile(String file, boolean warn) {
+ addFile(new File(file), warn);
+ return this;
+ }
+
+ 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)) {
+ /* 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) {
+ /* No such file or directory exists */
+ if (warn)
+ log.warning("path.element.not.found", file);
+ } else if (pe.isFile) {
+ /* File is an ordinary file. */
+ if (!isArchive(file)) {
+ /* Not a recognized extension; open it to see if
+ it looks like a valid zip file. */
+ try {
+ ZipFile z = new ZipFile(file);
+ z.close();
+ if (warn)
+ log.warning("unexpected.archive.file", file);
+ } catch (IOException e) {
+ // FIXME: include e.getLocalizedMessage in warning
+ if (warn)
+ log.warning("invalid.archive.file", file);
+ return;
+ }
+ }
+ }
+
+ /* 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);
+
+ if (expandJarClassPaths && file.exists() && file.isFile())
+ addJarClassPath(file, warn);
+ }
+
+ // Adds referenced classpath elements from a jar's Class-Path
+ // Manifest entry. In some future release, we may want to
+ // update this code to recognize URLs rather than simple
+ // 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();
+ }
+ } catch (IOException e) {
+ log.error("error.reading.file", jarFile, e.getLocalizedMessage());
+ }
+ }
+ }
+
+ private Path computeBootClassPath() {
+ bootClassPathRtJar = null;
+ String optionValue;
+ Path path = new Path();
+
+ path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
+
+ if ((optionValue = options.get(ENDORSEDDIRS)) != null)
+ path.addDirectories(optionValue);
+ else
+ path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
+
+ if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
+ path.addFiles(optionValue);
+ } else {
+ // Standard system classes for this compiler's release.
+ String files = System.getProperty("sun.boot.class.path");
+ path.addFiles(files, false);
+ File rt_jar = new File("rt.jar");
+ for (String file : new PathIterator(files, null)) {
+ File f = new File(file);
+ if (new File(f.getName()).equals(rt_jar))
+ bootClassPathRtJar = f;
+ }
+ }
+
+ path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
+
+ // Strictly speaking, standard extensions are not bootstrap
+ // classes, but we treat them identically, so we'll pretend
+ // that they are.
+ if ((optionValue = options.get(EXTDIRS)) != null)
+ path.addDirectories(optionValue);
+ else
+ path.addDirectories(System.getProperty("java.ext.dirs"), false);
+
+ return path;
+ }
+
+ private Path computeUserClassPath() {
+ String cp = options.get(CLASSPATH);
+
+ // CLASSPATH environment variable when run from `javac'.
+ if (cp == null) cp = System.getProperty("env.class.path");
+
+ // If invoked via a java VM (not the javac launcher), use the
+ // platform class path
+ if (cp == null && System.getProperty("application.home") == null)
+ cp = System.getProperty("java.class.path");
+
+ // Default to current working directory.
+ if (cp == null) cp = ".";
+
+ return new Path()
+ .expandJarClassPaths(true) // Only search user jars for Class-Paths
+ .emptyPathDefault(".") // Empty path elt ==> current directory
+ .addFiles(cp);
+ }
+
+ private Path computeSourcePath() {
+ String sourcePathArg = options.get(SOURCEPATH);
+ if (sourcePathArg == null)
+ return null;
+
+ return new Path().addFiles(sourcePathArg);
+ }
+
+ private Path computeAnnotationProcessorPath() {
+ String processorPathArg = options.get(PROCESSORPATH);
+ if (processorPathArg == null)
+ return null;
+
+ return new Path().addFiles(processorPathArg);
+ }
+
+ /** The actual effective locations searched for sources */
+ private Path sourceSearchPath;
+
+ public Collection<File> sourceSearchPath() {
+ if (sourceSearchPath == null) {
+ lazy();
+ Path sourcePath = getPathForLocation(SOURCE_PATH);
+ Path userClassPath = getPathForLocation(CLASS_PATH);
+ sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
+ }
+ return Collections.unmodifiableCollection(sourceSearchPath);
+ }
+
+ /** The actual effective locations searched for classes */
+ private Path classSearchPath;
+
+ public Collection<File> classSearchPath() {
+ if (classSearchPath == null) {
+ lazy();
+ Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
+ Path userClassPath = getPathForLocation(CLASS_PATH);
+ classSearchPath = new Path();
+ classSearchPath.addAll(bootClassPath);
+ classSearchPath.addAll(userClassPath);
+ }
+ return Collections.unmodifiableCollection(classSearchPath);
+ }
+
+ /** The actual effective locations for non-source, non-class files */
+ private Path otherSearchPath;
+
+ Collection<File> otherSearchPath() {
+ if (otherSearchPath == null) {
+ lazy();
+ Path userClassPath = getPathForLocation(CLASS_PATH);
+ Path sourcePath = getPathForLocation(SOURCE_PATH);
+ if (sourcePath == null)
+ otherSearchPath = userClassPath;
+ else {
+ otherSearchPath = new Path();
+ otherSearchPath.addAll(userClassPath);
+ otherSearchPath.addAll(sourcePath);
+ }
+ }
+ return Collections.unmodifiableCollection(otherSearchPath);
+ }
+
+ /** Is this the name of an archive file? */
+ private static 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
+ && (n.endsWith(".jar") || n.endsWith(".zip"));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,1248 @@
+/*
+ * Copyright 2007-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.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+import java.util.zip.ZipException;
+
+/** This class implements building of index of a zip archive and access to it's context.
+ * It also uses prebuild index if available. It supports invocations where it will
+ * serialize an optimized zip index file to disk.
+ *
+ * In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
+ * when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
+ *
+ * Location where to look for/generate optimized zip index files can be provided using
+ * "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
+ * the value of the "java.io.tmpdir" system property.
+ *
+ * If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
+ * created for each archive, used by the compiler for compilation, at location,
+ * specified by "cachezipindexdir" option.
+ *
+ * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp
+ * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
+ * and the compiler uses the cached indexes.
+ */
+public class ZipFileIndex {
+ private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
+ private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
+
+ public final static long NOT_MODIFIED = Long.MIN_VALUE;
+
+ private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
+ private static ReentrantLock lock = new ReentrantLock();
+
+ private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
+
+ private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
+ private Set<String> allDirs = Collections.<String>emptySet();
+
+ // ZipFileIndex data entries
+ private File zipFile;
+ private long zipFileLastModified = NOT_MODIFIED;
+ private RandomAccessFile zipRandomFile;
+ private ZipFileIndexEntry[] entries;
+
+ private boolean readFromIndex = false;
+ private File zipIndexFile = null;
+ private boolean triedToReadIndex = false;
+ private int symbolFilePrefixLength = 0;
+ private boolean hasPopulatedData = false;
+ private long lastReferenceTimeStamp = NOT_MODIFIED;
+
+ private boolean usePreindexedCache = false;
+ private String preindexedCacheLocation = null;
+
+ private boolean writeIndex = false;
+
+ /**
+ * Returns a list of all ZipFileIndex entries
+ *
+ * @return A list of ZipFileIndex entries, or an empty list
+ */
+ public static List<ZipFileIndex> getZipFileIndexes() {
+ return getZipFileIndexes(false);
+ }
+
+ /**
+ * Returns a list of all ZipFileIndex entries
+ *
+ * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
+ * all ZipFileEntry(s) are included into the list.
+ * @return A list of ZipFileIndex entries, or an empty list
+ */
+ public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
+ List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
+ lock.lock();
+ try {
+ zipFileIndexes.addAll(zipFileIndexCache.values());
+
+ if (openedOnly) {
+ for(ZipFileIndex elem : zipFileIndexes) {
+ if (!elem.isOpen()) {
+ zipFileIndexes.remove(elem);
+ }
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ return zipFileIndexes;
+ }
+
+ public boolean isOpen() {
+ lock.lock();
+ try {
+ return zipRandomFile != null;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
+ ZipFileIndex zi = null;
+ lock.lock();
+ try {
+ zi = getExistingZipIndex(zipFile);
+
+ if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
+ zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
+ useCache, cacheLocation);
+ zipFileIndexCache.put(zipFile, zi);
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ return zi;
+ }
+
+ public static ZipFileIndex getExistingZipIndex(File zipFile) {
+ lock.lock();
+ try {
+ return zipFileIndexCache.get(zipFile);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public static void clearCache() {
+ lock.lock();
+ try {
+ zipFileIndexCache.clear();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public static void clearCache(long timeNotUsed) {
+ lock.lock();
+ try {
+ Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
+ while (cachedFileIterator.hasNext()) {
+ File cachedFile = cachedFileIterator.next();
+ ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
+ if (cachedZipIndex != null) {
+ long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
+ if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
+ System.currentTimeMillis() > timeToTest) {
+ zipFileIndexCache.remove(cachedFile);
+ }
+ }
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public static void removeFromCache(File file) {
+ lock.lock();
+ try {
+ zipFileIndexCache.remove(file);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ /** Sets already opened list of ZipFileIndexes from an outside client
+ * of the compiler. This functionality should be used in a non-batch clients of the compiler.
+ */
+ public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
+ lock.lock();
+ try {
+ if (zipFileIndexCache.isEmpty()) {
+ throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
+ }
+
+ for (ZipFileIndex zfi : indexes) {
+ zipFileIndexCache.put(zfi.zipFile, zfi);
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
+ boolean useCache, String cacheLocation) throws IOException {
+ this.zipFile = zipFile;
+ this.symbolFilePrefixLength = symbolFilePrefixLen;
+ this.writeIndex = writeIndex;
+ this.usePreindexedCache = useCache;
+ this.preindexedCacheLocation = cacheLocation;
+
+ if (zipFile != null) {
+ this.zipFileLastModified = zipFile.lastModified();
+ }
+
+ // Validate integrity of the zip file
+ checkIndex();
+ }
+
+ public String toString() {
+ return "ZipFileIndex of file:(" + zipFile + ")";
+ }
+
+ // Just in case...
+ protected void finalize() {
+ closeFile();
+ }
+
+ private boolean isUpToDate() {
+ if (zipFile != null &&
+ ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
+ hasPopulatedData) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
+ * if its the same as the one at the time the index was build we don't need to reopen anything.
+ */
+ private void checkIndex() throws IOException {
+ boolean isUpToDate = true;
+ if (!isUpToDate()) {
+ closeFile();
+ isUpToDate = false;
+ }
+
+ if (zipRandomFile != null || isUpToDate) {
+ lastReferenceTimeStamp = System.currentTimeMillis();
+ return;
+ }
+
+ hasPopulatedData = true;
+
+ if (readIndex()) {
+ lastReferenceTimeStamp = System.currentTimeMillis();
+ return;
+ }
+
+ directories = Collections.<String, DirectoryEntry>emptyMap();
+ allDirs = Collections.<String>emptySet();
+
+ try {
+ openFile();
+ long totalLength = zipRandomFile.length();
+ ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
+ directory.buildIndex();
+ } finally {
+ if (zipRandomFile != null) {
+ closeFile();
+ }
+ }
+
+ lastReferenceTimeStamp = System.currentTimeMillis();
+ }
+
+ private void openFile() throws FileNotFoundException {
+ if (zipRandomFile == null && zipFile != null) {
+ zipRandomFile = new RandomAccessFile(zipFile, "r");
+ }
+ }
+
+ private void cleanupState() {
+ // Make sure there is a valid but empty index if the file doesn't exist
+ entries = ZipFileIndexEntry.EMPTY_ARRAY;
+ directories = Collections.<String, DirectoryEntry>emptyMap();
+ zipFileLastModified = NOT_MODIFIED;
+ allDirs = Collections.<String>emptySet();
+ }
+
+ public void close() {
+ lock.lock();
+ try {
+ writeIndex();
+ closeFile();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ private void closeFile() {
+ if (zipRandomFile != null) {
+ try {
+ zipRandomFile.close();
+ } catch (IOException ex) {
+ }
+ zipRandomFile = null;
+ }
+ }
+
+ /**
+ * Returns the ZipFileIndexEntry for an absolute path, if there is one.
+ */
+ public ZipFileIndexEntry getZipIndexEntry(String path) {
+ if (File.separatorChar != '/') {
+ path = path.replace('/', File.separatorChar);
+ }
+ lock.lock();
+ try {
+ checkIndex();
+ String lookFor = "";
+ int lastSepIndex = path.lastIndexOf(File.separatorChar);
+ boolean noSeparator = false;
+ if (lastSepIndex == -1) {
+ noSeparator = true;
+ }
+
+ DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
+
+ lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
+
+ return de == null ? null : de.getEntry(lookFor);
+ }
+ catch (IOException e) {
+ return null;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
+ */
+ public com.sun.tools.javac.util.List<String> getFiles(String path) {
+ if (File.separatorChar != '/') {
+ path = path.replace('/', File.separatorChar);
+ }
+
+ lock.lock();
+ try {
+ checkIndex();
+
+ DirectoryEntry de = directories.get(path);
+ com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();
+
+ if (ret == null) {
+ return com.sun.tools.javac.util.List.<String>nil();
+ }
+ return ret;
+ }
+ catch (IOException e) {
+ return com.sun.tools.javac.util.List.<String>nil();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public List<String> getAllDirectories(String path) {
+
+ if (File.separatorChar != '/') {
+ path = path.replace('/', File.separatorChar);
+ }
+
+ lock.lock();
+ try {
+ checkIndex();
+ path = path.intern();
+
+ DirectoryEntry de = directories.get(path);
+ com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
+
+ if (ret == null) {
+ return com.sun.tools.javac.util.List.<String>nil();
+ }
+
+ return ret;
+ }
+ catch (IOException e) {
+ return com.sun.tools.javac.util.List.<String>nil();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public Set<String> getAllDirectories() {
+ lock.lock();
+ try {
+ checkIndex();
+ if (allDirs == Collections.EMPTY_SET) {
+ Set<String> alldirs = new HashSet<String>();
+ Iterator<String> dirsIter = directories.keySet().iterator();
+ while (dirsIter.hasNext()) {
+ alldirs.add(new String(dirsIter.next()));
+ }
+
+ allDirs = alldirs;
+ }
+
+ return allDirs;
+ }
+ catch (IOException e) {
+ return Collections.<String>emptySet();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Tests if a specific path exists in the zip. This method will return true
+ * for file entries and directories.
+ *
+ * @param path A path within the zip.
+ * @return True if the path is a file or dir, false otherwise.
+ */
+ public boolean contains(String path) {
+ lock.lock();
+ try {
+ checkIndex();
+ return getZipIndexEntry(path) != null;
+ }
+ catch (IOException e) {
+ return false;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean isDirectory(String path) throws IOException {
+ lock.lock();
+ try {
+ // The top level in a zip file is always a directory.
+ if (path.length() == 0) {
+ lastReferenceTimeStamp = System.currentTimeMillis();
+ return true;
+ }
+
+ if (File.separatorChar != '/')
+ path = path.replace('/', File.separatorChar);
+ checkIndex();
+ return directories.get(path) != null;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public long getLastModified(String path) throws IOException {
+ lock.lock();
+ try {
+ ZipFileIndexEntry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException();
+ return entry.getLastModified();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public int length(String path) throws IOException {
+ lock.lock();
+ try {
+ ZipFileIndexEntry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException();
+
+ if (entry.isDir) {
+ return 0;
+ }
+
+ byte[] header = getHeader(entry);
+ // entry is not compressed?
+ if (get2ByteLittleEndian(header, 8) == 0) {
+ return entry.compressedSize;
+ } else {
+ return entry.size;
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public byte[] read(String path) throws IOException {
+ lock.lock();
+ try {
+ ZipFileIndexEntry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
+ return read(entry);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public byte[] read(ZipFileIndexEntry entry) throws IOException {
+ lock.lock();
+ try {
+ openFile();
+ byte[] result = readBytes(entry);
+ closeFile();
+ return result;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public int read(String path, byte[] buffer) throws IOException {
+ lock.lock();
+ try {
+ ZipFileIndexEntry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException();
+ return read(entry, buffer);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public int read(ZipFileIndexEntry entry, byte[] buffer)
+ throws IOException {
+ lock.lock();
+ try {
+ int result = readBytes(entry, buffer);
+ return result;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ private byte[] readBytes(ZipFileIndexEntry entry) throws IOException {
+ byte[] header = getHeader(entry);
+ int csize = entry.compressedSize;
+ byte[] cbuf = new byte[csize];
+ zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+ zipRandomFile.readFully(cbuf, 0, csize);
+
+ // is this compressed - offset 8 in the ZipEntry header
+ if (get2ByteLittleEndian(header, 8) == 0)
+ return cbuf;
+
+ int size = entry.size;
+ byte[] buf = new byte[size];
+ if (inflate(cbuf, buf) != size)
+ throw new ZipException("corrupted zip file");
+
+ return buf;
+ }
+
+ /**
+ *
+ */
+ private int readBytes(ZipFileIndexEntry entry, byte[] buffer) throws IOException {
+ byte[] header = getHeader(entry);
+
+ // entry is not compressed?
+ if (get2ByteLittleEndian(header, 8) == 0) {
+ zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+ int offset = 0;
+ int size = buffer.length;
+ while (offset < size) {
+ int count = zipRandomFile.read(buffer, offset, size - offset);
+ if (count == -1)
+ break;
+ offset += count;
+ }
+ return entry.size;
+ }
+
+ int csize = entry.compressedSize;
+ byte[] cbuf = new byte[csize];
+ zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
+ zipRandomFile.readFully(cbuf, 0, csize);
+
+ int count = inflate(cbuf, buffer);
+ if (count == -1)
+ throw new ZipException("corrupted zip file");
+
+ return entry.size;
+ }
+
+ //----------------------------------------------------------------------------
+ // Zip utilities
+ //----------------------------------------------------------------------------
+
+ private byte[] getHeader(ZipFileIndexEntry entry) throws IOException {
+ zipRandomFile.seek(entry.offset);
+ byte[] header = new byte[30];
+ zipRandomFile.readFully(header);
+ if (get4ByteLittleEndian(header, 0) != 0x04034b50)
+ throw new ZipException("corrupted zip file");
+ if ((get2ByteLittleEndian(header, 6) & 1) != 0)
+ throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
+ return header;
+ }
+
+ /*
+ * Inflate using the java.util.zip.Inflater class
+ */
+ private static Inflater inflater;
+ private int inflate(byte[] src, byte[] dest) {
+
+ // construct the inflater object or reuse an existing one
+ if (inflater == null)
+ inflater = new Inflater(true);
+
+ synchronized (inflater) {
+ inflater.reset();
+ inflater.setInput(src);
+ try {
+ return inflater.inflate(dest);
+ } catch (DataFormatException ex) {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
+ * endian format.
+ */
+ private static int get2ByteLittleEndian(byte[] buf, int pos) {
+ return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
+ }
+
+ /**
+ * return the 4 bytes buf[i..i+3] as an integer in little endian format.
+ */
+ private static int get4ByteLittleEndian(byte[] buf, int pos) {
+ return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
+ ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
+ }
+
+ /* ----------------------------------------------------------------------------
+ * ZipDirectory
+ * ----------------------------------------------------------------------------*/
+
+ private class ZipDirectory {
+ private String lastDir;
+ private int lastStart;
+ private int lastLen;
+
+ byte[] zipDir;
+ RandomAccessFile zipRandomFile = null;
+ ZipFileIndex zipFileIndex = null;
+
+ public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
+ this.zipRandomFile = zipRandomFile;
+ this.zipFileIndex = index;
+
+ findCENRecord(start, end);
+ }
+
+ /*
+ * Reads zip file central directory.
+ * For more details see readCEN in zip_util.c from the JDK sources.
+ * This is a Java port of that function.
+ */
+ private void findCENRecord(long start, long end) throws IOException {
+ long totalLength = end - start;
+ int endbuflen = 1024;
+ byte[] endbuf = new byte[endbuflen];
+ long endbufend = end - start;
+
+ // There is a variable-length field after the dir offset record. We need to do consequential search.
+ while (endbufend >= 22) {
+ if (endbufend < endbuflen)
+ endbuflen = (int)endbufend;
+ long endbufpos = endbufend - endbuflen;
+ zipRandomFile.seek(start + endbufpos);
+ zipRandomFile.readFully(endbuf, 0, endbuflen);
+ int i = endbuflen - 22;
+ while (i >= 0 &&
+ !(endbuf[i] == 0x50 &&
+ endbuf[i + 1] == 0x4b &&
+ endbuf[i + 2] == 0x05 &&
+ endbuf[i + 3] == 0x06 &&
+ endbufpos + i + 22 +
+ get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
+ i--;
+ }
+
+ if (i >= 0) {
+ zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
+ zipDir[0] = endbuf[i + 10];
+ zipDir[1] = endbuf[i + 11];
+ zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
+ zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
+ return;
+ } else {
+ endbufend = endbufpos + 21;
+ }
+ }
+ throw new ZipException("cannot read zip file");
+ }
+ private void buildIndex() throws IOException {
+ int entryCount = get2ByteLittleEndian(zipDir, 0);
+
+ entries = new ZipFileIndexEntry[entryCount];
+ // Add each of the files
+ if (entryCount > 0) {
+ directories = new HashMap<String, DirectoryEntry>();
+ ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
+ int pos = 2;
+ for (int i = 0; i < entryCount; i++) {
+ pos = readEntry(pos, entryList, directories);
+ }
+
+ // Add the accumulated dirs into the same list
+ Iterator i = directories.keySet().iterator();
+ while (i.hasNext()) {
+ ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
+ zipFileIndexEntry.isDir = true;
+ entryList.add(zipFileIndexEntry);
+ }
+
+ entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
+ Arrays.sort(entries);
+ } else {
+ cleanupState();
+ }
+ }
+
+ private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
+ Map<String, DirectoryEntry> directories) throws IOException {
+ if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
+ throw new ZipException("cannot read zip file entry");
+ }
+
+ int dirStart = pos + 46;
+ int fileStart = dirStart;
+ int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
+
+ if (zipFileIndex.symbolFilePrefixLength != 0 &&
+ ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
+ dirStart += zipFileIndex.symbolFilePrefixLength;
+ fileStart += zipFileIndex.symbolFilePrefixLength;
+ }
+
+ // Use the OS's path separator. Keep the position of the last one.
+ for (int index = fileStart; index < fileEnd; index++) {
+ byte nextByte = zipDir[index];
+ if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
+ zipDir[index] = (byte)File.separatorChar;
+ fileStart = index + 1;
+ }
+ }
+
+ String directory = null;
+ if (fileStart == dirStart)
+ directory = "";
+ else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
+ int index = lastLen - 1;
+ while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
+ if (index == 0) {
+ directory = lastDir;
+ break;
+ }
+ index--;
+ }
+ }
+
+ // Sub directories
+ if (directory == null) {
+ lastStart = dirStart;
+ lastLen = fileStart - dirStart - 1;
+
+ directory = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
+ lastDir = directory;
+
+ // Enter also all the parent directories
+ String tempDirectory = directory;
+
+ while (directories.get(tempDirectory) == null) {
+ directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
+ int separator = tempDirectory.lastIndexOf(File.separatorChar);
+ if (separator == -1)
+ break;
+ tempDirectory = tempDirectory.substring(0, separator);
+ }
+ }
+ else {
+ directory = directory.intern();
+ if (directories.get(directory) == null) {
+ directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
+ }
+ }
+
+ // For each dir create also a file
+ if (fileStart != fileEnd) {
+ ZipFileIndexEntry entry = new ZipFileIndexEntry(directory,
+ new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
+
+ entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
+ entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
+ entry.size = get4ByteLittleEndian(zipDir, pos + 24);
+ entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
+ entryList.add(entry);
+ }
+
+ return pos + 46 +
+ get2ByteLittleEndian(zipDir, pos + 28) +
+ get2ByteLittleEndian(zipDir, pos + 30) +
+ get2ByteLittleEndian(zipDir, pos + 32);
+ }
+ }
+
+ /**
+ * Returns the last modified timestamp of a zip file.
+ * @return long
+ */
+ public long getZipFileLastModified() throws IOException {
+ lock.lock();
+ try {
+ checkIndex();
+ return zipFileLastModified;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ /** ------------------------------------------------------------------------
+ * DirectoryEntry class
+ * -------------------------------------------------------------------------*/
+ static class DirectoryEntry {
+ private boolean filesInited;
+ private boolean directoriesInited;
+ private boolean zipFileEntriesInited;
+ private boolean entriesInited;
+
+ private long writtenOffsetOffset = 0;
+
+ private String dirName;
+
+ private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
+ private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
+ private com.sun.tools.javac.util.List<ZipFileIndexEntry> zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
+
+ private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
+
+ private ZipFileIndex zipFileIndex;
+
+ private int numEntries;
+
+ DirectoryEntry(String dirName, ZipFileIndex index) {
+ filesInited = false;
+ directoriesInited = false;
+ entriesInited = false;
+
+ if (File.separatorChar == '/') {
+ dirName.replace('\\', '/');
+ }
+ else {
+ dirName.replace('/', '\\');
+ }
+
+ this.dirName = dirName.intern();
+ this.zipFileIndex = index;
+ }
+
+ private com.sun.tools.javac.util.List<String> getFiles() {
+ if (filesInited) {
+ return zipFileEntriesFiles;
+ }
+
+ initEntries();
+
+ for (ZipFileIndexEntry e : entries) {
+ if (!e.isDir) {
+ zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
+ }
+ }
+ filesInited = true;
+ return zipFileEntriesFiles;
+ }
+
+ private com.sun.tools.javac.util.List<String> getDirectories() {
+ if (directoriesInited) {
+ return zipFileEntriesFiles;
+ }
+
+ initEntries();
+
+ for (ZipFileIndexEntry e : entries) {
+ if (e.isDir) {
+ zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
+ }
+ }
+
+ directoriesInited = true;
+
+ return zipFileEntriesDirectories;
+ }
+
+ private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
+ if (zipFileEntriesInited) {
+ return zipFileEntries;
+ }
+
+ initEntries();
+
+ zipFileEntries = com.sun.tools.javac.util.List.nil();
+ for (ZipFileIndexEntry zfie : entries) {
+ zipFileEntries = zipFileEntries.append(zfie);
+ }
+
+ zipFileEntriesInited = true;
+
+ return zipFileEntries;
+ }
+
+ private ZipFileIndexEntry getEntry(String rootName) {
+ initEntries();
+ int index = Collections.binarySearch(entries, new ZipFileIndexEntry(dirName, rootName));
+ if (index < 0) {
+ return null;
+ }
+
+ return entries.get(index);
+ }
+
+ private void initEntries() {
+ if (entriesInited) {
+ return;
+ }
+
+ if (!zipFileIndex.readFromIndex) {
+ int from = -Arrays.binarySearch(zipFileIndex.entries,
+ new ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
+ int to = -Arrays.binarySearch(zipFileIndex.entries,
+ new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
+
+ boolean emptyList = false;
+
+ for (int i = from; i < to; i++) {
+ entries.add(zipFileIndex.entries[i]);
+ }
+ } else {
+ File indexFile = zipFileIndex.getIndexFile();
+ if (indexFile != null) {
+ RandomAccessFile raf = null;
+ try {
+ raf = new RandomAccessFile(indexFile, "r");
+ raf.seek(writtenOffsetOffset);
+
+ for (int nFiles = 0; nFiles < numEntries; nFiles++) {
+ // Read the name bytes
+ int zfieNameBytesLen = raf.readInt();
+ byte [] zfieNameBytes = new byte[zfieNameBytesLen];
+ raf.read(zfieNameBytes);
+ String eName = new String(zfieNameBytes, "UTF-8");
+
+ // Read isDir
+ boolean eIsDir = raf.readByte() == (byte)0 ? false : true;
+
+ // Read offset of bytes in the real Jar/Zip file
+ int eOffset = raf.readInt();
+
+ // Read size of the file in the real Jar/Zip file
+ int eSize = raf.readInt();
+
+ // Read compressed size of the file in the real Jar/Zip file
+ int eCsize = raf.readInt();
+
+ // Read java time stamp of the file in the real Jar/Zip file
+ long eJavaTimestamp = raf.readLong();
+
+ ZipFileIndexEntry rfie = new ZipFileIndexEntry(dirName, eName);
+ rfie.isDir = eIsDir;
+ rfie.offset = eOffset;
+ rfie.size = eSize;
+ rfie.compressedSize = eCsize;
+ rfie.javatime = eJavaTimestamp;
+ entries.add(rfie);
+ }
+ } catch (Throwable t) {
+ // Do nothing
+ } finally {
+ try {
+ if (raf == null) {
+ raf.close();
+ }
+ } catch (Throwable t) {
+ // Do nothing
+ }
+ }
+ }
+ }
+
+ entriesInited = true;
+ }
+
+ List<ZipFileIndexEntry> getEntriesAsCollection() {
+ initEntries();
+
+ return entries;
+ }
+ }
+
+ private boolean readIndex() {
+ if (triedToReadIndex || !usePreindexedCache) {
+ return false;
+ }
+
+ boolean ret = false;
+ lock.lock();
+ try {
+ triedToReadIndex = true;
+ RandomAccessFile raf = null;
+ try {
+ File indexFileName = getIndexFile();
+ raf = new RandomAccessFile(indexFileName, "r");
+
+ long fileStamp = raf.readLong();
+ if (zipFile.lastModified() != fileStamp) {
+ ret = false;
+ } else {
+ directories = new HashMap<String, DirectoryEntry>();
+ int numDirs = raf.readInt();
+ for (int nDirs = 0; nDirs < numDirs; nDirs++) {
+ int dirNameBytesLen = raf.readInt();
+ byte [] dirNameBytes = new byte[dirNameBytesLen];
+ raf.read(dirNameBytes);
+
+ String dirNameStr = new String(dirNameBytes, "UTF-8");
+ DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
+ de.numEntries = raf.readInt();
+ de.writtenOffsetOffset = raf.readLong();
+ directories.put(dirNameStr, de);
+ }
+ ret = true;
+ zipFileLastModified = fileStamp;
+ }
+ } catch (Throwable t) {
+ // Do nothing
+ } finally {
+ if (raf != null) {
+ try {
+ raf.close();
+ } catch (Throwable tt) {
+ // Do nothing
+ }
+ }
+ }
+ if (ret == true) {
+ readFromIndex = true;
+ }
+ }
+ finally {
+ lock.unlock();
+ }
+
+ return ret;
+ }
+
+ private boolean writeIndex() {
+ boolean ret = false;
+ if (readFromIndex || !usePreindexedCache) {
+ return true;
+ }
+
+ if (!writeIndex) {
+ return true;
+ }
+
+ File indexFile = getIndexFile();
+ if (indexFile == null) {
+ return false;
+ }
+
+ RandomAccessFile raf = null;
+ long writtenSoFar = 0;
+ try {
+ raf = new RandomAccessFile(indexFile, "rw");
+
+ raf.writeLong(zipFileLastModified);
+ writtenSoFar += 8;
+
+
+ Iterator<String> iterDirName = directories.keySet().iterator();
+ List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
+ Map<String, Long> offsets = new HashMap<String, Long>();
+ raf.writeInt(directories.keySet().size());
+ writtenSoFar += 4;
+
+ while(iterDirName.hasNext()) {
+ String dirName = iterDirName.next();
+ DirectoryEntry dirEntry = directories.get(dirName);
+
+ directoriesToWrite.add(dirEntry);
+
+ // Write the dir name bytes
+ byte [] dirNameBytes = dirName.getBytes("UTF-8");
+ int dirNameBytesLen = dirNameBytes.length;
+ raf.writeInt(dirNameBytesLen);
+ writtenSoFar += 4;
+
+ raf.write(dirNameBytes);
+ writtenSoFar += dirNameBytesLen;
+
+ // Write the number of files in the dir
+ List dirEntries = dirEntry.getEntriesAsCollection();
+ raf.writeInt(dirEntries.size());
+ writtenSoFar += 4;
+
+ offsets.put(dirName, new Long(writtenSoFar));
+
+ // Write the offset of the file's data in the dir
+ dirEntry.writtenOffsetOffset = 0L;
+ raf.writeLong(0L);
+ writtenSoFar += 8;
+ }
+
+ for (DirectoryEntry de : directoriesToWrite) {
+ // Fix up the offset in the directory table
+ long currFP = raf.getFilePointer();
+
+ long offsetOffset = offsets.get(de.dirName).longValue();
+ raf.seek(offsetOffset);
+ raf.writeLong(writtenSoFar);
+
+ raf.seek(currFP);
+
+ // Now write each of the files in the DirectoryEntry
+ List<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
+ for (ZipFileIndexEntry zfie : entries) {
+ // Write the name bytes
+ byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
+ int zfieNameBytesLen = zfieNameBytes.length;
+ raf.writeInt(zfieNameBytesLen);
+ writtenSoFar += 4;
+ raf.write(zfieNameBytes);
+ writtenSoFar += zfieNameBytesLen;
+
+ // Write isDir
+ raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
+ writtenSoFar += 1;
+
+ // Write offset of bytes in the real Jar/Zip file
+ raf.writeInt(zfie.offset);
+ writtenSoFar += 4;
+
+ // Write size of the file in the real Jar/Zip file
+ raf.writeInt(zfie.size);
+ writtenSoFar += 4;
+
+ // Write compressed size of the file in the real Jar/Zip file
+ raf.writeInt(zfie.compressedSize);
+ writtenSoFar += 4;
+
+ // Write java time stamp of the file in the real Jar/Zip file
+ raf.writeLong(zfie.getLastModified());
+ writtenSoFar += 8;
+ }
+ }
+ } catch (Throwable t) {
+ // Do nothing
+ } finally {
+ try {
+ if (raf != null) {
+ raf.close();
+ }
+ } catch(IOException ioe) {
+ // Do nothing
+ }
+ }
+
+ return ret;
+ }
+
+ public boolean writeZipIndex() {
+ lock.lock();
+ try {
+ return writeIndex();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ private File getIndexFile() {
+ if (zipIndexFile == null) {
+ if (zipFile == null) {
+ return null;
+ }
+
+ zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
+ zipFile.getName() + ".index");
+ }
+
+ return zipIndexFile;
+ }
+
+ public File getZipFile() {
+ return zipFile;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexEntry.java Mon Jun 16 22:23:33 2008 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2007-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;
+
+public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
+ public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
+
+ // Directory related
+ String dir;
+ boolean isDir;
+
+ // File related
+ String name;
+
+ int offset;
+ int size;
+ int compressedSize;
+ long javatime;
+
+ private int nativetime;
+
+ public ZipFileIndexEntry(String path) {
+ int separator = path.lastIndexOf(File.separatorChar);
+ if (separator == -1) {
+ dir = "".intern();
+ name = path;
+ } else {
+ dir = path.substring(0, separator).intern();
+ name = path.substring(separator + 1);
+ }
+ }
+
+ public ZipFileIndexEntry(String directory, String name) {
+ this.dir = directory.intern();
+ this.name = name;
+ }
+
+ public String getName() {
+ if (dir == null || dir.length() == 0) {
+ return name;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(dir);
+ sb.append(File.separatorChar);
+ sb.append(name);
+ return sb.toString();
+ }
+
+ public String getFileName() {
+ return name;
+ }
+
+ public long getLastModified() {
+ if (javatime == 0) {
+ javatime = dosToJavaTime(nativetime);
+ }
+ return javatime;
+ }
+
+ // From java.util.zip
+ private static long dosToJavaTime(int nativetime) {
+ // Bootstrap build problems prevent me from using the code directly
+ // Convert the raw/native time to a long for now
+ return (long)nativetime;
+ }
+
+ void setNativeTime(int natTime) {
+ nativetime = natTime;
+ }
+
+ public boolean isDirectory() {
+ return isDir;
+ }
+
+ public int compareTo(ZipFileIndexEntry other) {
+ String otherD = other.dir;
+ if (dir != otherD) {
+ int c = dir.compareTo(otherD);
+ if (c != 0)
+ return c;
+ }
+ return name.compareTo(other.name);
+ }
+
+
+ public String toString() {
+ return isDir ? ("Dir:" + dir + " : " + name) :
+ (dir + ":" + name);
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Jun 16 22:23:33 2008 -0700
@@ -42,6 +42,7 @@
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Jun 16 22:23:33 2008 -0700
@@ -40,6 +40,7 @@
import javax.tools.JavaFileObject;
import javax.tools.DiagnosticListener;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Mon Jun 16 22:23:33 2008 -0700
@@ -25,13 +25,13 @@
package com.sun.tools.javac.main;
-import com.sun.tools.javac.util.Options;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.MissingResourceException;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.JavacOption.Option;
import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Mon Jun 16 22:23:33 2008 -0700
@@ -25,16 +25,12 @@
package com.sun.tools.javac.parser;
-import java.io.*;
import java.nio.*;
-import java.nio.ByteBuffer;
-import java.nio.charset.*;
-import java.nio.channels.*;
-import java.util.regex.*;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.code.Source;
import static com.sun.tools.javac.parser.Token.*;
import static com.sun.tools.javac.util.LayoutCharacters.*;
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Jun 16 22:23:33 2008 -0700
@@ -25,22 +25,17 @@
package com.sun.tools.javac.processing;
-import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.*;
-import com.sun.tools.javac.jvm.*;
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.parser.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.model.JavacTypes;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.main.JavaCompiler;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.*;
+
+import java.net.URL;
+import java.io.Closeable;
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.net.MalformedURLException;
import java.io.StringWriter;
import javax.annotation.processing.*;
@@ -50,24 +45,34 @@
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.util.*;
-
import javax.tools.JavaFileManager;
import javax.tools.StandardJavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.DiagnosticListener;
-import static javax.tools.StandardLocation.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.regex.*;
-import java.net.URLClassLoader;
-import java.net.URL;
-import java.io.Closeable;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.file.Paths;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.jvm.*;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.parser.*;
+import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.util.Abort;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Options;
+
+import static javax.tools.StandardLocation.*;
/**
* Objects of this class hold and manage the state needed to support
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileObject.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright 2005-2006 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.util;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.CharsetDecoder;
-import javax.lang.model.element.Modifier;
-import javax.lang.model.element.NestingKind;
-import javax.tools.JavaFileObject;
-
-import static javax.tools.JavaFileObject.Kind.*;
-
-public abstract class BaseFileObject implements JavaFileObject {
-
- public JavaFileObject.Kind getKind() {
- String n = getName();
- if (n.endsWith(CLASS.extension))
- return CLASS;
- else if (n.endsWith(SOURCE.extension))
- return SOURCE;
- else if (n.endsWith(HTML.extension))
- return HTML;
- else
- return OTHER;
- }
-
- @Override
- public String toString() {
- return getPath();
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getPath() {
- return getName();
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- abstract public String getName();
-
- public NestingKind getNestingKind() { return null; }
-
- public Modifier getAccessLevel() { return null; }
-
- public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
- return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors));
- }
-
- protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
- throw new UnsupportedOperationException();
- }
-
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Mon Jun 16 22:23:33 2008 -0700
@@ -27,6 +27,7 @@
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Mon Jun 16 22:23:33 2008 -0700
@@ -25,17 +25,13 @@
package com.sun.tools.javac.util;
-import java.net.URI;
-import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import javax.tools.Diagnostic;
-import javax.tools.FileObject;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JavacFileManager.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1715 +0,0 @@
-/*
- * Copyright 2005-2006 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.util;
-
-import com.sun.tools.javac.main.JavacOption;
-import com.sun.tools.javac.main.OptionName;
-import com.sun.tools.javac.main.RecognizedOptions;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.ref.SoftReference;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.lang.model.SourceVersion;
-import javax.tools.FileObject;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.code.Source;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.tools.StandardJavaFileManager;
-
-import com.sun.tools.javac.zip.*;
-import java.io.ByteArrayInputStream;
-
-import static com.sun.tools.javac.main.OptionName.*;
-import static javax.tools.StandardLocation.*;
-
-/**
- * This class provides access to the source, class and other files
- * used by the compiler and related tools.
- */
-public class JavacFileManager implements StandardJavaFileManager {
-
- private static final String[] symbolFileLocation = { "lib", "ct.sym" };
- private static final String symbolFilePrefix = "META-INF/sym/rt.jar/";
-
- boolean useZipFileIndex;
-
- private static int symbolFilePrefixLength = 0;
- static {
- try {
- symbolFilePrefixLength = symbolFilePrefix.getBytes("UTF-8").length;
- } catch (java.io.UnsupportedEncodingException uee) {
- // Can't happen...UTF-8 is always supported.
- }
- }
-
- 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();
- else
- return buffer.toString().toCharArray();
- }
-
- /**
- * The log to be used for error reporting.
- */
- protected Log log;
-
- /** Encapsulates knowledge of paths
- */
- private Paths paths;
-
- private Options options;
-
- private final File uninited = new File("U N I N I T E D");
-
- private final Set<JavaFileObject.Kind> sourceOrClass =
- EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS);
-
- /** The standard output directory, primarily used for classes.
- * Initialized by the "-d" option.
- * If classOutDir = null, files are written into same directory as the sources
- * they were generated from.
- */
- private File classOutDir = uninited;
-
- /** The output directory, used when generating sources while processing annotations.
- * Initialized by the "-s" option.
- */
- private File sourceOutDir = uninited;
-
- protected boolean mmappedIO;
- protected boolean ignoreSymbolFile;
-
- /**
- * User provided charset (through javax.tools).
- */
- protected Charset charset;
-
- /**
- * Register a Context.Factory to create a JavacFileManager.
- */
- public static void preRegister(final Context context) {
- context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
- public JavaFileManager make() {
- return new JavacFileManager(context, true, null);
- }
- });
- }
-
- /**
- * Create a JavacFileManager using a given context, optionally registering
- * it as the JavaFileManager for that context.
- */
- public JavacFileManager(Context context, boolean register, Charset charset) {
- if (register)
- context.put(JavaFileManager.class, this);
- byteBufferCache = new ByteBufferCache();
- this.charset = charset;
- setContext(context);
- }
-
- /**
- * Set the context for JavacFileManager.
- */
- public void setContext(Context context) {
- log = Log.instance(context);
- if (paths == null) {
- paths = Paths.instance(context);
- } else {
- // Reuse the Paths object as it stores the locations that
- // have been set with setLocation, etc.
- paths.setContext(context);
- }
-
- options = Options.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;
- }
-
- public JavaFileObject getFileForInput(String name) {
- return getRegularFile(new File(name));
- }
-
- public JavaFileObject getRegularFile(File file) {
- return new RegularFileObject(file);
- }
-
- public JavaFileObject getFileForOutput(String classname,
- JavaFileObject.Kind kind,
- JavaFileObject sibling)
- throws IOException
- {
- return getJavaFileForOutput(CLASS_OUTPUT, classname, kind, sibling);
- }
-
- public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
- ListBuffer<File> files = new ListBuffer<File>();
- for (String name : names)
- files.append(new File(nullCheck(name)));
- return getJavaFileObjectsFromFiles(files.toList());
- }
-
- public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
- return getJavaFileObjectsFromStrings(Arrays.asList(nullCheck(names)));
- }
-
- protected JavaFileObject.Kind getKind(String extension) {
- if (extension.equals(JavaFileObject.Kind.CLASS.extension))
- return JavaFileObject.Kind.CLASS;
- else if (extension.equals(JavaFileObject.Kind.SOURCE.extension))
- return JavaFileObject.Kind.SOURCE;
- else if (extension.equals(JavaFileObject.Kind.HTML.extension))
- return JavaFileObject.Kind.HTML;
- else
- return JavaFileObject.Kind.OTHER;
- }
-
- private static boolean isValidName(String name) {
- // Arguably, isValidName should reject keywords (such as in SourceVersion.isName() ),
- // but the set of keywords depends on the source level, and we don't want
- // impls of JavaFileManager to have to be dependent on the source level.
- // Therefore we simply check that the argument is a sequence of identifiers
- // separated by ".".
- for (String s : name.split("\\.", -1)) {
- if (!SourceVersion.isIdentifier(s))
- return false;
- }
- return true;
- }
-
- private static void validateClassName(String className) {
- if (!isValidName(className))
- throw new IllegalArgumentException("Invalid class name: " + className);
- }
-
- private static void validatePackageName(String packageName) {
- if (packageName.length() > 0 && !isValidName(packageName))
- throw new IllegalArgumentException("Invalid packageName name: " + packageName);
- }
-
- public static void testName(String name,
- boolean isValidPackageName,
- boolean isValidClassName)
- {
- try {
- validatePackageName(name);
- if (!isValidPackageName)
- throw new AssertionError("Invalid package name accepted: " + name);
- printAscii("Valid package name: \"%s\"", name);
- } catch (IllegalArgumentException e) {
- if (isValidPackageName)
- throw new AssertionError("Valid package name rejected: " + name);
- printAscii("Invalid package name: \"%s\"", name);
- }
- try {
- validateClassName(name);
- if (!isValidClassName)
- throw new AssertionError("Invalid class name accepted: " + name);
- printAscii("Valid class name: \"%s\"", name);
- } catch (IllegalArgumentException e) {
- if (isValidClassName)
- throw new AssertionError("Valid class name rejected: " + name);
- printAscii("Invalid class name: \"%s\"", name);
- }
- }
- private static void printAscii(String format, Object... args) {
- String message;
- try {
- final String ascii = "US-ASCII";
- message = new String(String.format(null, format, args).getBytes(ascii), ascii);
- } catch (java.io.UnsupportedEncodingException ex) {
- throw new AssertionError(ex);
- }
- System.out.println(message);
- }
-
- /** Return external representation of name,
- * converting '.' to File.separatorChar.
- */
- private static String externalizeFileName(CharSequence name) {
- return name.toString().replace('.', File.separatorChar);
- }
-
- private static String externalizeFileName(CharSequence n, JavaFileObject.Kind kind) {
- return externalizeFileName(n) + kind.extension;
- }
-
- private static String baseName(String fileName) {
- return fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
- }
-
- /**
- * Insert all files in subdirectory `subdirectory' of `directory' which end
- * in one of the extensions in `extensions' into packageSym.
- */
- private void listDirectory(File directory,
- String subdirectory,
- Set<JavaFileObject.Kind> fileKinds,
- boolean recurse,
- 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();
- }
-
- if (archive != null || isFile) {
- if (archive == null) {
- try {
- archive = openArchive(directory);
- } catch (IOException ex) {
- log.error("error.reading.file",
- directory, ex.getLocalizedMessage());
- return;
- }
- }
- if (subdirectory.length() != 0) {
- if (!useZipFileIndex) {
- subdirectory = subdirectory.replace('\\', '/');
- if (!subdirectory.endsWith("/")) subdirectory = subdirectory + "/";
- }
- else {
- if (File.separatorChar == '/') {
- subdirectory = subdirectory.replace('\\', '/');
- }
- else {
- subdirectory = subdirectory.replace('/', '\\');
- }
-
- if (!subdirectory.endsWith(File.separator)) subdirectory = subdirectory + File.separator;
- }
- }
-
- List<String> files = archive.getFiles(subdirectory);
- if (files != null) {
- for (String file; !files.isEmpty(); files = files.tail) {
- file = files.head;
- if (isValidFile(file, fileKinds)) {
- l.append(archive.getFileObject(subdirectory, file));
- }
- }
- }
- if (recurse) {
- for (String s: archive.getSubdirectories()) {
- if (s.startsWith(subdirectory) && !s.equals(subdirectory)) {
- // Because the archive map is a flat list of directories,
- // the enclosing loop will pick up all child subdirectories.
- // Therefore, there is no need to recurse deeper.
- listDirectory(directory, s, fileKinds, false, l);
- }
- }
- }
- } else {
- File d = subdirectory.length() != 0
- ? new File(directory, subdirectory)
- : directory;
- if (!caseMapCheck(d, subdirectory))
- return;
-
- File[] files = d.listFiles();
- if (files == null)
- return;
-
- for (File f: files) {
- String fname = f.getName();
- if (f.isDirectory()) {
- if (recurse && SourceVersion.isIdentifier(fname)) {
- listDirectory(directory,
- subdirectory + File.separator + fname,
- fileKinds,
- recurse,
- l);
- }
- } else {
- if (isValidFile(fname, fileKinds)) {
- JavaFileObject fe =
- new RegularFileObject(fname, new File(d, fname));
- l.append(fe);
- }
- }
- }
- }
- }
-
- private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
- int lastDot = s.lastIndexOf(".");
- String extn = (lastDot == -1 ? s : s.substring(lastDot));
- JavaFileObject.Kind kind = getKind(extn);
- return fileKinds.contains(kind);
- }
-
- private static final boolean fileSystemIsCaseSensitive =
- File.separatorChar == '/';
-
- /** Hack to make Windows case sensitive. Test whether given path
- * ends in a string of characters with the same case as given name.
- * Ignore file separators in both path and name.
- */
- private boolean caseMapCheck(File f, String name) {
- if (fileSystemIsCaseSensitive) return true;
- // Note that getCanonicalPath() returns the case-sensitive
- // spelled file name.
- String path;
- try {
- path = f.getCanonicalPath();
- } catch (IOException ex) {
- return false;
- }
- char[] pcs = path.toCharArray();
- char[] ncs = name.toCharArray();
- int i = pcs.length - 1;
- int j = ncs.length - 1;
- while (i >= 0 && j >= 0) {
- while (i >= 0 && pcs[i] == File.separatorChar) i--;
- while (j >= 0 && ncs[j] == File.separatorChar) j--;
- if (i >= 0 && j >= 0) {
- if (pcs[i] != ncs[j]) return false;
- i--;
- j--;
- }
- }
- return j < 0;
- }
-
- /**
- * An archive provides a flat directory structure of a ZipFile by
- * mapping directory names to lists of files (basenames).
- */
- public interface Archive {
- void close() throws IOException;
-
- boolean contains(String name);
-
- JavaFileObject getFileObject(String subdirectory, String file);
-
- List<String> getFiles(String subdirectory);
-
- Set<String> getSubdirectories();
- }
-
- public class ZipArchive implements Archive {
- protected final Map<String,List<String>> map;
- protected final ZipFile zdir;
- public ZipArchive(ZipFile zdir) throws IOException {
- this.zdir = zdir;
- this.map = new HashMap<String,List<String>>();
- for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
- ZipEntry entry;
- try {
- entry = e.nextElement();
- } catch (InternalError ex) {
- IOException io = new IOException();
- io.initCause(ex); // convenience constructors added in Mustang :-(
- throw io;
- }
- addZipEntry(entry);
- }
- }
-
- void addZipEntry(ZipEntry entry) {
- String name = entry.getName();
- int i = name.lastIndexOf('/');
- String dirname = name.substring(0, i+1);
- String basename = name.substring(i+1);
- if (basename.length() == 0)
- return;
- List<String> list = map.get(dirname);
- if (list == null)
- list = List.nil();
- list = list.prepend(basename);
- map.put(dirname, list);
- }
-
- public boolean contains(String name) {
- int i = name.lastIndexOf('/');
- String dirname = name.substring(0, i+1);
- String basename = name.substring(i+1);
- if (basename.length() == 0)
- return false;
- List<String> list = map.get(dirname);
- return (list != null && list.contains(basename));
- }
-
- public List<String> getFiles(String subdirectory) {
- return map.get(subdirectory);
- }
-
- public JavaFileObject getFileObject(String subdirectory, String file) {
- ZipEntry ze = zdir.getEntry(subdirectory + file);
- return new ZipFileObject(file, zdir, ze);
- }
-
- public Set<String> getSubdirectories() {
- return map.keySet();
- }
-
- public void close() throws IOException {
- zdir.close();
- }
- }
-
- public class SymbolArchive extends ZipArchive {
- final File origFile;
- public SymbolArchive(File orig, ZipFile zdir) throws IOException {
- super(zdir);
- this.origFile = orig;
- }
-
- @Override
- void addZipEntry(ZipEntry entry) {
- // called from super constructor, may not refer to origFile.
- String name = entry.getName();
- if (!name.startsWith(symbolFilePrefix))
- return;
- name = name.substring(symbolFilePrefix.length());
- int i = name.lastIndexOf('/');
- String dirname = name.substring(0, i+1);
- String basename = name.substring(i+1);
- if (basename.length() == 0)
- return;
- List<String> list = map.get(dirname);
- if (list == null)
- list = List.nil();
- list = list.prepend(basename);
- map.put(dirname, list);
- }
-
- @Override
- public JavaFileObject getFileObject(String subdirectory, String file) {
- return super.getFileObject(symbolFilePrefix + subdirectory, file);
- }
- }
-
- public class MissingArchive implements Archive {
- final File zipFileName;
- public MissingArchive(File name) {
- zipFileName = name;
- }
- public boolean contains(String name) {
- return false;
- }
-
- public void close() {
- }
-
- public JavaFileObject getFileObject(String subdirectory, String file) {
- return null;
- }
-
- public List<String> getFiles(String subdirectory) {
- return List.nil();
- }
-
- public Set<String> getSubdirectories() {
- return Collections.emptySet();
- }
- }
-
- /** A directory of zip files already opened.
- */
- Map<File, Archive> archives = new HashMap<File,Archive>();
-
- /** Open a new zip file directory.
- */
- protected Archive openArchive(File zipFileName) throws IOException {
- Archive archive = archives.get(zipFileName);
- if (archive == null) {
- File origZipFileName = zipFileName;
- if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
- File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
- if (new File(file.getName()).equals(new File("jre")))
- file = file.getParentFile();
- // file == ${jdk.home}
- for (String name : symbolFileLocation)
- file = new File(file, name);
- // file == ${jdk.home}/lib/ct.sym
- if (file.exists())
- zipFileName = file;
- }
-
- try {
-
- ZipFile zdir = null;
-
- boolean usePreindexedCache = false;
- String preindexCacheLocation = null;
-
- if (!useZipFileIndex) {
- zdir = new ZipFile(zipFileName);
- }
- else {
- usePreindexedCache = options.get("usezipindex") != null;
- preindexCacheLocation = options.get("java.io.tmpdir");
- String optCacheLoc = options.get("cachezipindexdir");
-
- if (optCacheLoc != null && optCacheLoc.length() != 0) {
- if (optCacheLoc.startsWith("\"")) {
- if (optCacheLoc.endsWith("\"")) {
- optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1);
- }
- else {
- optCacheLoc = optCacheLoc.substring(1);
- }
- }
-
- File cacheDir = new File(optCacheLoc);
- if (cacheDir.exists() && cacheDir.canWrite()) {
- preindexCacheLocation = optCacheLoc;
- if (!preindexCacheLocation.endsWith("/") &&
- !preindexCacheLocation.endsWith(File.separator)) {
- preindexCacheLocation += File.separator;
- }
- }
- }
- }
-
- if (origZipFileName == zipFileName) {
- if (!useZipFileIndex) {
- archive = new ZipArchive(zdir);
- } else {
- archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, 0,
- usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
- }
- }
- else {
- if (!useZipFileIndex) {
- archive = new SymbolArchive(origZipFileName, zdir);
- }
- else {
- archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefixLength,
- usePreindexedCache, preindexCacheLocation, options.get("writezipindexfiles") != null));
- }
- }
- } catch (FileNotFoundException ex) {
- archive = new MissingArchive(zipFileName);
- } catch (IOException ex) {
- log.error("error.reading.file", zipFileName, ex.getLocalizedMessage());
- archive = new MissingArchive(zipFileName);
- }
-
- archives.put(origZipFileName, archive);
- }
- return archive;
- }
-
- /** Flush any output resources.
- */
- public void flush() {
- contentCache.clear();
- }
-
- /**
- * Close the JavaFileManager, releasing resources.
- */
- public void close() {
- for (Iterator<Archive> i = archives.values().iterator(); i.hasNext(); ) {
- Archive a = i.next();
- i.remove();
- try {
- a.close();
- } catch (IOException e) {
- }
- }
- }
-
- private Map<JavaFileObject, SoftReference<CharBuffer>> contentCache = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
-
- private String defaultEncodingName;
- private String getDefaultEncodingName() {
- if (defaultEncodingName == null) {
- defaultEncodingName =
- new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
- }
- return defaultEncodingName;
- }
-
- protected String getEncodingName() {
- String encName = options.get(OptionName.ENCODING);
- if (encName == null)
- return getDefaultEncodingName();
- else
- return encName;
- }
-
- protected Source getSource() {
- String sourceName = options.get(OptionName.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- return (source != null ? source : Source.DEFAULT);
- }
-
- /**
- * Make a byte buffer from an input stream.
- */
- private ByteBuffer makeByteBuffer(InputStream in)
- throws IOException {
- int limit = in.available();
- if (mmappedIO && in instanceof FileInputStream) {
- // Experimental memory mapped I/O
- FileInputStream fin = (FileInputStream)in;
- return fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, limit);
- }
- if (limit < 1024) limit = 1024;
- ByteBuffer result = byteBufferCache.get(limit);
- int position = 0;
- while (in.available() != 0) {
- if (position >= limit)
- // expand buffer
- result = ByteBuffer.
- allocate(limit <<= 1).
- put((ByteBuffer)result.flip());
- int count = in.read(result.array(),
- position,
- limit - position);
- if (count < 0) break;
- result.position(position += count);
- }
- return (ByteBuffer)result.flip();
- }
-
- /**
- * A single-element cache of direct byte buffers.
- */
- private static class ByteBufferCache {
- private ByteBuffer cached;
- ByteBuffer get(int capacity) {
- if (capacity < 20480) capacity = 20480;
- ByteBuffer result =
- (cached != null && cached.capacity() >= capacity)
- ? (ByteBuffer)cached.clear()
- : ByteBuffer.allocate(capacity + capacity>>1);
- cached = null;
- return result;
- }
- void put(ByteBuffer x) {
- cached = x;
- }
- }
- private final ByteBufferCache byteBufferCache;
-
- private CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
- Charset charset = (this.charset == null)
- ? Charset.forName(encodingName)
- : this.charset;
- CharsetDecoder decoder = charset.newDecoder();
-
- CodingErrorAction action;
- if (ignoreEncodingErrors)
- action = CodingErrorAction.REPLACE;
- else
- action = CodingErrorAction.REPORT;
-
- return decoder
- .onMalformedInput(action)
- .onUnmappableCharacter(action);
- }
-
- /**
- * Decode a ByteBuffer into a CharBuffer.
- */
- private CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
- String encodingName = getEncodingName();
- CharsetDecoder decoder;
- try {
- decoder = getDecoder(encodingName, ignoreEncodingErrors);
- } catch (IllegalCharsetNameException e) {
- log.error("unsupported.encoding", encodingName);
- return (CharBuffer)CharBuffer.allocate(1).flip();
- } catch (UnsupportedCharsetException e) {
- log.error("unsupported.encoding", encodingName);
- return (CharBuffer)CharBuffer.allocate(1).flip();
- }
-
- // slightly overestimate the buffer size to avoid reallocation.
- float factor =
- decoder.averageCharsPerByte() * 0.8f +
- decoder.maxCharsPerByte() * 0.2f;
- CharBuffer dest = CharBuffer.
- allocate(10 + (int)(inbuf.remaining()*factor));
-
- while (true) {
- CoderResult result = decoder.decode(inbuf, dest, true);
- dest.flip();
-
- if (result.isUnderflow()) { // done reading
- // make sure there is at least one extra character
- if (dest.limit() == dest.capacity()) {
- dest = CharBuffer.allocate(dest.capacity()+1).put(dest);
- dest.flip();
- }
- return dest;
- } else if (result.isOverflow()) { // buffer too small; expand
- int newCapacity =
- 10 + dest.capacity() +
- (int)(inbuf.remaining()*decoder.maxCharsPerByte());
- dest = CharBuffer.allocate(newCapacity).put(dest);
- } else if (result.isMalformed() || result.isUnmappable()) {
- // bad character in input
-
- // report coding error (warn only pre 1.5)
- if (!getSource().allowEncodingErrors()) {
- log.error(new SimpleDiagnosticPosition(dest.limit()),
- "illegal.char.for.encoding",
- charset == null ? encodingName : charset.name());
- } else {
- log.warning(new SimpleDiagnosticPosition(dest.limit()),
- "illegal.char.for.encoding",
- charset == null ? encodingName : charset.name());
- }
-
- // skip past the coding error
- inbuf.position(inbuf.position() + result.length());
-
- // undo the flip() to prepare the output buffer
- // for more translation
- dest.position(dest.limit());
- dest.limit(dest.capacity());
- dest.put((char)0xfffd); // backward compatible
- } else {
- throw new AssertionError(result);
- }
- }
- // unreached
- }
-
- public ClassLoader getClassLoader(Location location) {
- nullCheck(location);
- Iterable<? extends File> path = getLocation(location);
- if (path == null)
- return null;
- ListBuffer<URL> lb = new ListBuffer<URL>();
- for (File f: path) {
- try {
- lb.append(f.toURI().toURL());
- } catch (MalformedURLException e) {
- throw new AssertionError(e);
- }
- }
- return new URLClassLoader(lb.toArray(new URL[lb.size()]),
- getClass().getClassLoader());
- }
-
- public Iterable<JavaFileObject> list(Location location,
- String packageName,
- Set<JavaFileObject.Kind> kinds,
- boolean recurse)
- throws IOException
- {
- // validatePackageName(packageName);
- nullCheck(packageName);
- nullCheck(kinds);
-
- Iterable<? extends File> path = getLocation(location);
- if (path == null)
- return List.nil();
- String subdirectory = externalizeFileName(packageName);
- ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
-
- for (File directory : path)
- listDirectory(directory, subdirectory, kinds, recurse, results);
-
- return results.toList();
- }
-
- public String inferBinaryName(Location location, JavaFileObject file) {
- file.getClass(); // null check
- location.getClass(); // null check
- // Need to match the path semantics of list(location, ...)
- Iterable<? extends File> path = getLocation(location);
- if (path == null) {
- //System.err.println("Path for " + location + " is null");
- return null;
- }
- //System.err.println("Path for " + location + " is " + path);
-
- if (file instanceof RegularFileObject) {
- RegularFileObject r = (RegularFileObject) file;
- String rPath = r.getPath();
- //System.err.println("RegularFileObject " + file + " " +r.getPath());
- for (File dir: path) {
- //System.err.println("dir: " + dir);
- String dPath = dir.getPath();
- if (!dPath.endsWith(File.separator))
- dPath += File.separator;
- if (rPath.regionMatches(true, 0, dPath, 0, dPath.length())
- && new File(rPath.substring(0, dPath.length())).equals(new File(dPath))) {
- String relativeName = rPath.substring(dPath.length());
- return removeExtension(relativeName).replace(File.separatorChar, '.');
- }
- }
- } else if (file instanceof ZipFileObject) {
- ZipFileObject z = (ZipFileObject) file;
- String entryName = z.getZipEntryName();
- if (entryName.startsWith(symbolFilePrefix))
- entryName = entryName.substring(symbolFilePrefix.length());
- return removeExtension(entryName).replace('/', '.');
- } else if (file instanceof ZipFileIndexFileObject) {
- ZipFileIndexFileObject z = (ZipFileIndexFileObject) file;
- String entryName = z.getZipEntryName();
- if (entryName.startsWith(symbolFilePrefix))
- entryName = entryName.substring(symbolFilePrefix.length());
- return removeExtension(entryName).replace(File.separatorChar, '.');
- } else
- throw new IllegalArgumentException(file.getClass().getName());
- // System.err.println("inferBinaryName failed for " + file);
- return null;
- }
- // where
- private static String removeExtension(String fileName) {
- int lastDot = fileName.lastIndexOf(".");
- return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
- }
-
- public boolean isSameFile(FileObject a, FileObject b) {
- nullCheck(a);
- nullCheck(b);
- if (!(a instanceof BaseFileObject))
- throw new IllegalArgumentException("Not supported: " + a);
- if (!(b instanceof BaseFileObject))
- throw new IllegalArgumentException("Not supported: " + b);
- return a.equals(b);
- }
-
- public boolean handleOption(String current, Iterator<String> remaining) {
- for (JavacOption o: javacFileManagerOptions) {
- if (o.matches(current)) {
- if (o.hasArg()) {
- if (remaining.hasNext()) {
- if (!o.process(options, current, remaining.next()))
- return true;
- }
- } else {
- if (!o.process(options, current))
- return true;
- }
- // operand missing, or process returned false
- throw new IllegalArgumentException(current);
- }
- }
-
- return false;
- }
- // where
- private static JavacOption[] javacFileManagerOptions =
- RecognizedOptions.getJavacFileManagerOptions(
- new RecognizedOptions.GrumpyHelper());
-
- public int isSupportedOption(String option) {
- for (JavacOption o : javacFileManagerOptions) {
- if (o.matches(option))
- return o.hasArg() ? 1 : 0;
- }
- return -1;
- }
-
- public boolean hasLocation(Location location) {
- return getLocation(location) != null;
- }
-
- public JavaFileObject getJavaFileForInput(Location location,
- String className,
- JavaFileObject.Kind kind)
- throws IOException
- {
- nullCheck(location);
- // validateClassName(className);
- nullCheck(className);
- nullCheck(kind);
- if (!sourceOrClass.contains(kind))
- throw new IllegalArgumentException("Invalid kind " + kind);
- return getFileForInput(location, externalizeFileName(className, kind));
- }
-
- public FileObject getFileForInput(Location location,
- String packageName,
- String relativeName)
- throws IOException
- {
- nullCheck(location);
- // validatePackageName(packageName);
- nullCheck(packageName);
- if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
- throw new IllegalArgumentException("Invalid relative name: " + relativeName);
- String name = packageName.length() == 0
- ? relativeName
- : new File(externalizeFileName(packageName), relativeName).getPath();
- return getFileForInput(location, name);
- }
-
- private JavaFileObject getFileForInput(Location location, String name) throws IOException {
- Iterable<? extends File> path = getLocation(location);
- if (path == null)
- return null;
-
- for (File dir: path) {
- if (dir.isDirectory()) {
- File f = new File(dir, name.replace('/', File.separatorChar));
- if (f.exists())
- return new RegularFileObject(f);
- } else {
- Archive a = openArchive(dir);
- if (a.contains(name)) {
- int i = name.lastIndexOf('/');
- String dirname = name.substring(0, i+1);
- String basename = name.substring(i+1);
- return a.getFileObject(dirname, basename);
- }
-
- }
- }
- return null;
-
- }
-
- public JavaFileObject getJavaFileForOutput(Location location,
- String className,
- JavaFileObject.Kind kind,
- FileObject sibling)
- throws IOException
- {
- nullCheck(location);
- // validateClassName(className);
- nullCheck(className);
- nullCheck(kind);
- if (!sourceOrClass.contains(kind))
- throw new IllegalArgumentException("Invalid kind " + kind);
- return getFileForOutput(location, externalizeFileName(className, kind), sibling);
- }
-
- public FileObject getFileForOutput(Location location,
- String packageName,
- String relativeName,
- FileObject sibling)
- throws IOException
- {
- nullCheck(location);
- // validatePackageName(packageName);
- nullCheck(packageName);
- if (!isRelativeUri(URI.create(relativeName))) // FIXME 6419701
- throw new IllegalArgumentException("relativeName is invalid");
- String name = packageName.length() == 0
- ? relativeName
- : new File(externalizeFileName(packageName), relativeName).getPath();
- return getFileForOutput(location, name, sibling);
- }
-
- private JavaFileObject getFileForOutput(Location location,
- String fileName,
- FileObject sibling)
- throws IOException
- {
- File dir;
- if (location == CLASS_OUTPUT) {
- if (getClassOutDir() != null) {
- dir = getClassOutDir();
- } else {
- File siblingDir = null;
- if (sibling != null && sibling instanceof RegularFileObject) {
- siblingDir = ((RegularFileObject)sibling).f.getParentFile();
- }
- return new RegularFileObject(new File(siblingDir, baseName(fileName)));
- }
- } else if (location == SOURCE_OUTPUT) {
- dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir());
- } else {
- Iterable<? extends File> path = paths.getPathForLocation(location);
- dir = null;
- for (File f: path) {
- dir = f;
- break;
- }
- }
-
- File file = (dir == null ? new File(fileName) : new File(dir, fileName));
- return new RegularFileObject(file);
-
- }
-
- public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
- Iterable<? extends File> files)
- {
- ArrayList<RegularFileObject> result;
- if (files instanceof Collection)
- result = new ArrayList<RegularFileObject>(((Collection)files).size());
- else
- result = new ArrayList<RegularFileObject>();
- for (File f: files)
- result.add(new RegularFileObject(nullCheck(f)));
- return result;
- }
-
- public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
- return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files)));
- }
-
- public void setLocation(Location location,
- Iterable<? extends File> path)
- throws IOException
- {
- nullCheck(location);
- paths.lazy();
-
- final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null;
-
- if (location == CLASS_OUTPUT)
- classOutDir = getOutputLocation(dir, D);
- else if (location == SOURCE_OUTPUT)
- sourceOutDir = getOutputLocation(dir, S);
- else
- paths.setPathForLocation(location, path);
- }
- // where
- private File getOutputDirectory(Iterable<? extends File> path) throws IOException {
- if (path == null)
- return null;
- Iterator<? extends File> pathIter = path.iterator();
- if (!pathIter.hasNext())
- throw new IllegalArgumentException("empty path for directory");
- File dir = pathIter.next();
- if (pathIter.hasNext())
- throw new IllegalArgumentException("path too long for directory");
- if (!dir.exists())
- throw new FileNotFoundException(dir + ": does not exist");
- else if (!dir.isDirectory())
- throw new IOException(dir + ": not a directory");
- return dir;
- }
-
- private File getOutputLocation(File dir, OptionName defaultOptionName) {
- if (dir != null)
- return dir;
- String arg = options.get(defaultOptionName);
- if (arg == null)
- return null;
- return new File(arg);
- }
-
- public Iterable<? extends File> getLocation(Location location) {
- nullCheck(location);
- paths.lazy();
- if (location == CLASS_OUTPUT) {
- return (getClassOutDir() == null ? null : List.of(getClassOutDir()));
- } else if (location == SOURCE_OUTPUT) {
- return (getSourceOutDir() == null ? null : List.of(getSourceOutDir()));
- } else
- return paths.getPathForLocation(location);
- }
-
- private File getClassOutDir() {
- if (classOutDir == uninited)
- classOutDir = getOutputLocation(null, D);
- return classOutDir;
- }
-
- private File getSourceOutDir() {
- if (sourceOutDir == uninited)
- sourceOutDir = getOutputLocation(null, S);
- return sourceOutDir;
- }
-
- /**
- * Enforces the specification of a "relative" URI as used in
- * {@linkplain #getFileForInput(Location,String,URI)
- * getFileForInput}. This method must follow the rules defined in
- * that method, do not make any changes without consulting the
- * specification.
- */
- protected static boolean isRelativeUri(URI uri) {
- if (uri.isAbsolute())
- return false;
- String path = uri.normalize().getPath();
- if (path.length() == 0 /* isEmpty() is mustang API */)
- return false;
- char first = path.charAt(0);
- return first != '.' && first != '/';
- }
-
- /**
- * Converts a relative file name to a relative URI. This is
- * different from File.toURI as this method does not canonicalize
- * the file before creating the URI. Furthermore, no schema is
- * used.
- * @param file a relative file name
- * @return a relative URI
- * @throws IllegalArgumentException if the file name is not
- * relative according to the definition given in {@link
- * javax.tools.JavaFileManager#getFileForInput}
- */
- public static String getRelativeName(File file) {
- if (!file.isAbsolute()) {
- String result = file.getPath().replace(File.separatorChar, '/');
- if (JavacFileManager.isRelativeUri(URI.create(result))) // FIXME 6419701
- return result;
- }
- throw new IllegalArgumentException("Invalid relative path: " + file);
- }
-
- @SuppressWarnings("deprecation") // bug 6410637
- protected static String getJavacFileName(FileObject file) {
- if (file instanceof BaseFileObject)
- return ((BaseFileObject)file).getPath();
- URI uri = file.toUri();
- String scheme = uri.getScheme();
- if (scheme == null || scheme.equals("file") || scheme.equals("jar"))
- return uri.getPath();
- else
- return uri.toString();
- }
-
- @SuppressWarnings("deprecation") // bug 6410637
- protected static String getJavacBaseFileName(FileObject file) {
- if (file instanceof BaseFileObject)
- return ((BaseFileObject)file).getName();
- URI uri = file.toUri();
- String scheme = uri.getScheme();
- if (scheme == null || scheme.equals("file") || scheme.equals("jar")) {
- String path = uri.getPath();
- if (path == null)
- return null;
- if (scheme != null && scheme.equals("jar"))
- path = path.substring(path.lastIndexOf('!') + 1);
- return path.substring(path.lastIndexOf('/') + 1);
- } else {
- return uri.toString();
- }
- }
-
- private static <T> T nullCheck(T o) {
- o.getClass(); // null check
- return o;
- }
-
- private static <T> Iterable<T> nullCheck(Iterable<T> it) {
- for (T t : it)
- t.getClass(); // null check
- return it;
- }
-
- /**
- * A subclass of JavaFileObject representing regular files.
- */
- private class RegularFileObject extends BaseFileObject {
- /** Have the parent directories been created?
- */
- private boolean hasParents=false;
-
- /** The file's name.
- */
- private String name;
-
- /** The underlying file.
- */
- final File f;
-
- public RegularFileObject(File f) {
- this(f.getName(), f);
- }
-
- public RegularFileObject(String name, File f) {
- if (f.isDirectory())
- throw new IllegalArgumentException("directories not supported");
- this.name = name;
- this.f = f;
- }
-
- public InputStream openInputStream() throws IOException {
- return new FileInputStream(f);
- }
-
- protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
- return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
- }
-
- public OutputStream openOutputStream() throws IOException {
- ensureParentDirectoriesExist();
- return new FileOutputStream(f);
- }
-
- public Writer openWriter() throws IOException {
- ensureParentDirectoriesExist();
- return new OutputStreamWriter(new FileOutputStream(f), getEncodingName());
- }
-
- private void ensureParentDirectoriesExist() throws IOException {
- if (!hasParents) {
- File parent = f.getParentFile();
- if (parent != null && !parent.exists()) {
- if (!parent.mkdirs()) {
- // if the mkdirs failed, it may be because another process concurrently
- // created the directory, so check if the directory got created
- // anyway before throwing an exception
- if (!parent.exists() || !parent.isDirectory())
- throw new IOException("could not create parent directories");
- }
- }
- hasParents = true;
- }
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getName() {
- return name;
- }
-
- public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) {
- cn.getClass(); // null check
- if (kind == Kind.OTHER && getKind() != kind)
- return false;
- String n = cn + kind.extension;
- if (name.equals(n))
- return true;
- if (name.equalsIgnoreCase(n)) {
- try {
- // allow for Windows
- return (f.getCanonicalFile().getName().equals(n));
- } catch (IOException e) {
- }
- }
- return false;
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getPath() {
- return f.getPath();
- }
-
- public long getLastModified() {
- return f.lastModified();
- }
-
- public boolean delete() {
- return f.delete();
- }
-
- public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
- SoftReference<CharBuffer> r = contentCache.get(this);
- CharBuffer cb = (r == null ? null : r.get());
- if (cb == null) {
- InputStream in = new FileInputStream(f);
- try {
- ByteBuffer bb = makeByteBuffer(in);
- JavaFileObject prev = log.useSource(this);
- try {
- cb = decode(bb, ignoreEncodingErrors);
- } finally {
- log.useSource(prev);
- }
- byteBufferCache.put(bb); // save for next time
- if (!ignoreEncodingErrors)
- contentCache.put(this, new SoftReference<CharBuffer>(cb));
- } finally {
- in.close();
- }
- }
- return cb;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof RegularFileObject))
- return false;
- RegularFileObject o = (RegularFileObject) other;
- try {
- return f.equals(o.f)
- || f.getCanonicalFile().equals(o.f.getCanonicalFile());
- } catch (IOException e) {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- return f.hashCode();
- }
-
- public URI toUri() {
- try {
- // Do no use File.toURI to avoid file system access
- String path = f.getAbsolutePath().replace(File.separatorChar, '/');
- return new URI("file://" + path).normalize();
- } catch (URISyntaxException ex) {
- return f.toURI();
- }
- }
-
- }
-
- /**
- * A subclass of JavaFileObject representing zip entries.
- */
- public class ZipFileObject extends BaseFileObject {
-
- /** The entry's name.
- */
- private String name;
-
- /** The zipfile containing the entry.
- */
- ZipFile zdir;
-
- /** The underlying zip entry object.
- */
- ZipEntry entry;
-
- public ZipFileObject(String name, ZipFile zdir, ZipEntry entry) {
- this.name = name;
- this.zdir = zdir;
- this.entry = entry;
- }
-
- public InputStream openInputStream() throws IOException {
- return zdir.getInputStream(entry);
- }
-
- public OutputStream openOutputStream() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
- return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
- }
-
- public Writer openWriter() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getName() {
- return name;
- }
-
- public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
- cn.getClass(); // null check
- if (k == Kind.OTHER && getKind() != k)
- return false;
- return name.equals(cn + k.extension);
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getPath() {
- return zdir.getName() + "(" + entry + ")";
- }
-
- public long getLastModified() {
- return entry.getTime();
- }
-
- public boolean delete() {
- throw new UnsupportedOperationException();
- }
-
- public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
- SoftReference<CharBuffer> r = contentCache.get(this);
- CharBuffer cb = (r == null ? null : r.get());
- if (cb == null) {
- InputStream in = zdir.getInputStream(entry);
- try {
- ByteBuffer bb = makeByteBuffer(in);
- JavaFileObject prev = log.useSource(this);
- try {
- cb = decode(bb, ignoreEncodingErrors);
- } finally {
- log.useSource(prev);
- }
- byteBufferCache.put(bb); // save for next time
- if (!ignoreEncodingErrors)
- contentCache.put(this, new SoftReference<CharBuffer>(cb));
- } finally {
- in.close();
- }
- }
- return cb;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof ZipFileObject))
- return false;
- ZipFileObject o = (ZipFileObject) other;
- return zdir.equals(o.zdir) || name.equals(o.name);
- }
-
- @Override
- public int hashCode() {
- return zdir.hashCode() + name.hashCode();
- }
-
- public String getZipName() {
- return zdir.getName();
- }
-
- public String getZipEntryName() {
- return entry.getName();
- }
-
- public URI toUri() {
- String zipName = new File(getZipName()).toURI().normalize().getPath();
- String entryName = getZipEntryName();
- return URI.create("jar:" + zipName + "!" + entryName);
- }
-
- }
-
- /**
- * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.zip.ZipFileIndex implementation.
- */
- public class ZipFileIndexFileObject extends BaseFileObject {
-
- /** The entry's name.
- */
- private String name;
-
- /** The zipfile containing the entry.
- */
- ZipFileIndex zfIndex;
-
- /** The underlying zip entry object.
- */
- ZipFileIndexEntry entry;
-
- /** The InputStream for this zip entry (file.)
- */
- InputStream inputStream = null;
-
- /** The name of the zip file where this entry resides.
- */
- String zipName;
-
- JavacFileManager defFileManager = null;
-
- public ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndexEntry entry, String zipFileName) {
- super();
- this.name = entry.getFileName();
- this.zfIndex = zfIndex;
- this.entry = entry;
- this.zipName = zipFileName;
- defFileManager = fileManager;
- }
-
- public InputStream openInputStream() throws IOException {
-
- if (inputStream == null) {
- inputStream = new ByteArrayInputStream(read());
- }
- return inputStream;
- }
-
- protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
- return JavacFileManager.this.getDecoder(getEncodingName(), ignoreEncodingErrors);
- }
-
- public OutputStream openOutputStream() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- public Writer openWriter() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getName() {
- return name;
- }
-
- public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
- cn.getClass(); // null check
- if (k == Kind.OTHER && getKind() != k)
- return false;
- return name.equals(cn + k.extension);
- }
-
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getPath() {
- return zipName + "(" + entry.getName() + ")";
- }
-
- public long getLastModified() {
- return entry.getLastModified();
- }
-
- public boolean delete() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof ZipFileIndexFileObject))
- return false;
- ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
- return entry.equals(o.entry);
- }
-
- @Override
- public int hashCode() {
- return zipName.hashCode() + (name.hashCode() << 10);
- }
-
- public String getZipName() {
- return zipName;
- }
-
- public String getZipEntryName() {
- return entry.getName();
- }
-
- public URI toUri() {
- String zipName = new File(getZipName()).toURI().normalize().getPath();
- String entryName = getZipEntryName();
- if (File.separatorChar != '/') {
- entryName = entryName.replace(File.separatorChar, '/');
- }
- return URI.create("jar:" + zipName + "!" + entryName);
- }
-
- private byte[] read() throws IOException {
- if (entry == null) {
- entry = zfIndex.getZipIndexEntry(name);
- if (entry == null)
- throw new FileNotFoundException();
- }
- return zfIndex.read(entry);
- }
-
- public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
- SoftReference<CharBuffer> r = defFileManager.contentCache.get(this);
- CharBuffer cb = (r == null ? null : r.get());
- if (cb == null) {
- InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
- try {
- ByteBuffer bb = makeByteBuffer(in);
- JavaFileObject prev = log.useSource(this);
- try {
- cb = decode(bb, ignoreEncodingErrors);
- } finally {
- log.useSource(prev);
- }
- byteBufferCache.put(bb); // save for next time
- if (!ignoreEncodingErrors)
- defFileManager.contentCache.put(this, new SoftReference<CharBuffer>(cb));
- } finally {
- in.close();
- }
- }
- return cb;
- }
- }
-
- public class ZipFileIndexArchive implements Archive {
- private final ZipFileIndex zfIndex;
- private JavacFileManager fileManager;
-
- public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
- this.fileManager = fileManager;
- this.zfIndex = zdir;
- }
-
- public boolean contains(String name) {
- return zfIndex.contains(name);
- }
-
- public com.sun.tools.javac.util.List<String> getFiles(String subdirectory) {
- return zfIndex.getFiles(((subdirectory.endsWith("/") || subdirectory.endsWith("\\"))? subdirectory.substring(0, subdirectory.length() - 1) : subdirectory));
- }
-
- public JavaFileObject getFileObject(String subdirectory, String file) {
- String fullZipFileName = subdirectory + file;
- ZipFileIndexEntry entry = zfIndex.getZipIndexEntry(fullZipFileName);
- JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
- return ret;
- }
-
- public Set<String> getSubdirectories() {
- return zfIndex.getAllDirectories();
- }
-
- public void close() throws IOException {
- zfIndex.close();
- }
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Mon Jun 16 22:23:33 2008 -0700
@@ -33,11 +33,14 @@
import java.util.Set;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
+
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+
import static com.sun.tools.javac.util.LayoutCharacters.*;
/** A class for error logs. Reports errors and warnings, and
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Old199.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright 2006 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.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import javax.tools.*;
-
-import static javax.tools.StandardLocation.SOURCE_PATH;
-
-/**
- * Provides an easy migration to JSR 199 v3.3. The class is
- * deprecated as we should remove it as soon as possible.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems.
- * If you write code that depends on this, you do so at your own
- * risk. This code and its internal interfaces are subject to change
- * or deletion without notice.</b></p>
- *
- * @author Peter von der Ah\u00e9
- */
-@Deprecated
-public class Old199 {
-
- private Old199() {}
-
- public static String getPath(FileObject jfo) {
- return JavacFileManager.getJavacFileName(jfo);
- }
-
- public static String getName(FileObject jfo) {
- return JavacFileManager.getJavacBaseFileName(jfo);
- }
-
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Paths.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-/*
- * Copyright 2003-2006 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.util;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-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 com.sun.tools.javac.code.Lint;
-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 static com.sun.tools.javac.main.OptionName.*;
-import static javax.tools.StandardLocation.*;
-
-/** This class converts command line arguments, environment variables
- * and system properties (in File.pathSeparator-separated String form)
- * into a boot class path, user class path, and source path (in
- * Collection<String> form).
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Paths {
-
- /** The context key for the todo list */
- protected static final Context.Key<Paths> pathsKey =
- new Context.Key<Paths>();
-
- /** Get the Paths instance for this context.
- * @param context the context
- * @return the Paths instance for this context
- */
- public static Paths instance(Context context) {
- Paths instance = context.get(pathsKey);
- if (instance == null)
- instance = new Paths(context);
- return instance;
- }
-
- /** The log to use for warning output */
- private Log log;
-
- /** Collection of command-line options */
- private Options options;
-
- /** 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;
- }
-
- protected Paths(Context context) {
- context.put(pathsKey, this);
- pathsForLocation = new HashMap<Location,Path>(16);
- setContext(context);
- }
-
- void setContext(Context context) {
- log = Log.instance(context);
- options = Options.instance(context);
- lint = Lint.instance(context);
- }
-
- /** Whether to warn about non-existent path elements */
- private boolean warn;
-
- private Map<Location, Path> pathsForLocation;
-
- private boolean inited = false; // TODO? caching bad?
-
- /**
- * rt.jar as found on the default bootclass path. If the user specified a
- * bootclasspath, null is used.
- */
- private File bootClassPathRtJar = null;
-
- Path getPathForLocation(Location location) {
- Path path = pathsForLocation.get(location);
- if (path == null)
- setPathForLocation(location, null);
- return pathsForLocation.get(location);
- }
-
- void setPathForLocation(Location location, Iterable<? extends File> path) {
- // TODO? if (inited) throw new IllegalStateException
- // TODO: otherwise reset sourceSearchPath, classSearchPath as needed
- Path p;
- if (path == null) {
- if (location == CLASS_PATH)
- p = computeUserClassPath();
- else if (location == PLATFORM_CLASS_PATH)
- p = computeBootClassPath();
- else if (location == ANNOTATION_PROCESSOR_PATH)
- p = computeAnnotationProcessorPath();
- else if (location == SOURCE_PATH)
- p = computeSourcePath();
- else
- // no defaults for other paths
- p = null;
- } else {
- p = new Path();
- for (File f: path)
- p.addFile(f, warn); // TODO: is use of warn appropriate?
- }
- pathsForLocation.put(location, p);
- }
-
- protected void lazy() {
- if (!inited) {
- warn = lint.isEnabled(Lint.LintCategory.PATH);
-
- pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath());
- pathsForLocation.put(CLASS_PATH, computeUserClassPath());
- pathsForLocation.put(SOURCE_PATH, computeSourcePath());
-
- inited = true;
- }
- }
-
- public Collection<File> bootClassPath() {
- lazy();
- return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH));
- }
- public Collection<File> userClassPath() {
- lazy();
- return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH));
- }
- public Collection<File> sourcePath() {
- lazy();
- Path p = getPathForLocation(SOURCE_PATH);
- return p == null || p.size() == 0
- ? null
- : Collections.unmodifiableCollection(p);
- }
-
- boolean isBootClassPathRtJar(File file) {
- return file.equals(bootClassPathRtJar);
- }
-
- private static class PathIterator implements Iterable<String> {
- private int pos = 0;
- private final String path;
- private final String emptyPathDefault;
-
- public PathIterator(String path, String emptyPathDefault) {
- this.path = path;
- this.emptyPathDefault = emptyPathDefault;
- }
- public PathIterator(String path) { this(path, null); }
- public Iterator<String> iterator() {
- return new Iterator<String>() {
- public boolean hasNext() {
- return pos <= path.length();
- }
- public String next() {
- int beg = pos;
- int end = path.indexOf(File.pathSeparator, beg);
- if (end == -1)
- end = path.length();
- pos = end + 1;
-
- if (beg == end && emptyPathDefault != null)
- return emptyPathDefault;
- else
- return path.substring(beg, end);
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- }
-
- private class Path extends LinkedHashSet<File> {
- private static final long serialVersionUID = 0;
-
- private boolean expandJarClassPaths = false;
- private Set<File> canonicalValues = new HashSet<File>();
-
- public Path expandJarClassPaths(boolean x) {
- expandJarClassPaths = x;
- return this;
- }
-
- /** What to use when path element is the empty string */
- private String emptyPathDefault = null;
-
- public Path emptyPathDefault(String x) {
- emptyPathDefault = x;
- return this;
- }
-
- public Path() { super(); }
-
- public Path addDirectories(String dirs, boolean warn) {
- if (dirs != null)
- for (String dir : new PathIterator(dirs))
- addDirectory(dir, warn);
- return this;
- }
-
- public Path addDirectories(String dirs) {
- return addDirectories(dirs, warn);
- }
-
- private void addDirectory(String dir, boolean warn) {
- if (! new File(dir).isDirectory()) {
- if (warn)
- log.warning("dir.path.element.not.found", dir);
- return;
- }
-
- File[] files = new File(dir).listFiles();
- if (files == null)
- return;
-
- for (File direntry : files) {
- if (isArchive(direntry))
- addFile(direntry, warn);
- }
- }
-
- public Path addFiles(String files, boolean warn) {
- if (files != null)
- for (String file : new PathIterator(files, emptyPathDefault))
- addFile(file, warn);
- return this;
- }
-
- public Path addFiles(String files) {
- return addFiles(files, warn);
- }
-
- public Path addFile(String file, boolean warn) {
- addFile(new File(file), warn);
- return this;
- }
-
- 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)) {
- /* 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) {
- /* No such file or directory exists */
- if (warn)
- log.warning("path.element.not.found", file);
- } else if (pe.isFile) {
- /* File is an ordinary file. */
- if (!isArchive(file)) {
- /* Not a recognized extension; open it to see if
- it looks like a valid zip file. */
- try {
- ZipFile z = new ZipFile(file);
- z.close();
- if (warn)
- log.warning("unexpected.archive.file", file);
- } catch (IOException e) {
- // FIXME: include e.getLocalizedMessage in warning
- if (warn)
- log.warning("invalid.archive.file", file);
- return;
- }
- }
- }
-
- /* 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);
-
- if (expandJarClassPaths && file.exists() && file.isFile())
- addJarClassPath(file, warn);
- }
-
- // Adds referenced classpath elements from a jar's Class-Path
- // Manifest entry. In some future release, we may want to
- // update this code to recognize URLs rather than simple
- // 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();
- }
- } catch (IOException e) {
- log.error("error.reading.file", jarFile, e.getLocalizedMessage());
- }
- }
- }
-
- private Path computeBootClassPath() {
- bootClassPathRtJar = null;
- String optionValue;
- Path path = new Path();
-
- path.addFiles(options.get(XBOOTCLASSPATH_PREPEND));
-
- if ((optionValue = options.get(ENDORSEDDIRS)) != null)
- path.addDirectories(optionValue);
- else
- path.addDirectories(System.getProperty("java.endorsed.dirs"), false);
-
- if ((optionValue = options.get(BOOTCLASSPATH)) != null) {
- path.addFiles(optionValue);
- } else {
- // Standard system classes for this compiler's release.
- String files = System.getProperty("sun.boot.class.path");
- path.addFiles(files, false);
- File rt_jar = new File("rt.jar");
- for (String file : new PathIterator(files, null)) {
- File f = new File(file);
- if (new File(f.getName()).equals(rt_jar))
- bootClassPathRtJar = f;
- }
- }
-
- path.addFiles(options.get(XBOOTCLASSPATH_APPEND));
-
- // Strictly speaking, standard extensions are not bootstrap
- // classes, but we treat them identically, so we'll pretend
- // that they are.
- if ((optionValue = options.get(EXTDIRS)) != null)
- path.addDirectories(optionValue);
- else
- path.addDirectories(System.getProperty("java.ext.dirs"), false);
-
- return path;
- }
-
- private Path computeUserClassPath() {
- String cp = options.get(CLASSPATH);
-
- // CLASSPATH environment variable when run from `javac'.
- if (cp == null) cp = System.getProperty("env.class.path");
-
- // If invoked via a java VM (not the javac launcher), use the
- // platform class path
- if (cp == null && System.getProperty("application.home") == null)
- cp = System.getProperty("java.class.path");
-
- // Default to current working directory.
- if (cp == null) cp = ".";
-
- return new Path()
- .expandJarClassPaths(true) // Only search user jars for Class-Paths
- .emptyPathDefault(".") // Empty path elt ==> current directory
- .addFiles(cp);
- }
-
- private Path computeSourcePath() {
- String sourcePathArg = options.get(SOURCEPATH);
- if (sourcePathArg == null)
- return null;
-
- return new Path().addFiles(sourcePathArg);
- }
-
- private Path computeAnnotationProcessorPath() {
- String processorPathArg = options.get(PROCESSORPATH);
- if (processorPathArg == null)
- return null;
-
- return new Path().addFiles(processorPathArg);
- }
-
- /** The actual effective locations searched for sources */
- private Path sourceSearchPath;
-
- public Collection<File> sourceSearchPath() {
- if (sourceSearchPath == null) {
- lazy();
- Path sourcePath = getPathForLocation(SOURCE_PATH);
- Path userClassPath = getPathForLocation(CLASS_PATH);
- sourceSearchPath = sourcePath != null ? sourcePath : userClassPath;
- }
- return Collections.unmodifiableCollection(sourceSearchPath);
- }
-
- /** The actual effective locations searched for classes */
- private Path classSearchPath;
-
- public Collection<File> classSearchPath() {
- if (classSearchPath == null) {
- lazy();
- Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH);
- Path userClassPath = getPathForLocation(CLASS_PATH);
- classSearchPath = new Path();
- classSearchPath.addAll(bootClassPath);
- classSearchPath.addAll(userClassPath);
- }
- return Collections.unmodifiableCollection(classSearchPath);
- }
-
- /** The actual effective locations for non-source, non-class files */
- private Path otherSearchPath;
-
- Collection<File> otherSearchPath() {
- if (otherSearchPath == null) {
- lazy();
- Path userClassPath = getPathForLocation(CLASS_PATH);
- Path sourcePath = getPathForLocation(SOURCE_PATH);
- if (sourcePath == null)
- otherSearchPath = userClassPath;
- else {
- otherSearchPath = new Path();
- otherSearchPath.addAll(userClassPath);
- otherSearchPath.addAll(sourcePath);
- }
- }
- return Collections.unmodifiableCollection(otherSearchPath);
- }
-
- /** Is this the name of an archive file? */
- private static 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
- && (n.endsWith(".jar") || n.endsWith(".zip"));
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1236 +0,0 @@
-/*
- * Copyright 2007-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.zip;
-
-import java.io.*;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.zip.*;
-
-/** This class implements building of index of a zip archive and access to it's context.
- * It also uses prebuild index if available. It supports invocations where it will
- * serialize an optimized zip index file to disk.
- *
- * In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
- * when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
- *
- * Location where to look for/generate optimized zip index files can be provided using
- * "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
- * the value of the "java.io.tmpdir" system property.
- *
- * If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
- * created for each archive, used by the compiler for compilation, at location,
- * specified by "cachezipindexdir" option.
- *
- * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp
- * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
- * and the compiler uses the cached indexes.
- */
-public class ZipFileIndex {
- private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
- private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);
-
- public final static long NOT_MODIFIED = Long.MIN_VALUE;
-
- private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
- private static ReentrantLock lock = new ReentrantLock();
-
- private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
-
- private Map<String, DirectoryEntry> directories = Collections.<String, DirectoryEntry>emptyMap();
- private Set<String> allDirs = Collections.<String>emptySet();
-
- // ZipFileIndex data entries
- private File zipFile;
- private long zipFileLastModified = NOT_MODIFIED;
- private RandomAccessFile zipRandomFile;
- private ZipFileIndexEntry[] entries;
-
- private boolean readFromIndex = false;
- private File zipIndexFile = null;
- private boolean triedToReadIndex = false;
- private int symbolFilePrefixLength = 0;
- private boolean hasPopulatedData = false;
- private long lastReferenceTimeStamp = NOT_MODIFIED;
-
- private boolean usePreindexedCache = false;
- private String preindexedCacheLocation = null;
-
- private boolean writeIndex = false;
-
- /**
- * Returns a list of all ZipFileIndex entries
- *
- * @return A list of ZipFileIndex entries, or an empty list
- */
- public static List<ZipFileIndex> getZipFileIndexes() {
- return getZipFileIndexes(false);
- }
-
- /**
- * Returns a list of all ZipFileIndex entries
- *
- * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
- * all ZipFileEntry(s) are included into the list.
- * @return A list of ZipFileIndex entries, or an empty list
- */
- public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
- List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
- lock.lock();
- try {
- zipFileIndexes.addAll(zipFileIndexCache.values());
-
- if (openedOnly) {
- for(ZipFileIndex elem : zipFileIndexes) {
- if (!elem.isOpen()) {
- zipFileIndexes.remove(elem);
- }
- }
- }
- }
- finally {
- lock.unlock();
- }
- return zipFileIndexes;
- }
-
- public boolean isOpen() {
- lock.lock();
- try {
- return zipRandomFile != null;
- }
- finally {
- lock.unlock();
- }
- }
-
- public static ZipFileIndex getZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean useCache, String cacheLocation, boolean writeIndex) throws IOException {
- ZipFileIndex zi = null;
- lock.lock();
- try {
- zi = getExistingZipIndex(zipFile);
-
- if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
- zi = new ZipFileIndex(zipFile, symbolFilePrefixLen, writeIndex,
- useCache, cacheLocation);
- zipFileIndexCache.put(zipFile, zi);
- }
- }
- finally {
- lock.unlock();
- }
- return zi;
- }
-
- public static ZipFileIndex getExistingZipIndex(File zipFile) {
- lock.lock();
- try {
- return zipFileIndexCache.get(zipFile);
- }
- finally {
- lock.unlock();
- }
- }
-
- public static void clearCache() {
- lock.lock();
- try {
- zipFileIndexCache.clear();
- }
- finally {
- lock.unlock();
- }
- }
-
- public static void clearCache(long timeNotUsed) {
- lock.lock();
- try {
- Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
- while (cachedFileIterator.hasNext()) {
- File cachedFile = cachedFileIterator.next();
- ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
- if (cachedZipIndex != null) {
- long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
- if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
- System.currentTimeMillis() > timeToTest) {
- zipFileIndexCache.remove(cachedFile);
- }
- }
- }
- }
- finally {
- lock.unlock();
- }
- }
-
- public static void removeFromCache(File file) {
- lock.lock();
- try {
- zipFileIndexCache.remove(file);
- }
- finally {
- lock.unlock();
- }
- }
-
- /** Sets already opened list of ZipFileIndexes from an outside client
- * of the compiler. This functionality should be used in a non-batch clients of the compiler.
- */
- public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
- lock.lock();
- try {
- if (zipFileIndexCache.isEmpty()) {
- throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
- }
-
- for (ZipFileIndex zfi : indexes) {
- zipFileIndexCache.put(zfi.zipFile, zfi);
- }
- }
- finally {
- lock.unlock();
- }
- }
-
- private ZipFileIndex(File zipFile, int symbolFilePrefixLen, boolean writeIndex,
- boolean useCache, String cacheLocation) throws IOException {
- this.zipFile = zipFile;
- this.symbolFilePrefixLength = symbolFilePrefixLen;
- this.writeIndex = writeIndex;
- this.usePreindexedCache = useCache;
- this.preindexedCacheLocation = cacheLocation;
-
- if (zipFile != null) {
- this.zipFileLastModified = zipFile.lastModified();
- }
-
- // Validate integrity of the zip file
- checkIndex();
- }
-
- public String toString() {
- return "ZipFileIndex of file:(" + zipFile + ")";
- }
-
- // Just in case...
- protected void finalize() {
- closeFile();
- }
-
- private boolean isUpToDate() {
- if (zipFile != null &&
- ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
- hasPopulatedData) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
- * if its the same as the one at the time the index was build we don't need to reopen anything.
- */
- private void checkIndex() throws IOException {
- boolean isUpToDate = true;
- if (!isUpToDate()) {
- closeFile();
- isUpToDate = false;
- }
-
- if (zipRandomFile != null || isUpToDate) {
- lastReferenceTimeStamp = System.currentTimeMillis();
- return;
- }
-
- hasPopulatedData = true;
-
- if (readIndex()) {
- lastReferenceTimeStamp = System.currentTimeMillis();
- return;
- }
-
- directories = Collections.<String, DirectoryEntry>emptyMap();
- allDirs = Collections.<String>emptySet();
-
- try {
- openFile();
- long totalLength = zipRandomFile.length();
- ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
- directory.buildIndex();
- } finally {
- if (zipRandomFile != null) {
- closeFile();
- }
- }
-
- lastReferenceTimeStamp = System.currentTimeMillis();
- }
-
- private void openFile() throws FileNotFoundException {
- if (zipRandomFile == null && zipFile != null) {
- zipRandomFile = new RandomAccessFile(zipFile, "r");
- }
- }
-
- private void cleanupState() {
- // Make sure there is a valid but empty index if the file doesn't exist
- entries = ZipFileIndexEntry.EMPTY_ARRAY;
- directories = Collections.<String, DirectoryEntry>emptyMap();
- zipFileLastModified = NOT_MODIFIED;
- allDirs = Collections.<String>emptySet();
- }
-
- public void close() {
- lock.lock();
- try {
- writeIndex();
- closeFile();
- }
- finally {
- lock.unlock();
- }
- }
-
- private void closeFile() {
- if (zipRandomFile != null) {
- try {
- zipRandomFile.close();
- } catch (IOException ex) {
- }
- zipRandomFile = null;
- }
- }
-
- /**
- * Returns the ZipFileIndexEntry for an absolute path, if there is one.
- */
- public ZipFileIndexEntry getZipIndexEntry(String path) {
- if (File.separatorChar != '/') {
- path = path.replace('/', File.separatorChar);
- }
- lock.lock();
- try {
- checkIndex();
- String lookFor = "";
- int lastSepIndex = path.lastIndexOf(File.separatorChar);
- boolean noSeparator = false;
- if (lastSepIndex == -1) {
- noSeparator = true;
- }
-
- DirectoryEntry de = directories.get(noSeparator ? "" : path.substring(0, lastSepIndex));
-
- lookFor = path.substring(noSeparator ? 0 : lastSepIndex + 1);
-
- return de == null ? null : de.getEntry(lookFor);
- }
- catch (IOException e) {
- return null;
- }
- finally {
- lock.unlock();
- }
- }
-
- /**
- * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
- */
- public com.sun.tools.javac.util.List<String> getFiles(String path) {
- if (File.separatorChar != '/') {
- path = path.replace('/', File.separatorChar);
- }
-
- lock.lock();
- try {
- checkIndex();
-
- DirectoryEntry de = directories.get(path);
- com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();
-
- if (ret == null) {
- return com.sun.tools.javac.util.List.<String>nil();
- }
- return ret;
- }
- catch (IOException e) {
- return com.sun.tools.javac.util.List.<String>nil();
- }
- finally {
- lock.unlock();
- }
- }
-
- public List<String> getAllDirectories(String path) {
-
- if (File.separatorChar != '/') {
- path = path.replace('/', File.separatorChar);
- }
-
- lock.lock();
- try {
- checkIndex();
- path = path.intern();
-
- DirectoryEntry de = directories.get(path);
- com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();
-
- if (ret == null) {
- return com.sun.tools.javac.util.List.<String>nil();
- }
-
- return ret;
- }
- catch (IOException e) {
- return com.sun.tools.javac.util.List.<String>nil();
- }
- finally {
- lock.unlock();
- }
- }
-
- public Set<String> getAllDirectories() {
- lock.lock();
- try {
- checkIndex();
- if (allDirs == Collections.EMPTY_SET) {
- Set<String> alldirs = new HashSet<String>();
- Iterator<String> dirsIter = directories.keySet().iterator();
- while (dirsIter.hasNext()) {
- alldirs.add(new String(dirsIter.next()));
- }
-
- allDirs = alldirs;
- }
-
- return allDirs;
- }
- catch (IOException e) {
- return Collections.<String>emptySet();
- }
- finally {
- lock.unlock();
- }
- }
-
- /**
- * Tests if a specific path exists in the zip. This method will return true
- * for file entries and directories.
- *
- * @param path A path within the zip.
- * @return True if the path is a file or dir, false otherwise.
- */
- public boolean contains(String path) {
- lock.lock();
- try {
- checkIndex();
- return getZipIndexEntry(path) != null;
- }
- catch (IOException e) {
- return false;
- }
- finally {
- lock.unlock();
- }
- }
-
- public boolean isDirectory(String path) throws IOException {
- lock.lock();
- try {
- // The top level in a zip file is always a directory.
- if (path.length() == 0) {
- lastReferenceTimeStamp = System.currentTimeMillis();
- return true;
- }
-
- if (File.separatorChar != '/')
- path = path.replace('/', File.separatorChar);
- checkIndex();
- return directories.get(path) != null;
- }
- finally {
- lock.unlock();
- }
- }
-
- public long getLastModified(String path) throws IOException {
- lock.lock();
- try {
- ZipFileIndexEntry entry = getZipIndexEntry(path);
- if (entry == null)
- throw new FileNotFoundException();
- return entry.getLastModified();
- }
- finally {
- lock.unlock();
- }
- }
-
- public int length(String path) throws IOException {
- lock.lock();
- try {
- ZipFileIndexEntry entry = getZipIndexEntry(path);
- if (entry == null)
- throw new FileNotFoundException();
-
- if (entry.isDir) {
- return 0;
- }
-
- byte[] header = getHeader(entry);
- // entry is not compressed?
- if (get2ByteLittleEndian(header, 8) == 0) {
- return entry.compressedSize;
- } else {
- return entry.size;
- }
- }
- finally {
- lock.unlock();
- }
- }
-
- public byte[] read(String path) throws IOException {
- lock.lock();
- try {
- ZipFileIndexEntry entry = getZipIndexEntry(path);
- if (entry == null)
- throw new FileNotFoundException(MessageFormat.format("Path not found in ZIP: {0}", path));
- return read(entry);
- }
- finally {
- lock.unlock();
- }
- }
-
- public byte[] read(ZipFileIndexEntry entry) throws IOException {
- lock.lock();
- try {
- openFile();
- byte[] result = readBytes(entry);
- closeFile();
- return result;
- }
- finally {
- lock.unlock();
- }
- }
-
- public int read(String path, byte[] buffer) throws IOException {
- lock.lock();
- try {
- ZipFileIndexEntry entry = getZipIndexEntry(path);
- if (entry == null)
- throw new FileNotFoundException();
- return read(entry, buffer);
- }
- finally {
- lock.unlock();
- }
- }
-
- public int read(ZipFileIndexEntry entry, byte[] buffer)
- throws IOException {
- lock.lock();
- try {
- int result = readBytes(entry, buffer);
- return result;
- }
- finally {
- lock.unlock();
- }
- }
-
- private byte[] readBytes(ZipFileIndexEntry entry) throws IOException {
- byte[] header = getHeader(entry);
- int csize = entry.compressedSize;
- byte[] cbuf = new byte[csize];
- zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
- zipRandomFile.readFully(cbuf, 0, csize);
-
- // is this compressed - offset 8 in the ZipEntry header
- if (get2ByteLittleEndian(header, 8) == 0)
- return cbuf;
-
- int size = entry.size;
- byte[] buf = new byte[size];
- if (inflate(cbuf, buf) != size)
- throw new ZipException("corrupted zip file");
-
- return buf;
- }
-
- /**
- *
- */
- private int readBytes(ZipFileIndexEntry entry, byte[] buffer) throws IOException {
- byte[] header = getHeader(entry);
-
- // entry is not compressed?
- if (get2ByteLittleEndian(header, 8) == 0) {
- zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
- int offset = 0;
- int size = buffer.length;
- while (offset < size) {
- int count = zipRandomFile.read(buffer, offset, size - offset);
- if (count == -1)
- break;
- offset += count;
- }
- return entry.size;
- }
-
- int csize = entry.compressedSize;
- byte[] cbuf = new byte[csize];
- zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
- zipRandomFile.readFully(cbuf, 0, csize);
-
- int count = inflate(cbuf, buffer);
- if (count == -1)
- throw new ZipException("corrupted zip file");
-
- return entry.size;
- }
-
- //----------------------------------------------------------------------------
- // Zip utilities
- //----------------------------------------------------------------------------
-
- private byte[] getHeader(ZipFileIndexEntry entry) throws IOException {
- zipRandomFile.seek(entry.offset);
- byte[] header = new byte[30];
- zipRandomFile.readFully(header);
- if (get4ByteLittleEndian(header, 0) != 0x04034b50)
- throw new ZipException("corrupted zip file");
- if ((get2ByteLittleEndian(header, 6) & 1) != 0)
- throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
- return header;
- }
-
- /*
- * Inflate using the java.util.zip.Inflater class
- */
- private static Inflater inflater;
- private int inflate(byte[] src, byte[] dest) {
-
- // construct the inflater object or reuse an existing one
- if (inflater == null)
- inflater = new Inflater(true);
-
- synchronized (inflater) {
- inflater.reset();
- inflater.setInput(src);
- try {
- return inflater.inflate(dest);
- } catch (DataFormatException ex) {
- return -1;
- }
- }
- }
-
- /**
- * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
- * endian format.
- */
- private static int get2ByteLittleEndian(byte[] buf, int pos) {
- return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
- }
-
- /**
- * return the 4 bytes buf[i..i+3] as an integer in little endian format.
- */
- private static int get4ByteLittleEndian(byte[] buf, int pos) {
- return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
- ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
- }
-
- /* ----------------------------------------------------------------------------
- * ZipDirectory
- * ----------------------------------------------------------------------------*/
-
- private class ZipDirectory {
- private String lastDir;
- private int lastStart;
- private int lastLen;
-
- byte[] zipDir;
- RandomAccessFile zipRandomFile = null;
- ZipFileIndex zipFileIndex = null;
-
- public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
- this.zipRandomFile = zipRandomFile;
- this.zipFileIndex = index;
-
- findCENRecord(start, end);
- }
-
- /*
- * Reads zip file central directory.
- * For more details see readCEN in zip_util.c from the JDK sources.
- * This is a Java port of that function.
- */
- private void findCENRecord(long start, long end) throws IOException {
- long totalLength = end - start;
- int endbuflen = 1024;
- byte[] endbuf = new byte[endbuflen];
- long endbufend = end - start;
-
- // There is a variable-length field after the dir offset record. We need to do consequential search.
- while (endbufend >= 22) {
- if (endbufend < endbuflen)
- endbuflen = (int)endbufend;
- long endbufpos = endbufend - endbuflen;
- zipRandomFile.seek(start + endbufpos);
- zipRandomFile.readFully(endbuf, 0, endbuflen);
- int i = endbuflen - 22;
- while (i >= 0 &&
- !(endbuf[i] == 0x50 &&
- endbuf[i + 1] == 0x4b &&
- endbuf[i + 2] == 0x05 &&
- endbuf[i + 3] == 0x06 &&
- endbufpos + i + 22 +
- get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
- i--;
- }
-
- if (i >= 0) {
- zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
- zipDir[0] = endbuf[i + 10];
- zipDir[1] = endbuf[i + 11];
- zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
- zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
- return;
- } else {
- endbufend = endbufpos + 21;
- }
- }
- throw new ZipException("cannot read zip file");
- }
- private void buildIndex() throws IOException {
- int entryCount = get2ByteLittleEndian(zipDir, 0);
-
- entries = new ZipFileIndexEntry[entryCount];
- // Add each of the files
- if (entryCount > 0) {
- directories = new HashMap<String, DirectoryEntry>();
- ArrayList<ZipFileIndexEntry> entryList = new ArrayList<ZipFileIndexEntry>();
- int pos = 2;
- for (int i = 0; i < entryCount; i++) {
- pos = readEntry(pos, entryList, directories);
- }
-
- // Add the accumulated dirs into the same list
- Iterator i = directories.keySet().iterator();
- while (i.hasNext()) {
- ZipFileIndexEntry zipFileIndexEntry = new ZipFileIndexEntry( (String) i.next());
- zipFileIndexEntry.isDir = true;
- entryList.add(zipFileIndexEntry);
- }
-
- entries = entryList.toArray(new ZipFileIndexEntry[entryList.size()]);
- Arrays.sort(entries);
- } else {
- cleanupState();
- }
- }
-
- private int readEntry(int pos, List<ZipFileIndexEntry> entryList,
- Map<String, DirectoryEntry> directories) throws IOException {
- if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
- throw new ZipException("cannot read zip file entry");
- }
-
- int dirStart = pos + 46;
- int fileStart = dirStart;
- int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);
-
- if (zipFileIndex.symbolFilePrefixLength != 0 &&
- ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
- dirStart += zipFileIndex.symbolFilePrefixLength;
- fileStart += zipFileIndex.symbolFilePrefixLength;
- }
-
- // Use the OS's path separator. Keep the position of the last one.
- for (int index = fileStart; index < fileEnd; index++) {
- byte nextByte = zipDir[index];
- if (nextByte == (byte)'\\' || nextByte == (byte)'/') {
- zipDir[index] = (byte)File.separatorChar;
- fileStart = index + 1;
- }
- }
-
- String directory = null;
- if (fileStart == dirStart)
- directory = "";
- else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
- int index = lastLen - 1;
- while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
- if (index == 0) {
- directory = lastDir;
- break;
- }
- index--;
- }
- }
-
- // Sub directories
- if (directory == null) {
- lastStart = dirStart;
- lastLen = fileStart - dirStart - 1;
-
- directory = new String(zipDir, dirStart, lastLen, "UTF-8").intern();
- lastDir = directory;
-
- // Enter also all the parent directories
- String tempDirectory = directory;
-
- while (directories.get(tempDirectory) == null) {
- directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
- int separator = tempDirectory.lastIndexOf(File.separatorChar);
- if (separator == -1)
- break;
- tempDirectory = tempDirectory.substring(0, separator);
- }
- }
- else {
- directory = directory.intern();
- if (directories.get(directory) == null) {
- directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
- }
- }
-
- // For each dir create also a file
- if (fileStart != fileEnd) {
- ZipFileIndexEntry entry = new ZipFileIndexEntry(directory,
- new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));
-
- entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
- entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
- entry.size = get4ByteLittleEndian(zipDir, pos + 24);
- entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
- entryList.add(entry);
- }
-
- return pos + 46 +
- get2ByteLittleEndian(zipDir, pos + 28) +
- get2ByteLittleEndian(zipDir, pos + 30) +
- get2ByteLittleEndian(zipDir, pos + 32);
- }
- }
-
- /**
- * Returns the last modified timestamp of a zip file.
- * @return long
- */
- public long getZipFileLastModified() throws IOException {
- lock.lock();
- try {
- checkIndex();
- return zipFileLastModified;
- }
- finally {
- lock.unlock();
- }
- }
-
- /** ------------------------------------------------------------------------
- * DirectoryEntry class
- * -------------------------------------------------------------------------*/
- static class DirectoryEntry {
- private boolean filesInited;
- private boolean directoriesInited;
- private boolean zipFileEntriesInited;
- private boolean entriesInited;
-
- private long writtenOffsetOffset = 0;
-
- private String dirName;
-
- private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
- private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
- private com.sun.tools.javac.util.List<ZipFileIndexEntry> zipFileEntries = com.sun.tools.javac.util.List.<ZipFileIndexEntry>nil();
-
- private List<ZipFileIndexEntry> entries = new ArrayList<ZipFileIndexEntry>();
-
- private ZipFileIndex zipFileIndex;
-
- private int numEntries;
-
- DirectoryEntry(String dirName, ZipFileIndex index) {
- filesInited = false;
- directoriesInited = false;
- entriesInited = false;
-
- if (File.separatorChar == '/') {
- dirName.replace('\\', '/');
- }
- else {
- dirName.replace('/', '\\');
- }
-
- this.dirName = dirName.intern();
- this.zipFileIndex = index;
- }
-
- private com.sun.tools.javac.util.List<String> getFiles() {
- if (filesInited) {
- return zipFileEntriesFiles;
- }
-
- initEntries();
-
- for (ZipFileIndexEntry e : entries) {
- if (!e.isDir) {
- zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
- }
- }
- filesInited = true;
- return zipFileEntriesFiles;
- }
-
- private com.sun.tools.javac.util.List<String> getDirectories() {
- if (directoriesInited) {
- return zipFileEntriesFiles;
- }
-
- initEntries();
-
- for (ZipFileIndexEntry e : entries) {
- if (e.isDir) {
- zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
- }
- }
-
- directoriesInited = true;
-
- return zipFileEntriesDirectories;
- }
-
- private com.sun.tools.javac.util.List<ZipFileIndexEntry> getEntries() {
- if (zipFileEntriesInited) {
- return zipFileEntries;
- }
-
- initEntries();
-
- zipFileEntries = com.sun.tools.javac.util.List.nil();
- for (ZipFileIndexEntry zfie : entries) {
- zipFileEntries = zipFileEntries.append(zfie);
- }
-
- zipFileEntriesInited = true;
-
- return zipFileEntries;
- }
-
- private ZipFileIndexEntry getEntry(String rootName) {
- initEntries();
- int index = Collections.binarySearch(entries, new ZipFileIndexEntry(dirName, rootName));
- if (index < 0) {
- return null;
- }
-
- return entries.get(index);
- }
-
- private void initEntries() {
- if (entriesInited) {
- return;
- }
-
- if (!zipFileIndex.readFromIndex) {
- int from = -Arrays.binarySearch(zipFileIndex.entries,
- new ZipFileIndexEntry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
- int to = -Arrays.binarySearch(zipFileIndex.entries,
- new ZipFileIndexEntry(dirName, MAX_CHAR)) - 1;
-
- boolean emptyList = false;
-
- for (int i = from; i < to; i++) {
- entries.add(zipFileIndex.entries[i]);
- }
- } else {
- File indexFile = zipFileIndex.getIndexFile();
- if (indexFile != null) {
- RandomAccessFile raf = null;
- try {
- raf = new RandomAccessFile(indexFile, "r");
- raf.seek(writtenOffsetOffset);
-
- for (int nFiles = 0; nFiles < numEntries; nFiles++) {
- // Read the name bytes
- int zfieNameBytesLen = raf.readInt();
- byte [] zfieNameBytes = new byte[zfieNameBytesLen];
- raf.read(zfieNameBytes);
- String eName = new String(zfieNameBytes, "UTF-8");
-
- // Read isDir
- boolean eIsDir = raf.readByte() == (byte)0 ? false : true;
-
- // Read offset of bytes in the real Jar/Zip file
- int eOffset = raf.readInt();
-
- // Read size of the file in the real Jar/Zip file
- int eSize = raf.readInt();
-
- // Read compressed size of the file in the real Jar/Zip file
- int eCsize = raf.readInt();
-
- // Read java time stamp of the file in the real Jar/Zip file
- long eJavaTimestamp = raf.readLong();
-
- ZipFileIndexEntry rfie = new ZipFileIndexEntry(dirName, eName);
- rfie.isDir = eIsDir;
- rfie.offset = eOffset;
- rfie.size = eSize;
- rfie.compressedSize = eCsize;
- rfie.javatime = eJavaTimestamp;
- entries.add(rfie);
- }
- } catch (Throwable t) {
- // Do nothing
- } finally {
- try {
- if (raf == null) {
- raf.close();
- }
- } catch (Throwable t) {
- // Do nothing
- }
- }
- }
- }
-
- entriesInited = true;
- }
-
- List<ZipFileIndexEntry> getEntriesAsCollection() {
- initEntries();
-
- return entries;
- }
- }
-
- private boolean readIndex() {
- if (triedToReadIndex || !usePreindexedCache) {
- return false;
- }
-
- boolean ret = false;
- lock.lock();
- try {
- triedToReadIndex = true;
- RandomAccessFile raf = null;
- try {
- File indexFileName = getIndexFile();
- raf = new RandomAccessFile(indexFileName, "r");
-
- long fileStamp = raf.readLong();
- if (zipFile.lastModified() != fileStamp) {
- ret = false;
- } else {
- directories = new HashMap<String, DirectoryEntry>();
- int numDirs = raf.readInt();
- for (int nDirs = 0; nDirs < numDirs; nDirs++) {
- int dirNameBytesLen = raf.readInt();
- byte [] dirNameBytes = new byte[dirNameBytesLen];
- raf.read(dirNameBytes);
-
- String dirNameStr = new String(dirNameBytes, "UTF-8");
- DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
- de.numEntries = raf.readInt();
- de.writtenOffsetOffset = raf.readLong();
- directories.put(dirNameStr, de);
- }
- ret = true;
- zipFileLastModified = fileStamp;
- }
- } catch (Throwable t) {
- // Do nothing
- } finally {
- if (raf != null) {
- try {
- raf.close();
- } catch (Throwable tt) {
- // Do nothing
- }
- }
- }
- if (ret == true) {
- readFromIndex = true;
- }
- }
- finally {
- lock.unlock();
- }
-
- return ret;
- }
-
- private boolean writeIndex() {
- boolean ret = false;
- if (readFromIndex || !usePreindexedCache) {
- return true;
- }
-
- if (!writeIndex) {
- return true;
- }
-
- File indexFile = getIndexFile();
- if (indexFile == null) {
- return false;
- }
-
- RandomAccessFile raf = null;
- long writtenSoFar = 0;
- try {
- raf = new RandomAccessFile(indexFile, "rw");
-
- raf.writeLong(zipFileLastModified);
- writtenSoFar += 8;
-
-
- Iterator<String> iterDirName = directories.keySet().iterator();
- List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
- Map<String, Long> offsets = new HashMap<String, Long>();
- raf.writeInt(directories.keySet().size());
- writtenSoFar += 4;
-
- while(iterDirName.hasNext()) {
- String dirName = iterDirName.next();
- DirectoryEntry dirEntry = directories.get(dirName);
-
- directoriesToWrite.add(dirEntry);
-
- // Write the dir name bytes
- byte [] dirNameBytes = dirName.getBytes("UTF-8");
- int dirNameBytesLen = dirNameBytes.length;
- raf.writeInt(dirNameBytesLen);
- writtenSoFar += 4;
-
- raf.write(dirNameBytes);
- writtenSoFar += dirNameBytesLen;
-
- // Write the number of files in the dir
- List dirEntries = dirEntry.getEntriesAsCollection();
- raf.writeInt(dirEntries.size());
- writtenSoFar += 4;
-
- offsets.put(dirName, new Long(writtenSoFar));
-
- // Write the offset of the file's data in the dir
- dirEntry.writtenOffsetOffset = 0L;
- raf.writeLong(0L);
- writtenSoFar += 8;
- }
-
- for (DirectoryEntry de : directoriesToWrite) {
- // Fix up the offset in the directory table
- long currFP = raf.getFilePointer();
-
- long offsetOffset = offsets.get(de.dirName).longValue();
- raf.seek(offsetOffset);
- raf.writeLong(writtenSoFar);
-
- raf.seek(currFP);
-
- // Now write each of the files in the DirectoryEntry
- List<ZipFileIndexEntry> entries = de.getEntriesAsCollection();
- for (ZipFileIndexEntry zfie : entries) {
- // Write the name bytes
- byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
- int zfieNameBytesLen = zfieNameBytes.length;
- raf.writeInt(zfieNameBytesLen);
- writtenSoFar += 4;
- raf.write(zfieNameBytes);
- writtenSoFar += zfieNameBytesLen;
-
- // Write isDir
- raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
- writtenSoFar += 1;
-
- // Write offset of bytes in the real Jar/Zip file
- raf.writeInt(zfie.offset);
- writtenSoFar += 4;
-
- // Write size of the file in the real Jar/Zip file
- raf.writeInt(zfie.size);
- writtenSoFar += 4;
-
- // Write compressed size of the file in the real Jar/Zip file
- raf.writeInt(zfie.compressedSize);
- writtenSoFar += 4;
-
- // Write java time stamp of the file in the real Jar/Zip file
- raf.writeLong(zfie.getLastModified());
- writtenSoFar += 8;
- }
- }
- } catch (Throwable t) {
- // Do nothing
- } finally {
- try {
- if (raf != null) {
- raf.close();
- }
- } catch(IOException ioe) {
- // Do nothing
- }
- }
-
- return ret;
- }
-
- public boolean writeZipIndex() {
- lock.lock();
- try {
- return writeIndex();
- }
- finally {
- lock.unlock();
- }
- }
-
- private File getIndexFile() {
- if (zipIndexFile == null) {
- if (zipFile == null) {
- return null;
- }
-
- zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
- zipFile.getName() + ".index");
- }
-
- return zipIndexFile;
- }
-
- public File getZipFile() {
- return zipFile;
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java Thu Jun 12 13:19:16 2008 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright 2007-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.zip;
-
-import java.io.File;
-
-public final class ZipFileIndexEntry implements Comparable<ZipFileIndexEntry> {
- public static final ZipFileIndexEntry[] EMPTY_ARRAY = {};
-
- // Directory related
- String dir;
- boolean isDir;
-
- // File related
- String name;
-
- int offset;
- int size;
- int compressedSize;
- long javatime;
-
- private int nativetime;
-
- public ZipFileIndexEntry(String path) {
- int separator = path.lastIndexOf(File.separatorChar);
- if (separator == -1) {
- dir = "".intern();
- name = path;
- } else {
- dir = path.substring(0, separator).intern();
- name = path.substring(separator + 1);
- }
- }
-
- public ZipFileIndexEntry(String directory, String name) {
- this.dir = directory.intern();
- this.name = name;
- }
-
- public String getName() {
- if (dir == null || dir.length() == 0) {
- return name;
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append(dir);
- sb.append(File.separatorChar);
- sb.append(name);
- return sb.toString();
- }
-
- public String getFileName() {
- return name;
- }
-
- public long getLastModified() {
- if (javatime == 0) {
- javatime = dosToJavaTime(nativetime);
- }
- return javatime;
- }
-
- // From java.util.zip
- private static long dosToJavaTime(int nativetime) {
- // Bootstrap build problems prevent me from using the code directly
- // Convert the raw/native time to a long for now
- return (long)nativetime;
- }
-
- void setNativeTime(int natTime) {
- nativetime = natTime;
- }
-
- public boolean isDirectory() {
- return isDir;
- }
-
- public int compareTo(ZipFileIndexEntry other) {
- String otherD = other.dir;
- if (dir != otherD) {
- int c = dir.compareTo(otherD);
- if (c != 0)
- return c;
- }
- return name.compareTo(other.name);
- }
-
-
- public String toString() {
- return isDir ? ("Dir:" + dir + " : " + name) :
- (dir + ":" + name);
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Mon Jun 16 22:23:33 2008 -0700
@@ -26,10 +26,10 @@
package com.sun.tools.javadoc;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.file.Old199;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
-import com.sun.tools.javac.util.Old199;
import java.io.File;
import java.util.EnumSet;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Mon Jun 16 22:23:33 2008 -0700
@@ -29,19 +29,14 @@
import java.util.Collection;
-import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.*;
-import com.sun.tools.javac.jvm.ClassReader;
-import com.sun.tools.javac.jvm.ClassWriter;
+import com.sun.tools.javac.file.Paths;
import com.sun.tools.javac.parser.DocCommentScanner;
-import com.sun.tools.javac.util.Paths;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
-import com.sun.javadoc.LanguageVersion;
-import static com.sun.javadoc.LanguageVersion.*;
/**
* This class could be the main entry point for Javadoc when Javadoc is used as a
@@ -147,7 +142,7 @@
} else if (isValidPackageName(name)) {
names = names.append(name);
} else if (name.endsWith(".java")) {
- docenv.error(null, "main.file_not_found", name);;
+ docenv.error(null, "main.file_not_found", name);
} else {
docenv.error(null, "main.illegal_package_name", name);
}
--- a/langtools/src/share/classes/com/sun/tools/javap/JavapFileManager.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javap/JavapFileManager.java Mon Jun 16 22:23:33 2008 -0700
@@ -32,9 +32,9 @@
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic;
-import com.sun.tools.javac.util.JavacFileManager;
/**
* javap's implementation of JavaFileManager.
--- a/langtools/test/tools/javac/6304921/TestLog.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/6304921/TestLog.java Mon Jun 16 22:23:33 2008 -0700
@@ -32,12 +32,12 @@
import java.net.URI;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.JCDiagnostic;
import com.sun.tools.javac.util.Options;
--- a/langtools/test/tools/javac/6589361/T6589361.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/6589361/T6589361.java Mon Jun 16 22:23:33 2008 -0700
@@ -4,8 +4,8 @@
* @summary 6589361:Failing building ct.sym file as part of the control build
*/
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JavacFileManager;
import java.io.File;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
--- a/langtools/test/tools/javac/T6358024.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/T6358024.java Mon Jun 16 22:23:33 2008 -0700
@@ -35,6 +35,7 @@
import javax.tools.*;
import com.sun.source.util.*;
import com.sun.tools.javac.api.*;
+import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/langtools/test/tools/javac/T6358166.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/T6358166.java Mon Jun 16 22:23:33 2008 -0700
@@ -32,6 +32,7 @@
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;
+import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/langtools/test/tools/javac/T6358168.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/T6358168.java Mon Jun 16 22:23:33 2008 -0700
@@ -33,6 +33,7 @@
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;
+import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/langtools/test/tools/javac/T6705935.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/T6705935.java Mon Jun 16 22:23:33 2008 -0700
@@ -30,7 +30,7 @@
import java.io.*;
import java.util.*;
import javax.tools.*;
-import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.file.*;
public class T6705935 {
public static void main(String... args) throws Exception {
--- a/langtools/test/tools/javac/api/T6358786.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/api/T6358786.java Mon Jun 16 22:23:33 2008 -0700
@@ -30,7 +30,7 @@
*/
import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.util.JavacFileManager;
+import com.sun.tools.javac.file.JavacFileManager;
import java.util.Arrays;
import javax.lang.model.util.Elements;
--- a/langtools/test/tools/javac/api/TestResolveIdent.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/api/TestResolveIdent.java Mon Jun 16 22:23:33 2008 -0700
@@ -30,8 +30,8 @@
*/
import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.JavacFileManager;
import java.io.File;
import java.io.IOException;
import javax.lang.model.element.TypeElement;
--- a/langtools/test/tools/javac/util/filemanager/TestName.java Thu Jun 12 13:19:16 2008 -0700
+++ b/langtools/test/tools/javac/util/filemanager/TestName.java Mon Jun 16 22:23:33 2008 -0700
@@ -29,7 +29,7 @@
* @author Peter von der Ah\u00e9
*/
-import com.sun.tools.javac.util.JavacFileManager;
+import com.sun.tools.javac.file.JavacFileManager;
public class TestName {
public static void main(String... args) {