6962236: backport JavacFileManager fixes from 7 to 6-open
authorjjg
Tue Jun 22 18:30:16 2010 -0700 (2 years ago)
changeset 1065c2858bccb3f
parent 1057e27c39553e1
child 10727f03394a69d
6962236: backport JavacFileManager fixes from 7 to 6-open
6410637: Make decision on deprecated methods in DefaultFileManager and BaseFileObject.
6419701: DefaultFileManager clean up: URI.create
6483788: DefaultFileManager.ZipFileObject.toUri() fails to escape space characters
6501502: JSR 199: FileObject.toUri should return file:///c:/ or file:/c:/ not file://c:/
6508981: cleanup file separator handling in JavacFileManager
6625520: javac handles missing entries on classpath badly
6705935: javac reports path name of entry in ZipFileIndex incorectly
6705945: com.sun.tools.javac.zip files do not have valid copyright
6714364: refactor javac File handling code into new javac.file package
6714365: refactor JavacFileManager to move nested classes to top level
6743107: clean up use of static caches in file manager
6794582: javadoc should read files using a FileManager
6832154: refactor Paths to be just a utility class for JavacFileManager
6838467: JSR199 FileObjects don't obey general contract of equals.
6877206: JavaFileObject.toUri returns bogus URI (win)
6877223: tests @ignored because of issues with File.toURI on Windows
6885123: JavaFileObject getName issues
6907660: stupid typo in ZipFileIndex guarantees NPE
6930076: "null" can incorrectly appear in error message compiler.err.error.reading.file
Reviewed-by: darcy
src/share/classes/com/sun/tools/apt/main/JavaCompiler.java
src/share/classes/com/sun/tools/apt/main/Main.java
src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java
src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java
src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java
src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java
src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java
src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
src/share/classes/com/sun/tools/javac/api/JavacTool.java
src/share/classes/com/sun/tools/javac/file/BaseFileObject.java
src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java
src/share/classes/com/sun/tools/javac/file/FSInfo.java
src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
src/share/classes/com/sun/tools/javac/file/Paths.java
src/share/classes/com/sun/tools/javac/file/RegularFileObject.java
src/share/classes/com/sun/tools/javac/file/RelativePath.java
src/share/classes/com/sun/tools/javac/file/SymbolArchive.java
src/share/classes/com/sun/tools/javac/file/ZipArchive.java
src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java
src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java
src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
src/share/classes/com/sun/tools/javac/main/Main.java
src/share/classes/com/sun/tools/javac/parser/Scanner.java
src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
src/share/classes/com/sun/tools/javac/util/BaseFileManager.java
src/share/classes/com/sun/tools/javac/util/BaseFileObject.java
src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java
src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
src/share/classes/com/sun/tools/javac/util/JavacFileManager.java
src/share/classes/com/sun/tools/javac/util/Log.java
src/share/classes/com/sun/tools/javac/util/Old199.java
src/share/classes/com/sun/tools/javac/util/Paths.java
src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java
src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java
src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
src/share/classes/com/sun/tools/javadoc/DocEnv.java
src/share/classes/com/sun/tools/javadoc/DocImpl.java
src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java
src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java
src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java
src/share/classes/com/sun/tools/javadoc/JavadocTool.java
src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java
test/tools/javac/6304921/TestLog.java
test/tools/javac/6508981/TestInferBinaryName.java
test/tools/javac/6508981/p/A.java
test/tools/javac/6589361/T6589361.java
test/tools/javac/T6358024.java
test/tools/javac/T6358166.java
test/tools/javac/T6358168.java
test/tools/javac/T6625520.java
test/tools/javac/T6705935.java
test/tools/javac/T6725036.java
test/tools/javac/api/6411310/T6411310.java
test/tools/javac/api/6411310/Test.java
test/tools/javac/api/6440333/T6440333.java
test/tools/javac/api/6440528/T6440528.java
test/tools/javac/api/6733837/T6733837.java
test/tools/javac/api/Sibling.java
test/tools/javac/api/T6358786.java
test/tools/javac/api/T6483788.java
test/tools/javac/api/T6501502.java
test/tools/javac/api/T6838467.java
test/tools/javac/api/T6877206.java
test/tools/javac/api/TestResolveIdent.java
test/tools/javac/util/filemanager/TestName.java
--- a/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java Tue Jun 22 18:30:16 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,20 +26,14 @@ package com.sun.tools.apt.main;
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.*;
@@ -239,6 +233,7 @@ public class JavaCompiler extends com.su
ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>();
try {
+ JavacFileManager fm = (JavacFileManager)fileManager;
//parse all files
ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>();
for (List<String> l = filenames; l.nonEmpty(); l = l.tail) {
@@ -256,7 +251,8 @@ public class JavaCompiler extends com.su
continue;
}
}
- trees.append(parse(l.head));
+ JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next();
+ trees.append(parse(fo));
}
//enter symbols for all files
--- a/src/share/classes/com/sun/tools/apt/main/Main.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/main/Main.java Tue Jun 22 18:30:16 2010 -0700
@@ -26,7 +26,6 @@ package com.sun.tools.apt.main;
package com.sun.tools.apt.main;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
@@ -37,14 +36,15 @@ import java.util.Map;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
-import java.util.Collection;
import java.net.URLClassLoader;
import java.net.URL;
-import java.io.File;
import java.net.MalformedURLException;
-import com.sun.tools.javac.util.Paths;
+import javax.tools.JavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
@@ -55,6 +55,8 @@ import com.sun.tools.apt.comp.UsageMessa
import com.sun.tools.apt.comp.UsageMessageNeededException;
import com.sun.tools.apt.util.Bark;
import com.sun.mirror.apt.AnnotationProcessorFactory;
+
+import static com.sun.tools.javac.file.Paths.pathToURLs;
/** This class provides a commandline interface to the apt build-time
* tool.
@@ -766,6 +768,7 @@ public class Main {
providedFactory = factory;
Context context = new Context();
+ JavacFileManager.preRegister(context);
options = Options.instance(context);
Bark bark;
@@ -778,7 +781,6 @@ public class Main {
// For testing: assume all arguments in forcedOpts are
// prefixed to command line arguments.
processArgs(forcedOpts);
-
/*
* A run of apt only gets passed the most recently generated
@@ -862,14 +864,14 @@ public class Main {
}
origOptions = Collections.unmodifiableMap(origOptions);
+ JavacFileManager fm = (JavacFileManager) context.get(JavaFileManager.class);
{
// Note: it might be necessary to check for an empty
// component ("") of the source path or class path
- Paths paths = Paths.instance(context);
String sourceDest = options.get("-s");
- if (paths.sourcePath() != null) {
- for(File f: paths.sourcePath())
+ if (fm.hasLocation(StandardLocation.SOURCE_PATH)) {
+ for(File f: fm.getLocation(StandardLocation.SOURCE_PATH))
augmentedSourcePath += (f + File.pathSeparator);
augmentedSourcePath += (sourceDest == null)?".":sourceDest;
} else {
@@ -880,8 +882,8 @@ public class Main {
}
String classDest = options.get("-d");
- if (paths.userClassPath() != null) {
- for(File f: paths.userClassPath())
+ if (fm.hasLocation(StandardLocation.CLASS_PATH)) {
+ for(File f: fm.getLocation(StandardLocation.CLASS_PATH))
baseClassPath += (f + File.pathSeparator);
// put baseClassPath into map to handle any
// value needed for the classloader
@@ -908,9 +910,8 @@ public class Main {
* uses.
*/
String aptclasspath = "";
- Paths paths = Paths.instance(context);
String bcp = "";
- Collection<File> bootclasspath = paths.bootClassPath();
+ Iterable<? extends File> bootclasspath = fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH);
if (bootclasspath != null) {
for(File f: bootclasspath)
@@ -1271,59 +1272,4 @@ public class Main {
}
}
}
-
- // Borrowed from DocletInvoker
- /**
- * Utility method for converting a search path string to an array
- * of directory and JAR file URLs.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
- */
- static URL[] pathToURLs(String path) {
- StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
- URL[] urls = new URL[st.countTokens()];
- int count = 0;
- while (st.hasMoreTokens()) {
- URL url = fileToURL(new File(st.nextToken()));
- if (url != null) {
- urls[count++] = url;
- }
- }
- if (urls.length != count) {
- URL[] tmp = new URL[count];
- System.arraycopy(urls, 0, tmp, 0, count);
- urls = tmp;
- }
- return urls;
- }
-
- /**
- * Returns the directory or JAR file URL corresponding to the specified
- * local file name.
- *
- * @param file the File object
- * @return the resulting directory or JAR file URL, or null if unknown
- */
- static URL fileToURL(File file) {
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- name = file.getAbsolutePath();
- }
- name = name.replace(File.separatorChar, '/');
- if (!name.startsWith("/")) {
- name = "/" + name;
- }
- // If the file does not exist, then assume that it's a directory
- if (!file.isFile()) {
- name = name + "/";
- }
- try {
- return new URL("file", "", name);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("file");
- }
- }
}
--- a/src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/apt/mirror/util/SourcePositionImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -67,15 +67,15 @@ public class SourcePositionImpl implemen
public String toString() {
int ln = line();
return (ln == Position.NOPOS)
- ? sourcefile.toString()
- : sourcefile + ":" + ln;
+ ? sourcefile.getName()
+ : sourcefile.getName() + ":" + ln;
}
/**
* {@inheritDoc}
*/
public File file() {
- return new File(sourcefile.toString());
+ return new File(sourcefile.toUri());
}
/**
--- a/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,12 +25,11 @@
package com.sun.tools.doclets.formats.html.markup;
-import com.sun.tools.doclets.internal.toolkit.*;
-
-import com.sun.javadoc.*;
import java.io.*;
import java.util.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
+
+import com.sun.javadoc.*;
+import com.sun.tools.doclets.internal.toolkit.*;
/**
@@ -56,8 +55,9 @@ public abstract class HtmlDocWriter exte
super(configuration,
null, configuration.destDirName + filename,
configuration.docencoding);
+ // use File to normalize file separators
configuration.message.notice("doclet.Generating_0",
- configuration.destDirName + filename);
+ new File(configuration.destDirName, filename));
}
public HtmlDocWriter(Configuration configuration,
@@ -65,10 +65,10 @@ public abstract class HtmlDocWriter exte
super(configuration,
configuration.destDirName + path, filename,
configuration.docencoding);
+ // use File to normalize file separators
configuration.message.notice("doclet.Generating_0",
- configuration.destDirName +
- ((path.length() > 0)?
- path + File.separator: "") + filename);
+ new File(configuration.destDirName,
+ ((path.length() > 0)? path + File.separator: "") + filename));
}
/**
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Tue Jun 22 18:30:16 2010 -0700
@@ -81,46 +81,14 @@ public class MessageRetriever {
}
/**
- * get and format message string from resource
- *
- * @param key selects message from resource
- */
- public String getText(String key) {
- return getText(key, (String)null);
- }
-
- /**
* Get and format message string from resource
*
* @param key selects message from resource
- * @param a1 Argument, to be repalced in the message.
- */
- public String getText(String key, String a1) {
- return getText(key, a1, null);
- }
-
- /**
- * Get and format message string from resource
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public String getText(String key, String a1, String a2) {
- return getText(key, a1, a2, null);
- }
-
- /**
- * Get and format message string from resource
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
+ * @param args arguments to be replaced in the message.
* @throws MissingResourceException when the key does not
* exist in the properties file.
*/
- public String getText(String key, String a1, String a2, String a3) throws MissingResourceException {
+ public String getText(String key, Object... args) throws MissingResourceException {
if (messageRB == null) {
try {
messageRB = ResourceBundle.getBundle(resourcelocation);
@@ -130,7 +98,7 @@ public class MessageRetriever {
}
}
String message = messageRB.getString(key);
- return MessageFormat.format(message, a1, a2, a3);
+ return MessageFormat.format(message, args);
}
/**
@@ -195,261 +163,61 @@ public class MessageRetriever {
*
* @param pos the position of the source
* @param key selects message from resource
- */
- public void error(SourcePosition pos, String key) {
- printError(pos, getText(key));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param key selects message from resource
- */
- public void error(String key) {
- printError(getText(key));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void error(SourcePosition pos, String key, String a1) {
- printError(pos, getText(key, a1));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void error(String key, String a1) {
- printError(getText(key, a1));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void error(SourcePosition pos, String key, String a1, String a2) {
- printError(pos, getText(key, a1, a2));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void error(String key, String a1, String a2) {
- printError(getText(key, a1, a2));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void error(SourcePosition pos, String key, String a1, String a2, String a3) {
- printError(pos, getText(key, a1, a2, a3));
- }
-
- /**
- * Print error message, increment error count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void error(String key, String a1, String a2, String a3) {
- printError(getText(key, a1, a2, a3));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- */
- public void warning(SourcePosition pos, String key) {
- printWarning(pos, getText(key));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param key selects message from resource
- */
- public void warning(String key) {
- printWarning(getText(key));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void warning(SourcePosition pos, String key, String a1) {
- printWarning(pos, getText(key, a1));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void warning(String key, String a1) {
- printWarning(getText(key, a1));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void warning(SourcePosition pos, String key, String a1, String a2) {
- printWarning(pos, getText(key, a1, a2));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void warning(String key, String a1, String a2) {
- printWarning(getText(key, a1, a2));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void warning(SourcePosition pos, String key, String a1, String a2, String a3) {
- printWarning(pos, getText(key, a1, a2, a3));
- }
-
- /**
- * Print warning message, increment warning count.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void warning(String key, String a1, String a2, String a3) {
- printWarning(getText(key, a1, a2, a3));
- }
-
- /**
- * Print a message.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- */
- public void notice(SourcePosition pos, String key) {
- printNotice(pos, getText(key));
- }
-
- /**
- * Print a message.
- *
- * @param key selects message from resource
- */
- public void notice(String key) {
- printNotice(getText(key));
- }
-
- /**
- * Print a message.
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void notice(SourcePosition pos, String key, String a1) {
- printNotice(pos, getText(key, a1));
- }
-
- /**
- * Print a message.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- */
- public void notice(String key, String a1) {
- printNotice(getText(key, a1));
- }
-
- /**
- * Print a message.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void notice(SourcePosition pos, String key, String a1, String a2) {
- printNotice(pos, getText(key, a1, a2));
- }
-
- /**
- * Print a message.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- */
- public void notice(String key, String a1, String a2) {
- printNotice(getText(key, a1, a2));
- }
-
- /**
- * Print a message.
- *
- * @param pos the position of the source
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void notice(SourcePosition pos, String key, String a1, String a2, String a3) {
- printNotice(pos, getText(key, a1, a2, a3));
- }
-
- /**
- * Print a message.
- *
- * @param key selects message from resource
- * @param a1 first argument to be replaced in the message.
- * @param a2 second argument to be replaced in the message.
- * @param a3 third argument to be replaced in the message.
- */
- public void notice(String key, String a1, String a2, String a3) {
- printNotice(getText(key, a1, a2, a3));
+ * @param args arguments to be replaced in the message.
+ */
+ public void error(SourcePosition pos, String key, Object... args) {
+ printError(pos, getText(key, args));
+ }
+
+ /**
+ * Print error message, increment error count.
+ *
+ * @param key selects message from resource
+ * @param args arguments to be replaced in the message.
+ */
+ public void error(String key, Object... args) {
+ printError(getText(key, args));
+ }
+
+ /**
+ * Print warning message, increment warning count.
+ *
+ * @param pos the position of the source
+ * @param key selects message from resource
+ * @param args arguments to be replaced in the message.
+ */
+ public void warning(SourcePosition pos, String key, Object... args) {
+ printWarning(pos, getText(key, args));
+ }
+
+ /**
+ * Print warning message, increment warning count.
+ *
+ * @param key selects message from resource
+ * @param args arguments to be replaced in the message.
+ */
+ public void warning(String key, Object... args) {
+ printWarning(getText(key, args));
+ }
+
+ /**
+ * Print a message.
+ *
+ * @param pos the position of the source
+ * @param key selects message from resource
+ * @param args arguments to be replaced in the message.
+ */
+ public void notice(SourcePosition pos, String key, Object... args) {
+ printNotice(pos, getText(key, args));
+ }
+
+ /**
+ * Print a message.
+ *
+ * @param key selects message from resource
+ * @param args arguments to be replaced in the message.
+ */
+ public void notice(String key, Object... args) {
+ printNotice(getText(key, args));
}
}
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,10 +25,12 @@
package com.sun.tools.doclets.internal.toolkit.util;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.javadoc.*;
import java.io.*;
import java.util.*;
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+import com.sun.tools.doclets.internal.toolkit.*;
/**
* Converts Java Source Code to HTML.
@@ -123,16 +125,27 @@ public class SourceToHTMLConverter {
if (cd == null || outputdir == null) {
return;
}
- File file;
- SourcePosition sp = cd.position();
- if (sp == null || (file = sp.file()) == null) {
- return;
- }
try {
+ SourcePosition sp = cd.position();
+ if (sp == null)
+ return;
+ Reader r;
+ // temp hack until we can update SourcePosition API.
+ if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) {
+ FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject();
+ if (fo == null)
+ return;
+ r = fo.openReader(true);
+ } else {
+ File file = sp.file();
+ if (file == null)
+ return;
+ r = new FileReader(file);
+ }
+ LineNumberReader reader = new LineNumberReader(r);
int lineno = 1;
String line;
StringBuffer output = new StringBuffer();
- LineNumberReader reader = new LineNumberReader(new FileReader(file));
try {
while ((line = reader.readLine()) != null) {
output.append(formatLine(line, configuration.sourcetab, lineno));
@@ -260,12 +273,12 @@ public class SourceToHTMLConverter {
* @param docs the array of <code>Doc</code>s to add anchors for.
* @param hash the <code>HashMap</code> to add to.
*/
- protected static void addToHash(Doc[] docs, HashMap hash) {
+ protected static void addToHash(Doc[] docs, HashMap<Integer,String> hash) {
if(docs == null) {
return;
}
for(int i = 0; i < docs.length; i++) {
- hash.put(new Integer(docs[i].position().line()), getAnchor(docs[i]));
+ hash.put(docs[i].position().line(), getAnchor(docs[i]));
}
}
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,10 +25,11 @@
package com.sun.tools.doclets.internal.toolkit.util;
+import java.io.*;
+import java.util.*;
+
import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;
-import java.util.*;
-import java.io.*;
/**
* Utilities Class for Doclets.
@@ -579,7 +580,7 @@ public class Util {
* @param docencoding Encoding to be used for this file.
* @exception IOException Exception raised by the FileWriter is passed on
* to next level.
- * @exception UnSupportedEncodingException Exception raised by the
+ * @exception UnsupportedEncodingException Exception raised by the
* OutputStreamWriter is passed on to next level.
* @return Writer Writer for the file getting generated.
* @see java.io.FileOutputStream
@@ -598,9 +599,7 @@ public class Util {
fos = new FileOutputStream(filename);
}
if (docencoding == null) {
- OutputStreamWriter oswriter = new OutputStreamWriter(fos);
- docencoding = oswriter.getEncoding();
- return oswriter;
+ return new OutputStreamWriter(fos);
} else {
return new OutputStreamWriter(fos, docencoding);
}
--- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -42,6 +42,7 @@ import com.sun.tools.javac.code.*;
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/src/share/classes/com/sun/tools/javac/api/JavacTool.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTool.java Tue Jun 22 18:30:16 2010 -0700
@@ -31,7 +31,6 @@ import java.io.PrintWriter;
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 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;
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,6 +25,7 @@
package com.sun.tools.javac.jvm;
+import java.net.URISyntaxException;
import java.io.*;
import java.net.URI;
import java.nio.CharBuffer;
@@ -42,6 +43,7 @@ import com.sun.tools.javac.code.Type.*;
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;
@@ -1047,7 +1049,7 @@ public class ClassReader extends ClassFi
void readClassAttr(ClassSymbol c, Name attrName, int attrLen) {
if (attrName == names.SourceFile) {
Name n = readName(nextChar());
- c.sourcefile = new SourceFileObject(n);
+ c.sourcefile = new SourceFileObject(n, c.flatname);
} else if (attrName == names.InnerClasses) {
readInnerClasses(c);
} else if (allowGenerics && attrName == names.Signature) {
@@ -2212,69 +2214,103 @@ public class ClassReader extends ClassFi
/** The file's name.
*/
private Name name;
-
- public SourceFileObject(Name name) {
+ private Name flatname;
+
+ public SourceFileObject(Name name, Name flatname) {
+ super(null); // no file manager; never referenced for this file object
this.name = name;
- }
-
+ this.flatname = flatname;
+ }
+
+ //@Override
+ public URI toUri() {
+ try {
+ return new URI(null, name.toString(), null);
+ } catch (URISyntaxException e) {
+ throw new CannotCreateUriError(name.toString(), e);
+ }
+ }
+
+ //@Override
+ public String getName() {
+ return name.toString();
+ }
+
+ //@Override
+ public String getShortName() {
+ return getName();
+ }
+
+ //@Override
+ public JavaFileObject.Kind getKind() {
+ return getKind(getName());
+ }
+
+ //@Override
public InputStream openInputStream() {
throw new UnsupportedOperationException();
}
+ //@Override
public OutputStream openOutputStream() {
throw new UnsupportedOperationException();
}
- public Reader openReader() {
+ //@Override
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
throw new UnsupportedOperationException();
}
+ //@Override
+ public Reader openReader(boolean ignoreEncodingErrors) {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
public Writer openWriter() {
throw new UnsupportedOperationException();
}
- /** @deprecated see bug 6410637 */
- @Deprecated
- public String getName() {
- return name.toString();
- }
-
+ //@Override
public long getLastModified() {
throw new UnsupportedOperationException();
}
+ //@Override
public boolean delete() {
throw new UnsupportedOperationException();
}
- public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
- throw new UnsupportedOperationException();
- }
-
- @Override
+ //@Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ return flatname.toString();
+ }
+
+ //@Override
+ public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
+ return true; // fail-safe mode
+ }
+
+ /**
+ * Check if two file objects are equal.
+ * SourceFileObjects are just placeholder objects for the value of a
+ * SourceFile attribute, and do not directly represent specific files.
+ * Two SourceFileObjects are equal if their names are equal.
+ */
+ //@Override
public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
if (!(other instanceof SourceFileObject))
return false;
SourceFileObject o = (SourceFileObject) other;
return name.equals(o.name);
}
- @Override
+ //@Override
public int hashCode() {
return name.hashCode();
}
-
- public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) {
- return true; // fail-safe mode
- }
-
- public URI toUri() {
- return URI.create(name.toString());
- }
-
- public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
- throw new UnsupportedOperationException();
- }
-
}
}
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Tue Jun 22 18:30:16 2010 -0700
@@ -37,6 +37,7 @@ import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
@@ -1546,13 +1547,8 @@ public class ClassWriter extends ClassFi
// the last possible moment because the sourcefile may be used
// elsewhere in error diagnostics. Fixes 4241573.
//databuf.appendChar(c.pool.put(c.sourcefile));
- String filename = c.sourcefile.toString();
- int sepIdx = filename.lastIndexOf(File.separatorChar);
- // Allow '/' as separator on all platforms, e.g., on Win32.
- int slashIdx = filename.lastIndexOf('/');
- if (slashIdx > sepIdx) sepIdx = slashIdx;
- if (sepIdx >= 0) filename = filename.substring(sepIdx + 1);
- databuf.appendChar(c.pool.put(names.fromString(filename)));
+ String simpleName = BaseFileObject.getSimpleName(c.sourcefile);
+ databuf.appendChar(c.pool.put(names.fromString(simpleName)));
endAttr(alenIdx);
acount++;
}
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Jun 22 18:30:16 2010 -0700
@@ -44,6 +44,7 @@ import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
+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.*;
@@ -553,7 +554,7 @@ public class JavaCompiler implements Cla
inputFiles.add(filename);
return filename.getCharContent(false);
} catch (IOException e) {
- log.error("error.reading.file", filename, e.getLocalizedMessage());
+ log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
return null;
}
}
@@ -716,7 +717,7 @@ public class JavaCompiler implements Cla
try {
tree = parse(filename, filename.getCharContent(false));
} catch (IOException e) {
- log.error("error.reading.file", filename, e);
+ log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
} finally {
log.useSource(prev);
--- a/src/share/classes/com/sun/tools/javac/main/Main.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/main/Main.java Tue Jun 22 18:30:16 2010 -0700
@@ -32,6 +32,8 @@ import java.util.MissingResourceExceptio
import java.util.MissingResourceException;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.file.CacheFSInfo;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.JavacOption.Option;
import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
@@ -331,13 +333,13 @@ public class Main {
return EXIT_CMDERR;
}
- List<File> filenames;
+ List<File> files;
try {
- filenames = processArgs(CommandLine.parse(args));
- if (filenames == null) {
+ files = processArgs(CommandLine.parse(args));
+ if (files == null) {
// null signals an error in options, abort
return EXIT_CMDERR;
- } else if (filenames.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
+ } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
// it is allowed to compile nothing if just asking for help or version info
if (options.get("-help") != null
|| options.get("-X") != null
@@ -362,17 +364,23 @@ public class Main {
context.put(Log.outKey, out);
+ // allow System property in following line as a Mustang legacy
+ boolean batchMode = (options.get("nonBatchMode") == null
+ && System.getProperty("nonBatchMode") == null);
+ if (batchMode)
+ CacheFSInfo.preRegister(context);
+
fileManager = context.get(JavaFileManager.class);
comp = JavaCompiler.instance(context);
if (comp == null) return EXIT_SYSERR;
- if (!filenames.isEmpty()) {
+ if (!files.isEmpty()) {
// add filenames to fileObjects
comp = JavaCompiler.instance(context);
List<JavaFileObject> otherFiles = List.nil();
JavacFileManager dfm = (JavacFileManager)fileManager;
- for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(filenames))
+ for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
otherFiles = otherFiles.prepend(fo);
for (JavaFileObject fo : otherFiles)
fileObjects = fileObjects.prepend(fo);
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue Jun 22 18:30:16 2010 -0700
@@ -32,6 +32,7 @@ import java.nio.channels.*;
import java.nio.channels.*;
import java.util.regex.*;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.Source;
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue Jun 22 18:30:16 2010 -0700
@@ -28,6 +28,7 @@ import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
@@ -169,7 +170,6 @@ public class JavacProcessingEnvironment
}
private void initProcessorIterator(Context context, Iterable<? extends Processor> processors) {
- Paths paths = Paths.instance(context);
Log log = Log.instance(context);
Iterator<? extends Processor> processorIterator;
--- a/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Tue Jun 22 18:30:16 2010 -0700
@@ -27,6 +27,8 @@ package com.sun.tools.javac.util;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
@@ -143,8 +145,10 @@ public class DiagnosticFormatter {
sb.append(format_raw((JCDiagnostic) arg));
sb.append(')');
}
+ else if (arg instanceof BaseFileObject)
+ sb.append(((BaseFileObject) arg).getShortName());
else if (arg instanceof JavaFileObject)
- sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg));
+ sb.append(BaseFileObject.getSimpleName((JavaFileObject) arg));
else
sb.append(arg);
sep = ", ";
--- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,12 +25,8 @@
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;
@@ -341,7 +337,7 @@ public class JCDiagnostic implements Dia
*/
public String getSourceName() {
JavaFileObject s = getSource();
- return s == null ? null : JavacFileManager.getJavacFileName(s);
+ return s == null ? null : s.getName();
}
/**
@@ -445,6 +441,8 @@ public class JCDiagnostic implements Dia
Object arg = args[i];
if (arg == null)
strings[i] = null;
+ else if (arg instanceof FileObject)
+ strings[i] = ((FileObject) arg).getName();
else if (arg instanceof JCDiagnostic)
strings[i] = ((JCDiagnostic) arg).getMessage(null);
else
--- a/src/share/classes/com/sun/tools/javac/util/Log.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/Log.java Tue Jun 22 18:30:16 2010 -0700
@@ -33,6 +33,8 @@ import java.util.Set;
import java.util.Set;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.file.BaseFileObject;
+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;
@@ -233,7 +235,10 @@ public class Log {
return name;
}
public CharSequence getName() {
- return JavacFileManager.getJavacBaseFileName(getFile());
+ if (name instanceof BaseFileObject)
+ return ((BaseFileObject) name).getShortName();
+ else
+ return BaseFileObject.getSimpleName(name);
}
public int getLineNumber(int pos) {
return Log.this.getLineNumber(pos);
@@ -522,7 +527,10 @@ public class Log {
return file;
}
public CharSequence getName() {
- return JavacFileManager.getJavacBaseFileName(getFile());
+ if (file instanceof BaseFileObject)
+ return ((BaseFileObject) file).getShortName();
+ else
+ return BaseFileObject.getSimpleName(file);
}
public int getLineNumber(int pos) {
return Log.this.getLineNumber(pos);
@@ -660,7 +668,7 @@ public class Log {
JavaFileObject file = currentSource();
if (file != null)
printLines(errWriter,
- JavacFileManager.getJavacFileName(file) + ":" +
+ file.getName() + ":" +
line + ": " + msg);
printErrLine(pos, errWriter);
}
--- a/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,44 +25,46 @@
package com.sun.tools.javadoc;
-import java.util.*;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
import com.sun.javadoc.*;
import static com.sun.javadoc.LanguageVersion.*;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.TypeTags;
+
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.TypeTags;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Scope;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
-
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.TreeInfo;
-
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.TypeTags.*;
-
-import java.io.File;
-import java.util.Set;
-import java.util.HashSet;
-import java.lang.reflect.Modifier;
/**
* Represents a java class and provides access to information
@@ -274,16 +276,41 @@ public class ClassDocImpl extends Progra
*/
public PackageDoc containingPackage() {
PackageDocImpl p = env.getPackageDoc(tsym.packge());
- SourcePosition po = position();
- if (po != null && p.setDocPath == false && p.zipDocPath == null) {
- //Set the package path if possible
- File packageDir = po.file().getParentFile();
- if (packageDir != null
- && (new File(packageDir, "package.html")).exists()) {
- p.setDocPath(packageDir.getPath());
- } else {
- p.setDocPath(null);
- }
+ if (p.setDocPath == false) {
+ FileObject docPath;
+ try {
+ Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+ ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+
+ docPath = env.fileManager.getFileForInput(
+ location, p.qualifiedName(), "package.html");
+ } catch (IOException e) {
+ docPath = null;
+ }
+
+ if (docPath == null) {
+ // fall back on older semantics of looking in same directory as
+ // source file for this class
+ SourcePosition po = position();
+ if (env.fileManager instanceof StandardJavaFileManager &&
+ po instanceof SourcePositionImpl) {
+ URI uri = ((SourcePositionImpl) po).filename.toUri();
+ if ("file".equals(uri.getScheme())) {
+ File f = new File(uri);
+ File dir = f.getParentFile();
+ if (dir != null) {
+ File pf = new File(dir, "package.html");
+ if (pf.exists()) {
+ StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
+ docPath = sfm.getJavaFileObjects(pf).iterator().next();
+ }
+ }
+
+ }
+ }
+ }
+
+ p.setDocPath(docPath);
}
return p;
}
@@ -1254,7 +1281,7 @@ public class ClassDocImpl extends Progra
*/
public SourcePosition position() {
if (tsym.sourcefile == null) return null;
- return SourcePositionImpl.make(tsym.sourcefile.toString(),
+ return SourcePositionImpl.make(tsym.sourcefile,
(tree==null) ? Position.NOPOS : tree.pos,
lineMap);
}
--- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,23 +25,20 @@
package com.sun.tools.javadoc;
+import java.lang.reflect.Modifier;
import java.util.*;
-import java.lang.reflect.Modifier;
+import javax.tools.JavaFileManager;
import com.sun.javadoc.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.ClassType;
-import com.sun.tools.javac.code.Type.TypeVar;
-import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
-
/**
* Holds the environment for a run of javadoc.
@@ -75,10 +72,6 @@ public class DocEnv {
/** Referenced directly in RootDocImpl. */
JavadocClassReader reader;
- /** The compiler's attribution phase (needed to evaluate
- * constant initializers). */
- Attr attr;
-
/** Javadoc's own version of the compiler's enter phase. */
JavadocEnter enter;
@@ -93,8 +86,6 @@ public class DocEnv {
/** Access filter (public, protected, ...). */
ModifierFilter showAccess;
- private ClassDocImpl runtimeException;
-
/** True if we are using a sentence BreakIterator. */
boolean breakiterator;
@@ -105,6 +96,7 @@ public class DocEnv {
Check chk;
Types types;
+ JavaFileManager fileManager;
/** Allow documenting from class files? */
boolean docClasses = false;
@@ -130,11 +122,11 @@ public class DocEnv {
syms = Symtab.instance(context);
reader = JavadocClassReader.instance0(context);
enter = JavadocEnter.instance0(context);
- attr = Attr.instance(context);
names = Name.Table.instance(context);
externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable"));
chk = Check.instance(context);
types = Types.instance(context);
+ fileManager = context.get(JavaFileManager.class);
// Default. Should normally be reset with setLocale.
this.doclocale = new DocLocale(this, "", breakiterator);
--- a/src/share/classes/com/sun/tools/javadoc/DocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/DocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,11 +25,13 @@
package com.sun.tools.javadoc;
-import com.sun.javadoc.*;
-
import java.io.InputStream;
import java.io.IOException;
import java.text.CollationKey;
+import javax.tools.FileObject;
+
+import com.sun.javadoc.*;
+
import com.sun.tools.javac.util.Position;
/**
@@ -43,7 +45,7 @@ import com.sun.tools.javac.util.Position
* @author Atul M Dambalkar
* @author Neal Gafter (rewrite)
*/
-abstract class DocImpl implements Doc, Comparable<Object> {
+public abstract class DocImpl implements Doc, Comparable<Object> {
/**
* Doc environment
@@ -163,7 +165,7 @@ abstract class DocImpl implements Doc, C
/**
* Utility for subclasses which read HTML documentation files.
*/
- String readHTMLDocumentation(InputStream input, String filename) throws IOException {
+ String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
int filesize = input.available();
byte[] filecontents = new byte[filesize];
input.read(filecontents, 0, filesize);
--- a/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -267,7 +267,7 @@ public abstract class ExecutableMemberDo
*/
public SourcePosition position() {
if (sym.enclClass().sourcefile == null) return null;
- return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(),
+ return SourcePositionImpl.make(sym.enclClass().sourcefile,
(tree==null) ? 0 : tree.pos,
lineMap);
}
--- a/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -260,7 +260,7 @@ public class FieldDocImpl extends Member
*/
public SourcePosition position() {
if (sym.enclClass().sourcefile == null) return null;
- return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(),
+ return SourcePositionImpl.make(sym.enclClass().sourcefile,
(tree==null) ? 0 : tree.pos,
lineMap);
}
--- a/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,15 +25,13 @@
package com.sun.tools.javadoc;
+import java.util.EnumSet;
+import javax.tools.JavaFileObject;
+
import com.sun.tools.javac.code.Symbol.PackageSymbol;
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;
-import javax.tools.JavaFileObject;
/** Javadoc uses an extended class reader that records package.html entries
* @author Neal Gafter
@@ -80,32 +78,7 @@ class JavadocClassReader extends ClassRe
*/
@Override
protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) {
- CharSequence fileName = Old199.getName(fo);
- if (docenv != null && fileName.equals("package.html")) {
- if (fo instanceof JavacFileManager.ZipFileObject) {
- JavacFileManager.ZipFileObject zfo = (JavacFileManager.ZipFileObject) fo;
- String zipName = zfo.getZipName();
- String entryName = zfo.getZipEntryName();
- int lastSep = entryName.lastIndexOf("/");
- String classPathName = entryName.substring(0, lastSep + 1);
- docenv.getPackageDoc(pack).setDocPath(zipName, classPathName);
- }
- else if (fo instanceof JavacFileManager.ZipFileIndexFileObject) {
- JavacFileManager.ZipFileIndexFileObject zfo = (JavacFileManager.ZipFileIndexFileObject) fo;
- String zipName = zfo.getZipName();
- String entryName = zfo.getZipEntryName();
- if (File.separatorChar != '/') {
- entryName = entryName.replace(File.separatorChar, '/');
- }
-
- int lastSep = entryName.lastIndexOf("/");
- String classPathName = entryName.substring(0, lastSep + 1);
- docenv.getPackageDoc(pack).setDocPath(zipName, classPathName);
- }
- else {
- File fileDir = new File(Old199.getPath(fo)).getParentFile();
- docenv.getPackageDoc(pack).setDocPath(fileDir.getAbsolutePath());
- }
- }
+ if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML))
+ docenv.getPackageDoc(pack).setDocPath(fo);
}
}
--- a/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/JavadocTool.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,23 +25,30 @@
package com.sun.tools.javadoc;
-import java.io.*;
-
+import java.io.File;
+import java.io.IOException;
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 java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.comp.Annotate;
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.*;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+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.Position;
+
/**
* This class could be the main entry point for Javadoc when Javadoc is used as a
@@ -58,7 +65,6 @@ public class JavadocTool extends com.sun
final JavadocClassReader reader;
final JavadocEnter enter;
final Annotate annotate;
- private final Paths paths;
/**
* Construct a new JavaCompiler processor, using appropriately
@@ -71,7 +77,6 @@ public class JavadocTool extends com.sun
reader = JavadocClassReader.instance0(context);
enter = JavadocEnter.instance0(context);
annotate = Annotate.instance(context);
- paths = Paths.instance(context);
}
/**
@@ -125,7 +130,7 @@ public class JavadocTool extends com.sun
boolean quiet) throws IOException {
docenv = DocEnv.instance(context);
docenv.showAccess = filter;
- docenv.quiet = quiet;
+ docenv.quiet = quiet;
docenv.breakiterator = breakiterator;
docenv.setLocale(doclocale);
docenv.setEncoding(encoding);
@@ -138,16 +143,18 @@ public class JavadocTool extends com.sun
ListBuffer<JCCompilationUnit> packTrees = new ListBuffer<JCCompilationUnit>();
try {
+ StandardJavaFileManager fm = (StandardJavaFileManager) docenv.fileManager;
for (List<String> it = javaNames; it.nonEmpty(); it = it.tail) {
String name = it.head;
if (!docClasses && name.endsWith(".java") && new File(name).exists()) {
+ JavaFileObject fo = fm.getJavaFileObjects(name).iterator().next();
docenv.notice("main.Loading_source_file", name);
- JCCompilationUnit tree = parse(name);
- classTrees.append(tree);
+ JCCompilationUnit tree = parse(fo);
+ classTrees.append(tree);
} 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);
}
@@ -156,12 +163,14 @@ public class JavadocTool extends com.sun
if (!docClasses) {
// Recursively search given subpackages. If any packages
//are found, add them to the list.
- searchSubPackages(subPackages, names, excludedPackages);
+ Map<String,List<JavaFileObject>> packageFiles =
+ searchSubPackages(subPackages, names, excludedPackages);
// Parse the packages
for (List<String> packs = names.toList(); packs.nonEmpty(); packs = packs.tail) {
// Parse sources ostensibly belonging to package.
- parsePackageClasses(packs.head, packTrees, excludedPackages);
+ String packageName = packs.head;
+ parsePackageClasses(packageName, packageFiles.get(packageName), packTrees, excludedPackages);
}
if (messager.nerrors() != 0) return null;
@@ -172,7 +181,8 @@ public class JavadocTool extends com.sun
}
} catch (Abort ex) {}
- if (messager.nerrors() != 0) return null;
+ if (messager.nerrors() != 0)
+ return null;
if (docClasses)
return new RootDocImpl(docenv, javaNames, options);
@@ -190,66 +200,129 @@ public class JavadocTool extends com.sun
return isValidClassName(s);
}
-
- private final static char pathSep = File.pathSeparatorChar;
-
/**
* search all directories in path for subdirectory name. Add all
* .java files found in such a directory to args.
*/
private void parsePackageClasses(String name,
- ListBuffer<JCCompilationUnit> trees,
- List<String> excludedPackages)
- throws IOException {
+ Iterable<JavaFileObject> files,
+ ListBuffer<JCCompilationUnit> trees,
+ List<String> excludedPackages)
+ throws IOException {
if (excludedPackages.contains(name)) {
return;
}
+
boolean hasFiles = false;
docenv.notice("main.Loading_source_files_for_package", name);
- name = name.replace('.', File.separatorChar);
- for (File pathname : paths.sourceSearchPath()) {
- File f = new File(pathname, name);
- String names[] = f.list();
- // if names not null, then found directory with source files
- if (names != null) {
- String dir = f.getAbsolutePath();
- if (!dir.endsWith(File.separator))
- dir = dir + File.separator;
- for (int j = 0; j < names.length; j++) {
- if (isValidJavaSourceFile(names[j])) {
- String fn = dir + names[j];
- // messager.notice("main.Loading_source_file", fn);
- trees.append(parse(fn));
- hasFiles = true;
- }
- }
- }
- }
- if (!hasFiles)
+
+ if (files == null) {
+ Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+ ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+ ListBuffer<JavaFileObject> lb = new ListBuffer<JavaFileObject>();
+ for (JavaFileObject fo: docenv.fileManager.list(
+ location, name, EnumSet.of(JavaFileObject.Kind.SOURCE), false)) {
+ String binaryName = docenv.fileManager.inferBinaryName(location, fo);
+ String simpleName = getSimpleName(binaryName);
+ if (isValidClassName(simpleName)) {
+ lb.append(fo);
+ }
+ }
+ files = lb.toList();
+ }
+
+ for (JavaFileObject fo : files) {
+ // messager.notice("main.Loading_source_file", fn);
+ trees.append(parse(fo));
+ hasFiles = true;
+ }
+
+ if (!hasFiles) {
messager.warning(null, "main.no_source_files_for_package",
- name.replace(File.separatorChar, '.'));
+ name.replace(File.separatorChar, '.'));
+ }
}
/**
* Recursively search all directories in path for subdirectory name.
* Add all packages found in such a directory to packages list.
*/
+ private Map<String,List<JavaFileObject>> searchSubPackages(
+ List<String> subPackages,
+ ListBuffer<String> packages,
+ List<String> excludedPackages)
+ throws IOException {
+ Map<String,List<JavaFileObject>> packageFiles =
+ new HashMap<String,List<JavaFileObject>>();
+
+ Map<String,Boolean> includedPackages = new HashMap<String,Boolean>();
+ includedPackages.put("", true);
+ for (String p: excludedPackages)
+ includedPackages.put(p, false);
+
+ if (docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) {
+ searchSubPackages(subPackages,
+ includedPackages,
+ packages, packageFiles,
+ StandardLocation.SOURCE_PATH,
+ EnumSet.of(JavaFileObject.Kind.SOURCE));
+ searchSubPackages(subPackages,
+ includedPackages,
+ packages, packageFiles,
+ StandardLocation.CLASS_PATH,
+ EnumSet.of(JavaFileObject.Kind.CLASS));
+ } else {
+ searchSubPackages(subPackages,
+ includedPackages,
+ packages, packageFiles,
+ StandardLocation.CLASS_PATH,
+ EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS));
+ }
+ return packageFiles;
+ }
+
private void searchSubPackages(List<String> subPackages,
- ListBuffer<String> packages,
- List<String> excludedPackages) {
- // FIXME: This search path is bogus.
- // Only the effective source path should be searched for sources.
- // Only the effective class path should be searched for classes.
- // Should the bootclasspath/extdirs also be searched for classes?
- java.util.List<File> pathnames = new java.util.ArrayList<File>();
- if (paths.sourcePath() != null)
- for (File elt : paths.sourcePath())
- pathnames.add(elt);
- for (File elt : paths.userClassPath())
- pathnames.add(elt);
-
- for (String subPackage : subPackages)
- searchSubPackage(subPackage, packages, excludedPackages, pathnames);
+ Map<String,Boolean> includedPackages,
+ ListBuffer<String> packages,
+ Map<String, List<JavaFileObject>> packageFiles,
+ StandardLocation location, Set<JavaFileObject.Kind> kinds)
+ throws IOException {
+ for (String subPackage: subPackages) {
+ if (!isIncluded(subPackage, includedPackages))
+ continue;
+
+ for (JavaFileObject fo: docenv.fileManager.list(location, subPackage, kinds, true)) {
+ String binaryName = docenv.fileManager.inferBinaryName(location, fo);
+ String packageName = getPackageName(binaryName);
+ String simpleName = getSimpleName(binaryName);
+ if (isIncluded(packageName, includedPackages) && isValidClassName(simpleName)) {
+ List<JavaFileObject> list = packageFiles.get(packageName);
+ list = (list == null ? List.of(fo) : list.prepend(fo));
+ packageFiles.put(packageName, list);
+ if (!packages.contains(packageName))
+ packages.add(packageName);
+ }
+ }
+ }
+ }
+
+ private String getPackageName(String name) {
+ int lastDot = name.lastIndexOf(".");
+ return (lastDot == -1 ? "" : name.substring(0, lastDot));
+ }
+
+ private String getSimpleName(String name) {
+ int lastDot = name.lastIndexOf(".");
+ return (lastDot == -1 ? name : name.substring(lastDot + 1));
+ }
+
+ private boolean isIncluded(String packageName, Map<String,Boolean> includedPackages) {
+ Boolean b = includedPackages.get(packageName);
+ if (b == null) {
+ b = isIncluded(getPackageName(packageName), includedPackages);
+ includedPackages.put(packageName, b);
+ }
+ return b;
}
/**
--- a/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,29 +25,22 @@
package com.sun.tools.javadoc;
+import java.io.InputStream;
+import java.io.IOException;
+import javax.tools.FileObject;
+
import com.sun.javadoc.*;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipEntry;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
-import com.sun.tools.javac.comp.AttrContext;
-import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
-
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-
/**
* Represents a java package. Provides access to information
@@ -63,14 +56,10 @@ import com.sun.tools.javac.tree.JCTree.J
public class PackageDocImpl extends DocImpl implements PackageDoc {
- private static final String PACKAGE_HTML_FILE_NAME = "package.html";
-
protected PackageSymbol sym;
private JCCompilationUnit tree = null; // for source position
- public String docPath = null;
- public String zipDocPath = null;
- public String zipDocEntry = null;
+ public FileObject docPath = null;
private boolean foundDoc; // found a doc comment in either
// package.html or package-info.java
@@ -108,30 +97,16 @@ public class PackageDocImpl extends DocI
* Do lazy initialization of "documentation" string.
*/
String documentation() {
- if (documentation != null) return documentation;
- if (zipDocPath != null) {
- try {
- ZipFile f = new ZipFile(zipDocPath);
- ZipEntry entry = f.getEntry(zipDocEntry);
- if (entry != null) {
- InputStream s = f.getInputStream(entry);
- return (documentation = readHTMLDocumentation(s,
- zipDocPath + File.separatorChar + zipDocEntry));
- }
- } catch (IOException exc) {
- documentation = "";
- env.error(null, "javadoc.File_Read_Error",
- zipDocPath + File.separatorChar + zipDocEntry);
- }
- }
+ if (documentation != null)
+ return documentation;
if (docPath != null) {
// read from file
try {
- InputStream s = new FileInputStream(docPath);
+ InputStream s = docPath.openInputStream();
documentation = readHTMLDocumentation(s, docPath);
} catch (IOException exc) {
documentation = "";
- env.error(null, "javadoc.File_Read_Error", docPath);
+ env.error(null, "javadoc.File_Read_Error", docPath.getName());
}
} else {
// no doc file to be had
@@ -363,24 +338,12 @@ public class PackageDocImpl extends DocI
/**
* set doc path for an unzipped directory
*/
- public void setDocPath(String path) {
+ public void setDocPath(FileObject path) {
setDocPath = true;
if (path == null)
return;
- String newDocPath = path + File.separatorChar + PACKAGE_HTML_FILE_NAME;
- if (!newDocPath.equals(docPath)) {
- docPath = newDocPath;
- checkDoc();
- }
- }
-
- /**
- * set the doc path for zipped directory
- */
- public void setDocPath(String path, String entry) {
- if (!path.equals(zipDocPath)) {
- zipDocPath = path;
- zipDocEntry = entry + PACKAGE_HTML_FILE_NAME;
+ if (!path.equals(docPath)) {
+ docPath = path;
checkDoc();
}
}
@@ -409,7 +372,7 @@ public class PackageDocImpl extends DocI
*/
public SourcePosition position() {
return (tree != null)
- ? SourcePositionImpl.make(tree.sourcefile + "", tree.pos, tree.lineMap)
+ ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap)
: SourcePositionImpl.make(docPath, Position.NOPOS, null);
}
}
--- a/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -26,13 +26,13 @@ package com.sun.tools.javadoc;
package com.sun.tools.javadoc;
import java.io.IOException;
-import java.io.FileInputStream;
-import java.io.File;
+import java.util.Locale;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
import com.sun.javadoc.*;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Position;
@@ -307,10 +307,13 @@ public class RootDocImpl extends DocImpl
* Return the path of the overview file and null if it does not exist.
* @return the path of the overview file and null if it does not exist.
*/
- private String getOverviewPath() {
+ private JavaFileObject getOverviewPath() {
for (String[] opt : options) {
if (opt[0].equals("-overview")) {
- return opt[1];
+ if (env.fileManager instanceof StandardJavaFileManager) {
+ StandardJavaFileManager fm = (StandardJavaFileManager) env.fileManager;
+ return fm.getJavaFileObjects(opt[1]).iterator().next();
+ }
}
}
return null;
@@ -322,7 +325,7 @@ public class RootDocImpl extends DocImpl
protected String documentation() {
if (documentation == null) {
int cnt = options.length();
- String overviewPath = getOverviewPath();
+ JavaFileObject overviewPath = getOverviewPath();
if (overviewPath == null) {
// no doc file to be had
documentation = "";
@@ -330,11 +333,11 @@ public class RootDocImpl extends DocImpl
// read from file
try {
documentation = readHTMLDocumentation(
- new FileInputStream(overviewPath),
+ overviewPath.openInputStream(),
overviewPath);
} catch (IOException exc) {
documentation = "";
- env.error(null, "javadoc.File_Read_Error", overviewPath);
+ env.error(null, "javadoc.File_Read_Error", overviewPath.getName());
}
}
}
@@ -346,9 +349,16 @@ public class RootDocImpl extends DocImpl
* no position is available.
*/
public SourcePosition position() {
- String path;
+ JavaFileObject path;
return ((path = getOverviewPath()) == null) ?
null :
SourcePositionImpl.make(path, Position.NOPOS, null);
}
+
+ /**
+ * Return the locale provided by the user or the default locale value.
+ */
+ public Locale getLocale() {
+ return env.doclocale.locale;
+ }
}
--- a/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java Mon Jun 21 11:43:28 2010 -0700
+++ b/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java Tue Jun 22 18:30:16 2010 -0700
@@ -25,10 +25,11 @@
package com.sun.tools.javadoc;
+import java.io.File;
+import javax.tools.FileObject;
+
import com.sun.javadoc.SourcePosition;
import com.sun.tools.javac.util.Position;
-
-import java.io.File;
/**
* A source position: filename, line number, and column number.
@@ -37,15 +38,21 @@ import java.io.File;
* @author Neal M Gafter
* @author Michael Van De Vanter (position representation changed to char offsets)
*/
-class SourcePositionImpl implements SourcePosition {
- String filename;
+public class SourcePositionImpl implements SourcePosition {
+ FileObject filename;
int position;
Position.LineMap lineMap;
/** The source file. Returns null if no file information is
* available. */
public File file() {
- return (filename == null) ? null : new File(filename);
+ return (filename == null) ? null : new File(filename.getName());
+ }
+
+ /** The source file. Returns null if no file information is
+ * available. */
+ public FileObject fileObject() {
+ return filename;
}
/** The line in the source file. The first line is numbered 1;
@@ -71,7 +78,7 @@ class SourcePositionImpl implements Sour
}
}
- private SourcePositionImpl(String file, int position,
+ private SourcePositionImpl(FileObject file, int position,
Position.LineMap lineMap) {
super();
this.filename = file;
@@ -79,16 +86,27 @@ class SourcePositionImpl implements Sour
this.lineMap = lineMap;
}
- public static SourcePosition make(String file, int pos,
+ public static SourcePosition make(FileObject file, int pos,
Position.LineMap lineMap) {
if (file == null) return null;
return new SourcePositionImpl(file, pos, lineMap);
}
public String toString() {
+ // Backwards compatibility hack. ZipFileObjects use the format
+ // zipfile(zipentry) but javadoc has been using zipfile/zipentry
+ String fn = filename.getName();
+ if (fn.endsWith(")")) {
+ int paren = fn.lastIndexOf("(");
+ if (paren != -1)
+ fn = fn.substring(0, paren)
+ + File.separatorChar
+ + fn.substring(paren + 1, fn.length() - 1);
+ }
+
if (position == Position.NOPOS)
- return filename;
+ return fn;
else
- return filename + ":" + line();
+ return fn + ":" + line();
}
}
--- a/test/tools/javac/6304921/TestLog.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/6304921/TestLog.java Tue Jun 22 18:30:16 2010 -0700
@@ -32,12 +32,12 @@ import java.net.URI;
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/test/tools/javac/6589361/T6589361.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/6589361/T6589361.java Tue Jun 22 18:30:16 2010 -0700
@@ -1,11 +1,11 @@
/**
- * @test @(#)T6589361.java 1.1 07/07/18
+ * @test
* @bug 6589361
* @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;
@@ -23,8 +23,9 @@ public class T6589361 {
set.add(JavaFileObject.Kind.CLASS);
Iterable<JavaFileObject> files = fm.list(StandardLocation.PLATFORM_CLASS_PATH, "java.lang", set, false);
for (JavaFileObject file : files) {
-
- if (file.toString().startsWith("java" + File.separator + "lang" + File.separator + "Object.class")) {
+ // Note: Zip/Jar entry names use '/', not File.separator, but just to be sure,
+ // we normalize the filename as well.
+ if (file.getName().replace(File.separatorChar, '/').contains("java/lang/Object.class")) {
String str = fm.inferBinaryName(StandardLocation.CLASS_PATH, file);
if (!str.equals("java.lang.Object")) {
throw new AssertionError("Error in JavacFileManager.inferBinaryName method!");
--- a/test/tools/javac/T6358024.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/T6358024.java Tue Jun 22 18:30:16 2010 -0700
@@ -35,6 +35,8 @@ import javax.tools.*;
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.file.JavacFileManager;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/test/tools/javac/T6358166.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/T6358166.java Tue Jun 22 18:30:16 2010 -0700
@@ -32,6 +32,8 @@ import javax.annotation.processing.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;
+import com.sun.tools.javac.file.*;
+import com.sun.tools.javac.file.JavacFileManager; // disambiguate
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/test/tools/javac/T6358168.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/T6358168.java Tue Jun 22 18:30:16 2010 -0700
@@ -33,6 +33,8 @@ import javax.annotation.processing.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;
+import com.sun.tools.javac.file.*;
+import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.util.*;
--- a/test/tools/javac/T6725036.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/T6725036.java Tue Jun 22 18:30:16 2010 -0700
@@ -34,10 +34,10 @@ import java.util.jar.JarFile;
import java.util.jar.JarFile;
import javax.tools.JavaFileObject;
-import com.sun.tools.javac.util.JavacFileManager;
-import com.sun.tools.javac.zip.ZipFileIndex;
-import com.sun.tools.javac.zip.ZipFileIndexEntry;
-import com.sun.tools.javac.util.JavacFileManager.ZipFileIndexArchive;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.file.ZipFileIndex;
+import com.sun.tools.javac.file.ZipFileIndexArchive;
import com.sun.tools.javac.util.Context;
public class T6725036 {
@@ -46,7 +46,7 @@ public class T6725036 {
}
void run() throws Exception {
- String TEST_ENTRY_NAME = "java/lang/String.class";
+ RelativeFile TEST_ENTRY_NAME = new RelativeFile("java/lang/String.class");
File f = new File(System.getProperty("java.home"));
if (!f.getName().equals("jre"))
@@ -54,23 +54,21 @@ public class T6725036 {
File rt_jar = new File(new File(f, "lib"), "rt.jar");
JarFile j = new JarFile(rt_jar);
- JarEntry je = j.getJarEntry(TEST_ENTRY_NAME);
+ JarEntry je = j.getJarEntry(TEST_ENTRY_NAME.getPath());
long jarEntryTime = je.getTime();
ZipFileIndex zfi =
- ZipFileIndex.getZipFileIndex(rt_jar, 0, false, null, false);
+ ZipFileIndex.getZipFileIndex(rt_jar, null, false, null, false);
long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME);
- check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME, zfiTime);
+ check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime);
Context context = new Context();
JavacFileManager fm = new JavacFileManager(context, false, null);
- ZipFileIndexArchive zfia =
- fm.new ZipFileIndexArchive(fm, zfi);
- int sep = TEST_ENTRY_NAME.lastIndexOf("/");
+ ZipFileIndexArchive zfia = new ZipFileIndexArchive(fm, zfi);
JavaFileObject jfo =
- zfia.getFileObject(TEST_ENTRY_NAME.substring(0, sep + 1),
- TEST_ENTRY_NAME.substring(sep + 1));
+ zfia.getFileObject(TEST_ENTRY_NAME.dirname(),
+ TEST_ENTRY_NAME.basename());
long jfoTime = jfo.getLastModified();
check(je, jarEntryTime, jfo, jfoTime);
--- a/test/tools/javac/api/6411310/T6411310.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/6411310/T6411310.java Tue Jun 22 18:30:16 2010 -0700
@@ -37,7 +37,7 @@ import static javax.tools.StandardLocati
import static javax.tools.StandardLocation.CLASS_PATH;
import static javax.tools.JavaFileObject.Kind.CLASS;
-// Limited test while we wait for 6419926
+// Limited test while we wait for 6419926: 6419926 is now closed
public class T6411310 extends ToolTester {
@@ -45,8 +45,11 @@ public class T6411310 extends ToolTester
JavaFileObject file = fm.getJavaFileForInput(PLATFORM_CLASS_PATH,
"java.lang.Object",
CLASS);
- if (!file.getName().equals("Object.class"))
+ String fileName = file.getName();
+ if (!fileName.matches(".*java/lang/Object.class\\)?")) {
+ System.err.println(fileName);
throw new AssertionError(file);
+ }
}
public static void main(String... args) throws IOException {
--- a/test/tools/javac/api/6440333/T6440333.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/6440333/T6440333.java Tue Jun 22 18:30:16 2010 -0700
@@ -26,7 +26,6 @@
* @bug 6440333
* @summary SimpleJavaFileObject.toString() generates URI with some extra message
* @author Peter von der Ah\u00e9
- * @ignore 6877223 test ignored because of issues with File.toUri on Windows (6877206)
* @library ../lib
* @compile T6440333.java
* @run main T6440333
@@ -34,6 +33,7 @@
import java.io.File;
import java.io.IOException;
+import java.net.URI;
import javax.tools.JavaFileObject;
public class T6440333 extends ToolTester {
@@ -41,14 +41,10 @@ public class T6440333 extends ToolTester
File path = test_src.getCanonicalFile();
File src = new File(new File(path, "."), "T6440333.java");
JavaFileObject fo = fm.getJavaFileObjects(src).iterator().next();
- String expect = src.getCanonicalFile().getPath().replace(File.separatorChar, '/');
+ URI expect = src.getCanonicalFile().toURI();
System.err.println("Expect " + expect);
- // CURRENTLY, the following line fails on Windows because a file C:/w/jjg/...
- // returns a URI file://C/w/jjg... which incorrectly encodes the drive letter
- // in the URI authority. This is against the spec that the authority is
- // undefined and breaks the contract that new File(f.toURI()).equals(f.getAbsoluteFile())
- System.err.println("Got: " + fo.toUri().getPath());
- if (!expect.equals(fo.toUri().getPath())) {
+ System.err.println("Found " + fo.toUri());
+ if (!expect.equals(fo.toUri())) {
throw new AssertionError();
}
}
--- a/test/tools/javac/api/6440528/T6440528.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/6440528/T6440528.java Tue Jun 22 18:30:16 2010 -0700
@@ -59,9 +59,9 @@ public class T6440528 extends ToolTester
}
private File getUnderlyingFile(Object o) throws Exception {
- Field f = o.getClass().getDeclaredField("f");
- f.setAccessible(true);
- return (File)f.get(o);
+ Field file = o.getClass().getDeclaredField("file");
+ file.setAccessible(true);
+ return (File)file.get(o);
}
public static void main(String... args) throws Exception {
--- a/test/tools/javac/api/Sibling.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/Sibling.java Tue Jun 22 18:30:16 2010 -0700
@@ -26,7 +26,6 @@
* @bug 6399602
* @summary Verify that files are created relative to sibling
* @author Peter von der Ah\u00e9
- * @ignore 6877223 test ignored because of issues with File.toUri on Windows (6877206)
*/
import java.io.File;
@@ -48,10 +47,9 @@ public class Sibling {
"foo.bar.baz.Test",
CLASS,
sibling);
- String name =
- new File("Test.class").getAbsolutePath().replace(File.separatorChar, '/');
- if (!classFile.toUri().getPath().equals(name))
- throw new AssertionError("Expected " + name + ", got " +
- classFile.toUri().getPath());
+ File file = new File("Test.class").getAbsoluteFile();
+ if (!classFile.toUri().equals(file.toURI()))
+ throw new AssertionError("Expected " + file.toURI() + ", got " +
+ classFile.toUri());
}
}
--- a/test/tools/javac/api/T6358786.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/T6358786.java Tue Jun 22 18:30:16 2010 -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/test/tools/javac/api/TestResolveIdent.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/api/TestResolveIdent.java Tue Jun 22 18:30:16 2010 -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/test/tools/javac/util/filemanager/TestName.java Mon Jun 21 11:43:28 2010 -0700
+++ b/test/tools/javac/util/filemanager/TestName.java Tue Jun 22 18:30:16 2010 -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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.CharsetDecoder;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+
+import static javax.tools.JavaFileObject.Kind.*;
+
+import com.sun.tools.javac.util.BaseFileManager;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * 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 abstract class BaseFileObject implements JavaFileObject {
+ protected BaseFileObject(JavacFileManager fileManager) {
+ this.fileManager = fileManager;
+ }
+
+ /** Return a short name for the object, such as for use in raw diagnostics
+ */
+ public abstract String getShortName();
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + 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();
+ }
+
+ protected abstract String inferBinaryName(Iterable<? extends File> path);
+
+ protected static JavaFileObject.Kind getKind(String filename) {
+ return BaseFileManager.getKind(filename);
+ }
+
+ protected static String removeExtension(String fileName) {
+ int lastDot = fileName.lastIndexOf(".");
+ return (lastDot == -1 ? fileName : fileName.substring(0, lastDot));
+ }
+
+ protected static URI createJarUri(File jarFile, String entryName) {
+ URI jarURI = jarFile.toURI().normalize();
+ String separator = entryName.startsWith("/") ? "!" : "!/";
+ try {
+ // The jar URI convention appears to be not to re-encode the jarURI
+ return new URI("jar:" + jarURI + separator + entryName);
+ } catch (URISyntaxException e) {
+ throw new CannotCreateUriError(jarURI + separator + entryName, e);
+ }
+ }
+
+ /** Used when URLSyntaxException is thrown unexpectedly during
+ * implementations of (Base)FileObject.toURI(). */
+ protected static class CannotCreateUriError extends Error {
+ private static final long serialVersionUID = 9101708840997613546L;
+ public CannotCreateUriError(String value, Throwable cause) {
+ super(value, cause);
+ }
+ }
+
+ /** Return the last component of a presumed hierarchical URI.
+ * From the scheme specific part of the URI, it returns the substring
+ * after the last "/" if any, or everything if no "/" is found.
+ */
+ public static String getSimpleName(FileObject fo) {
+ URI uri = fo.toUri();
+ String s = uri.getSchemeSpecificPart();
+ return s.substring(s.lastIndexOf("/") + 1); // safe when / not found
+
+ }
+
+ // force subtypes to define equals
+ @Override
+ public abstract boolean equals(Object other);
+
+ // force subtypes to define hashCode
+ @Override
+ public abstract int hashCode();
+
+ /** The file manager that created this JavaFileObject. */
+ protected final JavacFileManager fileManager;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import com.sun.tools.javac.util.Context;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Caching implementation of FSInfo.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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 CacheFSInfo extends FSInfo {
+
+ /**
+ * Register a Context.Factory to create a singleton CacheFSInfo.
+ */
+ public static void preRegister(final Context context) {
+ context.put(FSInfo.class, new Context.Factory<FSInfo>() {
+ public FSInfo make() {
+ if (singleton == null)
+ singleton = new CacheFSInfo();
+ context.put(FSInfo.class, singleton);
+ return singleton;
+ }
+ });
+ }
+
+ static CacheFSInfo singleton;
+
+ public void clearCache() {
+ cache.clear();
+ }
+
+ @Override
+ public File getCanonicalFile(File file) {
+ Entry e = getEntry(file);
+ return e.canonicalFile;
+ }
+
+ @Override
+ public boolean exists(File file) {
+ Entry e = getEntry(file);
+ return e.exists;
+ }
+
+ @Override
+ public boolean isDirectory(File file) {
+ Entry e = getEntry(file);
+ return e.isDirectory;
+ }
+
+ @Override
+ public boolean isFile(File file) {
+ Entry e = getEntry(file);
+ return e.isFile;
+ }
+
+ @Override
+ public List<File> getJarClassPath(File file) throws IOException {
+ // don't bother to lock the cache, because it is thread-safe, and
+ // because the worst that can happen would be to create two identical
+ // jar class paths together and have one overwrite the other.
+ Entry e = getEntry(file);
+ if (e.jarClassPath == null)
+ e.jarClassPath = super.getJarClassPath(file);
+ return e.jarClassPath;
+ }
+
+ private Entry getEntry(File file) {
+ // don't bother to lock the cache, because it is thread-safe, and
+ // because the worst that can happen would be to create two identical
+ // entries together and have one overwrite the other.
+ Entry e = cache.get(file);
+ if (e == null) {
+ e = new Entry();
+ e.canonicalFile = super.getCanonicalFile(file);
+ e.exists = super.exists(file);
+ e.isDirectory = super.isDirectory(file);
+ e.isFile = super.isFile(file);
+ cache.put(file, e);
+ }
+ return e;
+ }
+
+ // could also be a Map<File,SoftReference<Entry>> ?
+ private Map<File,Entry> cache = new ConcurrentHashMap<File,Entry>();
+
+ private static class Entry {
+ File canonicalFile;
+ boolean exists;
+ boolean isFile;
+ boolean isDirectory;
+ List<File> jarClassPath;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/FSInfo.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,94 @@
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Get meta-info about files. Default direct (non-caching) implementation.
+ * @see CacheFSInfo
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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 FSInfo {
+
+ /** Get the FSInfo instance for this context.
+ * @param context the context
+ * @return the Paths instance for this context
+ */
+ public static FSInfo instance(Context context) {
+ FSInfo instance = context.get(FSInfo.class);
+ if (instance == null)
+ instance = new FSInfo();
+ return instance;
+ }
+
+ protected FSInfo() {
+ }
+
+ protected FSInfo(Context context) {
+ context.put(FSInfo.class, this);
+ }
+
+ public File getCanonicalFile(File file) {
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ return file.getAbsoluteFile();
+ }
+ }
+
+ public boolean exists(File file) {
+ return file.exists();
+ }
+
+ public boolean isDirectory(File file) {
+ return file.isDirectory();
+ }
+
+ public boolean isFile(File file) {
+ return file.isFile();
+ }
+
+ public List<File> getJarClassPath(File file) throws IOException {
+ String parent = file.getParent();
+ JarFile jarFile = new JarFile(file);
+ try {
+ Manifest man = jarFile.getManifest();
+ if (man == null)
+ return Collections.emptyList();
+
+ Attributes attr = man.getMainAttributes();
+ if (attr == null)
+ return Collections.emptyList();
+
+ String path = attr.getValue(Attributes.Name.CLASS_PATH);
+ if (path == null)
+ return Collections.emptyList();
+
+ List<File> list = new ArrayList<File>();
+
+ for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) {
+ String elt = st.nextToken();
+ File f = (parent == null ? new File(elt) : new File(parent, elt));
+ list.add(f);
+ }
+
+ return list;
+ } finally {
+ jarFile.close();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,860 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+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.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.util.BaseFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.main.OptionName.*;
+
+/**
+ * This class provides access to the source, class and other files
+ * used by the compiler and related tools.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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 JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
+
+ boolean useZipFileIndex;
+
+ public static char[] toArray(CharBuffer buffer) {
+ if (buffer.hasArray())
+ return ((CharBuffer)buffer.compact().flip()).array();
+ else
+ return buffer.toString().toCharArray();
+ }
+
+ /** Encapsulates knowledge of paths
+ */
+ private Paths paths;
+
+ private FSInfo fsInfo;
+
+ 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;
+
+ /**
+ * 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) {
+ super(charset);
+ if (register)
+ context.put(JavaFileManager.class, this);
+ setContext(context);
+ }
+
+ /**
+ * Set the context for JavacFileManager.
+ */
+ @Override
+ public void setContext(Context context) {
+ super.setContext(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);
+ }
+
+ fsInfo = FSInfo.instance(context);
+
+ useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == 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(this, 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)));
+ }
+
+ 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);
+ }
+
+ /**
+ * Insert all files in subdirectory `subdirectory' of `directory' which end
+ * in one of the extensions in `extensions' into packageSym.
+ */
+ private void listDirectory(File directory,
+ RelativeDirectory subdirectory,
+ Set<JavaFileObject.Kind> fileKinds,
+ boolean recurse,
+ ListBuffer<JavaFileObject> l) {
+ Archive archive = archives.get(directory);
+
+ boolean isFile = fsInfo.isFile(directory);
+
+ if (archive != null || isFile) {
+ if (archive == null) {
+ try {
+ archive = openArchive(directory);
+ } catch (IOException ex) {
+ log.error("error.reading.file",
+ directory, getMessage(ex));
+ return;
+ }
+ }
+
+ 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 (RelativeDirectory s: archive.getSubdirectories()) {
+ if (subdirectory.contains(s)) {
+ // 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.getFile(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,
+ new RelativeDirectory(subdirectory, fname),
+ fileKinds,
+ recurse,
+ l);
+ }
+ } else {
+ if (isValidFile(fname, fileKinds)) {
+ JavaFileObject fe =
+ new RegularFileObject(this, fname, new File(d, fname));
+ l.append(fe);
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isValidFile(String s, Set<JavaFileObject.Kind> fileKinds) {
+ JavaFileObject.Kind kind = getKind(s);
+ 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, RelativePath 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.path.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] == '/') 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(RelativePath name);
+
+ JavaFileObject getFileObject(RelativeDirectory subdirectory, String file);
+
+ List<String> getFiles(RelativeDirectory subdirectory);
+
+ Set<RelativeDirectory> getSubdirectories();
+ }
+
+ public class MissingArchive implements Archive {
+ final File zipFileName;
+ public MissingArchive(File name) {
+ zipFileName = name;
+ }
+ public boolean contains(RelativePath name) {
+ return false;
+ }
+
+ public void close() {
+ }
+
+ public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+ return null;
+ }
+
+ public List<String> getFiles(RelativeDirectory subdirectory) {
+ return List.nil();
+ }
+
+ public Set<RelativeDirectory> getSubdirectories() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String toString() {
+ return "MissingArchive[" + zipFileName + "]";
+ }
+ }
+
+ /** A directory of zip files already opened.
+ */
+ Map<File, Archive> archives = new HashMap<File,Archive>();
+
+ private static final String[] symbolFileLocation = { "lib", "ct.sym" };
+ private static final RelativeDirectory symbolFilePrefix
+ = new RelativeDirectory("META-INF/sym/rt.jar/");
+
+ /** 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(this, zdir);
+ } else {
+ archive = new ZipFileIndexArchive(this,
+ ZipFileIndex.getZipFileIndex(zipFileName,
+ null,
+ usePreindexedCache,
+ preindexCacheLocation,
+ options.get("writezipindexfiles") != null));
+ }
+ }
+ else {
+ if (!useZipFileIndex) {
+ archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
+ }
+ else {
+ archive = new ZipFileIndexArchive(this,
+ ZipFileIndex.getZipFileIndex(zipFileName,
+ symbolFilePrefix,
+ usePreindexedCache,
+ preindexCacheLocation,
+ options.get("writezipindexfiles") != null));
+ }
+ }
+ } catch (FileNotFoundException ex) {
+ archive = new MissingArchive(zipFileName);
+ } catch (IOException ex) {
+ if (zipFileName.exists())
+ log.error("error.reading.file", zipFileName, getMessage(ex));
+ 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 String defaultEncodingName;
+ private String getDefaultEncodingName() {
+ if (defaultEncodingName == null) {
+ defaultEncodingName =
+ new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+ }
+ return defaultEncodingName;
+ }
+
+ 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 getClassLoader(lb.toArray(new URL[lb.size()]));
+ }
+
+ 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();
+ RelativeDirectory subdirectory = RelativeDirectory.forPackage(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) {
+ return null;
+ }
+
+ if (file instanceof BaseFileObject) {
+ return ((BaseFileObject) file).inferBinaryName(path);
+ } else
+ throw new IllegalArgumentException(file.getClass().getName());
+ }
+
+ 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 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, RelativeFile.forClass(className, kind));
+ }
+
+ public FileObject getFileForInput(Location location,
+ String packageName,
+ String relativeName)
+ throws IOException
+ {
+ nullCheck(location);
+ // validatePackageName(packageName);
+ nullCheck(packageName);
+ if (!isRelativeUri(relativeName))
+ throw new IllegalArgumentException("Invalid relative name: " + relativeName);
+ RelativeFile name = packageName.length() == 0
+ ? new RelativeFile(relativeName)
+ : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
+ return getFileForInput(location, name);
+ }
+
+ private JavaFileObject getFileForInput(Location location, RelativeFile name) throws IOException {
+ Iterable<? extends File> path = getLocation(location);
+ if (path == null)
+ return null;
+
+ for (File dir: path) {
+ if (dir.isDirectory()) {
+ File f = name.getFile(dir);
+ if (f.exists())
+ return new RegularFileObject(this, f);
+ } else {
+ Archive a = openArchive(dir);
+ if (a.contains(name)) {
+ return a.getFileObject(name.dirname(), name.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, RelativeFile.forClass(className, kind), sibling);
+ }
+
+ public FileObject getFileForOutput(Location location,
+ String packageName,
+ String relativeName,
+ FileObject sibling)
+ throws IOException
+ {
+ nullCheck(location);
+ // validatePackageName(packageName);
+ nullCheck(packageName);
+ if (!isRelativeUri(relativeName))
+ throw new IllegalArgumentException("relativeName is invalid");
+ RelativeFile name = packageName.length() == 0
+ ? new RelativeFile(relativeName)
+ : new RelativeFile(RelativeDirectory.forPackage(packageName), relativeName);
+ return getFileForOutput(location, name, sibling);
+ }
+
+ private JavaFileObject getFileForOutput(Location location,
+ RelativeFile 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).file.getParentFile();
+ }
+ return new RegularFileObject(this, new File(siblingDir, fileName.basename()));
+ }
+ } 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 = fileName.getFile(dir); // null-safe
+ return new RegularFileObject(this, 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(this, 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 != '/';
+ }
+
+ // Convenience method
+ protected static boolean isRelativeUri(String u) {
+ try {
+ return isRelativeUri(new URI(u));
+ } catch (URISyntaxException e) {
+ return false;
+ }
+ }
+
+ /**
+ * 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 (isRelativeUri(result))
+ return result;
+ }
+ throw new IllegalArgumentException("Invalid relative path: " + file);
+ }
+
+ /**
+ * Get a detail message from an IOException.
+ * Most, but not all, instances of IOException provide a non-null result
+ * for getLocalizedMessage(). But some instances return null: in these
+ * cases, fallover to getMessage(), and if even that is null, return the
+ * name of the exception itself.
+ * @param e an IOException
+ * @return a string to include in a compiler diagnostic
+ */
+ public static String getMessage(IOException e) {
+ String s = e.getLocalizedMessage();
+ if (s != null)
+ return s;
+ s = e.getMessage();
+ if (s != null)
+ return s;
+ return e.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/Paths.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.StringTokenizer;
+import java.util.zip.ZipFile;
+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.ListBuffer;
+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 supported API.
+ * 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;
+
+ /** Access to (possibly cached) file info */
+ private FSInfo fsInfo;
+
+ 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);
+ fsInfo = FSInfo.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);
+ }
+
+ /**
+ * Split a path into its elements. Empty path elements will be ignored.
+ * @param path The path to be split
+ * @return The elements of the path
+ */
+ private static Iterable<File> getPathEntries(String path) {
+ return getPathEntries(path, null);
+ }
+
+ /**
+ * Split a path into its elements. If emptyPathDefault is not null, all
+ * empty elements in the path, including empty elements at either end of
+ * the path, will be replaced with the value of emptyPathDefault.
+ * @param path The path to be split
+ * @param emptyPathDefault The value to substitute for empty path elements,
+ * or null, to ignore empty path elements
+ * @return The elements of the path
+ */
+ private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
+ ListBuffer<File> entries = new ListBuffer<File>();
+ int start = 0;
+ while (start <= path.length()) {
+ int sep = path.indexOf(File.pathSeparatorChar, start);
+ if (sep == -1)
+ sep = path.length();
+ if (start < sep)
+ entries.add(new File(path.substring(start, sep)));
+ else if (emptyPathDefault != null)
+ entries.add(emptyPathDefault);
+ start = sep + 1;
+ }
+ return entries;
+ }
+
+ 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 File emptyPathDefault = null;
+
+ public Path emptyPathDefault(File x) {
+ emptyPathDefault = x;
+ return this;
+ }
+
+ public Path() { super(); }
+
+ public Path addDirectories(String dirs, boolean warn) {
+ if (dirs != null)
+ for (File dir : getPathEntries(dirs))
+ addDirectory(dir, warn);
+ return this;
+ }
+
+ public Path addDirectories(String dirs) {
+ return addDirectories(dirs, warn);
+ }
+
+ private void addDirectory(File dir, boolean warn) {
+ if (!dir.isDirectory()) {
+ if (warn)
+ log.warning("dir.path.element.not.found", dir);
+ return;
+ }
+
+ File[] files = 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 (File file : getPathEntries(files, emptyPathDefault))
+ addFile(file, warn);
+ return this;
+ }
+
+ public Path addFiles(String files) {
+ return addFiles(files, warn);
+ }
+
+ public void addFile(File file, boolean warn) {
+ File canonFile = fsInfo.getCanonicalFile(file);
+ if (contains(file) || canonicalValues.contains(canonFile)) {
+ /* Discard duplicates and avoid infinite recursion */
+ return;
+ }
+
+ if (! fsInfo.exists(file)) {
+ /* No such file or directory exists */
+ if (warn)
+ log.warning("path.element.not.found", file);
+ } else if (fsInfo.isFile(file)) {
+ /* 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(canonFile);
+
+ if (expandJarClassPaths && fsInfo.exists(file) && fsInfo.isFile(file))
+ 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 {
+ for (File f: fsInfo.getJarClassPath(jarFile)) {
+ addFile(f, warn);
+ }
+ } catch (IOException e) {
+ log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e));
+ }
+ }
+ }
+
+ 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 (File file : getPathEntries(files)) {
+ if (new File(file.getName()).equals(rt_jar))
+ bootClassPathRtJar = file;
+ }
+ }
+
+ 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(new File(".")) // 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 boolean isArchive(File file) {
+ String n = file.getName().toLowerCase();
+ return fsInfo.isFile(file)
+ && (n.endsWith(".jar") || n.endsWith(".zip"));
+ }
+
+ /**
+ * Utility method for converting a search path string to an array
+ * of directory and JAR file URLs.
+ *
+ * Note that this method is called by apt and the DocletInvoker.
+ *
+ * @param path the search path string
+ * @return the resulting array of directory and JAR file URLs
+ */
+ public static URL[] pathToURLs(String path) {
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ URL[] urls = new URL[st.countTokens()];
+ int count = 0;
+ while (st.hasMoreTokens()) {
+ URL url = fileToURL(new File(st.nextToken()));
+ if (url != null) {
+ urls[count++] = url;
+ }
+ }
+ if (urls.length != count) {
+ URL[] tmp = new URL[count];
+ System.arraycopy(urls, 0, tmp, 0, count);
+ urls = tmp;
+ }
+ return urls;
+ }
+
+ /**
+ * Returns the directory or JAR file URL corresponding to the specified
+ * local file name.
+ *
+ * @param file the File object
+ * @return the resulting directory or JAR file URL, or null if unknown
+ */
+ private static URL fileToURL(File file) {
+ String name;
+ try {
+ name = file.getCanonicalPath();
+ } catch (IOException e) {
+ name = file.getAbsolutePath();
+ }
+ name = name.replace(File.separatorChar, '/');
+ if (!name.startsWith("/")) {
+ name = "/" + name;
+ }
+ // If the file does not exist, then assume that it's a directory
+ if (!file.isFile()) {
+ name = name + "/";
+ }
+ try {
+ return new URL("file", "", name);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(file.toString());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+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.Reference;
+import java.lang.ref.SoftReference;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import javax.tools.JavaFileObject;
+
+/**
+ * A subclass of JavaFileObject representing regular files.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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>
+ */
+class RegularFileObject extends BaseFileObject {
+
+ /** Have the parent directories been created?
+ */
+ private boolean hasParents = false;
+ private String name;
+ final File file;
+ private Reference<File> absFileRef;
+
+ public RegularFileObject(JavacFileManager fileManager, File f) {
+ this(fileManager, f.getName(), f);
+ }
+
+ public RegularFileObject(JavacFileManager fileManager, String name, File f) {
+ super(fileManager);
+ if (f.isDirectory()) {
+ throw new IllegalArgumentException("directories not supported");
+ }
+ this.name = name;
+ this.file = f;
+ }
+
+ //@Override
+ public URI toUri() {
+ return file.toURI().normalize();
+ }
+
+ //@Override
+ public String getName() {
+ return file.getPath();
+ }
+
+ //@Override
+ public String getShortName() {
+ return name;
+ }
+
+ //@Override
+ public JavaFileObject.Kind getKind() {
+ return getKind(name);
+ }
+
+ //@Override
+ public InputStream openInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ //@Override
+ public OutputStream openOutputStream() throws IOException {
+ ensureParentDirectoriesExist();
+ return new FileOutputStream(file);
+ }
+
+ //@Override
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ CharBuffer cb = fileManager.getCachedContent(this);
+ if (cb == null) {
+ InputStream in = new FileInputStream(file);
+ try {
+ ByteBuffer bb = fileManager.makeByteBuffer(in);
+ JavaFileObject prev = fileManager.log.useSource(this);
+ try {
+ cb = fileManager.decode(bb, ignoreEncodingErrors);
+ } finally {
+ fileManager.log.useSource(prev);
+ }
+ fileManager.recycleByteBuffer(bb);
+ if (!ignoreEncodingErrors) {
+ fileManager.cache(this, cb);
+ }
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ //@Override
+ public Writer openWriter() throws IOException {
+ ensureParentDirectoriesExist();
+ return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName());
+ }
+
+ //@Override
+ public long getLastModified() {
+ return file.lastModified();
+ }
+
+ //@Override
+ public boolean delete() {
+ return file.delete();
+ }
+
+ //@Override
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+ }
+
+ //@Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ String fPath = file.getPath();
+ //System.err.println("RegularFileObject " + file + " " +r.getPath());
+ for (File dir: path) {
+ //System.err.println("dir: " + dir);
+ String dPath = dir.getPath();
+ if (dPath.length() == 0)
+ dPath = System.getProperty("user.dir");
+ if (!dPath.endsWith(File.separator))
+ dPath += File.separator;
+ if (fPath.regionMatches(true, 0, dPath, 0, dPath.length())
+ && new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) {
+ String relativeName = fPath.substring(dPath.length());
+ return removeExtension(relativeName).replace(File.separatorChar, '.');
+ }
+ }
+ return null;
+ }
+
+ //@Override
+ 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 file.getCanonicalFile().getName().equals(n);
+ } catch (IOException e) {
+ }
+ }
+ return false;
+ }
+
+ private void ensureParentDirectoriesExist() throws IOException {
+ if (!hasParents) {
+ File parent = file.getParentFile();
+ if (parent != null && !parent.exists()) {
+ if (!parent.mkdirs()) {
+ if (!parent.exists() || !parent.isDirectory()) {
+ throw new IOException("could not create parent directories");
+ }
+ }
+ }
+ hasParents = true;
+ }
+ }
+
+ /**
+ * Check if two file objects are equal.
+ * Two RegularFileObjects are equal if the absolute paths of the underlying
+ * files are equal.
+ */
+ //@Override
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
+ if (!(other instanceof RegularFileObject))
+ return false;
+
+ RegularFileObject o = (RegularFileObject) other;
+ return getAbsoluteFile().equals(o.getAbsoluteFile());
+ }
+
+ //@Override
+ public int hashCode() {
+ return getAbsoluteFile().hashCode();
+ }
+
+ private File getAbsoluteFile() {
+ File absFile = (absFileRef == null ? null : absFileRef.get());
+ if (absFile == null) {
+ absFile = file.getAbsoluteFile();
+ absFileRef = new SoftReference<File>(absFile);
+ }
+ return absFile;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/RelativePath.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileObject;
+
+/**
+ * Used to represent a platform-neutral path within a platform-specific
+ * container, such as a directory or zip file.
+ * Internally, the file separator is always '/'.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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 abstract class RelativePath implements Comparable<RelativePath> {
+ /**
+ * @param p must use '/' as an internal separator
+ */
+ protected RelativePath(String p) {
+ path = p;
+ }
+
+ public abstract RelativeDirectory dirname();
+
+ public abstract String basename();
+
+ public File getFile(File directory) {
+ if (path.length() == 0)
+ return directory;
+ return new File(directory, path.replace('/', File.separatorChar));
+ }
+
+ public int compareTo(RelativePath other) {
+ return path.compareTo(other.path);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RelativePath))
+ return false;
+ return path.equals(((RelativePath) other).path);
+ }
+
+ @Override
+ public int hashCode() {
+ return path.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "RelPath[" + path + "]";
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ protected final String path;
+
+ /**
+ * Used to represent a platform-neutral subdirectory within a platform-specific
+ * container, such as a directory or zip file.
+ * Internally, the file separator is always '/', and if the path is not empty,
+ * it always ends in a '/' as well.
+ */
+ public static class RelativeDirectory extends RelativePath {
+
+ static RelativeDirectory forPackage(CharSequence packageName) {
+ return new RelativeDirectory(packageName.toString().replace('.', '/'));
+ }
+
+ /**
+ * @param p must use '/' as an internal separator
+ */
+ public RelativeDirectory(String p) {
+ super(p.length() == 0 || p.endsWith("/") ? p : p + "/");
+ }
+
+ /**
+ * @param p must use '/' as an internal separator
+ */
+ public RelativeDirectory(RelativeDirectory d, String p) {
+ this(d.path + p);
+ }
+
+ @Override
+ public RelativeDirectory dirname() {
+ int l = path.length();
+ if (l == 0)
+ return this;
+ int sep = path.lastIndexOf('/', l - 2);
+ return new RelativeDirectory(path.substring(0, sep + 1));
+ }
+
+ @Override
+ public String basename() {
+ int l = path.length();
+ if (l == 0)
+ return path;
+ int sep = path.lastIndexOf('/', l - 2);
+ return path.substring(sep + 1, l - 1);
+ }
+
+ /**
+ * Return true if this subdirectory "contains" the other path.
+ * A subdirectory path does not contain itself.
+ **/
+ boolean contains(RelativePath other) {
+ return other.path.length() > path.length() && other.path.startsWith(path);
+ }
+
+ @Override
+ public String toString() {
+ return "RelativeDirectory[" + path + "]";
+ }
+ }
+
+ /**
+ * Used to represent a platform-neutral file within a platform-specific
+ * container, such as a directory or zip file.
+ * Internally, the file separator is always '/'. It never ends in '/'.
+ */
+ public static class RelativeFile extends RelativePath {
+ static RelativeFile forClass(CharSequence className, JavaFileObject.Kind kind) {
+ return new RelativeFile(className.toString().replace('.', '/') + kind.extension);
+ }
+
+ public RelativeFile(String p) {
+ super(p);
+ if (p.endsWith("/"))
+ throw new IllegalArgumentException(p);
+ }
+
+ /**
+ * @param p must use '/' as an internal separator
+ */
+ public RelativeFile(RelativeDirectory d, String p) {
+ this(d.path + p);
+ }
+
+ RelativeFile(RelativeDirectory d, RelativePath p) {
+ this(d, p.path);
+ }
+
+ @Override
+ public RelativeDirectory dirname() {
+ int sep = path.lastIndexOf('/');
+ return new RelativeDirectory(path.substring(0, sep + 1));
+ }
+
+ @Override
+ public String basename() {
+ int sep = path.lastIndexOf('/');
+ return path.substring(sep + 1);
+ }
+
+ ZipEntry getZipEntry(ZipFile zip) {
+ return zip.getEntry(path);
+ }
+
+ @Override
+ public String toString() {
+ return "RelativeFile[" + path + "]";
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * 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 SymbolArchive extends ZipArchive {
+
+ final File origFile;
+ final RelativeDirectory prefix;
+
+ public SymbolArchive(JavacFileManager fileManager, File orig, ZipFile zdir, RelativeDirectory prefix) throws IOException {
+ super(fileManager, zdir, false);
+ this.origFile = orig;
+ this.prefix = prefix;
+ initMap();
+ }
+
+ @Override
+ void addZipEntry(ZipEntry entry) {
+ String name = entry.getName();
+ if (!name.startsWith(prefix.path)) {
+ return;
+ }
+ name = name.substring(prefix.path.length());
+ int i = name.lastIndexOf('/');
+ RelativeDirectory dirname = new RelativeDirectory(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(RelativeDirectory subdirectory, String file) {
+ RelativeDirectory prefix_subdir = new RelativeDirectory(prefix, subdirectory.path);
+ ZipEntry ze = new RelativeFile(prefix_subdir, file).getZipEntry(zfile);
+ return new SymbolFileObject(this, file, ze);
+ }
+
+ @Override
+ public String toString() {
+ return "SymbolArchive[" + zfile.getName() + "]";
+ }
+
+ /**
+ * A subclass of JavaFileObject representing zip entries in a symbol file.
+ */
+ public static class SymbolFileObject extends ZipFileObject {
+ protected SymbolFileObject(SymbolArchive zarch, String name, ZipEntry entry) {
+ super(zarch, name, entry);
+ }
+
+ @Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ String entryName = entry.getName();
+ String prefix = ((SymbolArchive) zarch).prefix.path;
+ if (entryName.startsWith(prefix))
+ entryName = entryName.substring(prefix.length());
+ return removeExtension(entryName).replace('/', '.');
+ }
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipArchive.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.file.JavacFileManager.Archive;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * 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 ZipArchive implements Archive {
+
+ public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException {
+ this(fm, zfile, true);
+ }
+
+ protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException {
+ this.fileManager = fm;
+ this.zfile = zfile;
+ this.map = new HashMap<RelativeDirectory,List<String>>();
+ if (initMap)
+ initMap();
+ }
+
+ protected void initMap() throws IOException {
+ for (Enumeration<? extends ZipEntry> e = zfile.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('/');
+ RelativeDirectory dirname = new RelativeDirectory(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(RelativePath name) {
+ RelativeDirectory dirname = name.dirname();
+ String basename = name.basename();
+ if (basename.length() == 0)
+ return false;
+ List<String> list = map.get(dirname);
+ return (list != null && list.contains(basename));
+ }
+
+ public List<String> getFiles(RelativeDirectory subdirectory) {
+ return map.get(subdirectory);
+ }
+
+ public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+ ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile);
+ return new ZipFileObject(this, file, ze);
+ }
+
+ public Set<RelativeDirectory> getSubdirectories() {
+ return map.keySet();
+ }
+
+ public void close() throws IOException {
+ zfile.close();
+ }
+
+ @Override
+ public String toString() {
+ return "ZipArchive[" + zfile.getName() + "]";
+ }
+
+ private File getAbsoluteFile() {
+ File absFile = (absFileRef == null ? null : absFileRef.get());
+ if (absFile == null) {
+ absFile = new File(zfile.getName()).getAbsoluteFile();
+ absFileRef = new SoftReference<File>(absFile);
+ }
+ return absFile;
+ }
+
+ /**
+ * The file manager that created this archive.
+ */
+ protected JavacFileManager fileManager;
+ /**
+ * The index for the contents of this archive.
+ */
+ protected final Map<RelativeDirectory,List<String>> map;
+ /**
+ * The zip file for the archive.
+ */
+ protected final ZipFile zfile;
+ /**
+ * A reference to the absolute filename for the zip file for the archive.
+ */
+ protected Reference<File> absFileRef;
+
+ /**
+ * A subclass of JavaFileObject representing zip entries.
+ */
+ public static class ZipFileObject extends BaseFileObject {
+
+ private String name;
+ ZipArchive zarch;
+ ZipEntry entry;
+
+ protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
+ super(zarch.fileManager);
+ this.zarch = zarch;
+ this.name = name;
+ this.entry = entry;
+ }
+
+ public URI toUri() {
+ File zipFile = new File(zarch.zfile.getName());
+ return createJarUri(zipFile, entry.getName());
+ }
+
+ //@Override
+ public String getName() {
+ return zarch.zfile.getName() + "(" + entry.getName() + ")";
+ }
+
+ //@Override
+ public String getShortName() {
+ return new File(zarch.zfile.getName()).getName() + "(" + entry + ")";
+ }
+
+ //@Override
+ public JavaFileObject.Kind getKind() {
+ return getKind(entry.getName());
+ }
+
+ //@Override
+ public InputStream openInputStream() throws IOException {
+ return zarch.zfile.getInputStream(entry);
+ }
+
+ //@Override
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ CharBuffer cb = fileManager.getCachedContent(this);
+ if (cb == null) {
+ InputStream in = zarch.zfile.getInputStream(entry);
+ try {
+ ByteBuffer bb = fileManager.makeByteBuffer(in);
+ JavaFileObject prev = fileManager.log.useSource(this);
+ try {
+ cb = fileManager.decode(bb, ignoreEncodingErrors);
+ } finally {
+ fileManager.log.useSource(prev);
+ }
+ fileManager.recycleByteBuffer(bb);
+ if (!ignoreEncodingErrors) {
+ fileManager.cache(this, cb);
+ }
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ //@Override
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ public long getLastModified() {
+ return entry.getTime();
+ }
+
+ //@Override
+ public boolean delete() {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+ }
+
+ //@Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ String entryName = entry.getName();
+ return removeExtension(entryName).replace('/', '.');
+ }
+
+ //@Override
+ 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);
+ }
+
+ /**
+ * Check if two file objects are equal.
+ * Two ZipFileObjects are equal if the absolute paths of the underlying
+ * zip files are equal and if the paths within those zip files are equal.
+ */
+ //@Override
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
+ if (!(other instanceof ZipFileObject))
+ return false;
+
+ ZipFileObject o = (ZipFileObject) other;
+ return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile())
+ && name.equals(o.name);
+ }
+
+ //@Override
+ public int hashCode() {
+ return zarch.getAbsoluteFile().hashCode() + name.hashCode();
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,1338 @@
+/*
+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+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;
+
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+
+/** 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.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * 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 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<RelativeDirectory, DirectoryEntry> directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
+ private Set<RelativeDirectory> allDirs = Collections.<RelativeDirectory>emptySet();
+
+ // ZipFileIndex data entries
+ private File zipFile;
+ private Reference<File> absFileRef;
+ private long zipFileLastModified = NOT_MODIFIED;
+ private RandomAccessFile zipRandomFile;
+ private Entry[] entries;
+
+ private boolean readFromIndex = false;
+ private File zipIndexFile = null;
+ private boolean triedToReadIndex = false;
+ final RelativeDirectory symbolFilePrefix;
+ 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;
+
+ private Map <String, SoftReference<RelativeDirectory>> relativeDirectoryCache =
+ new HashMap<String, SoftReference<RelativeDirectory>>();
+
+ /**
+ * 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,
+ RelativeDirectory symbolFilePrefix,
+ 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, symbolFilePrefix, 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, RelativeDirectory symbolFilePrefix, boolean writeIndex,
+ boolean useCache, String cacheLocation) throws IOException {
+ this.zipFile = zipFile;
+ this.symbolFilePrefix = symbolFilePrefix;
+ this.symbolFilePrefixLength = (symbolFilePrefix == null ? 0 :
+ symbolFilePrefix.getPath().getBytes("UTF-8").length);
+ 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[" + 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.<RelativeDirectory, DirectoryEntry>emptyMap();
+ allDirs = Collections.<RelativeDirectory>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 = Entry.EMPTY_ARRAY;
+ directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
+ zipFileLastModified = NOT_MODIFIED;
+ allDirs = Collections.<RelativeDirectory>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.
+ */
+ Entry getZipIndexEntry(RelativePath path) {
+ lock.lock();
+ try {
+ checkIndex();
+ DirectoryEntry de = directories.get(path.dirname());
+ String lookFor = path.basename();
+ 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(RelativeDirectory path) {
+ 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> getDirectories(RelativeDirectory path) {
+ lock.lock();
+ try {
+ checkIndex();
+
+ 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<RelativeDirectory> getAllDirectories() {
+ lock.lock();
+ try {
+ checkIndex();
+ if (allDirs == Collections.EMPTY_SET) {
+ allDirs = new HashSet<RelativeDirectory>(directories.keySet());
+ }
+
+ return allDirs;
+ }
+ catch (IOException e) {
+ return Collections.<RelativeDirectory>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(RelativePath path) {
+ lock.lock();
+ try {
+ checkIndex();
+ return getZipIndexEntry(path) != null;
+ }
+ catch (IOException e) {
+ return false;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean isDirectory(RelativePath path) throws IOException {
+ lock.lock();
+ try {
+ // The top level in a zip file is always a directory.
+ if (path.getPath().length() == 0) {
+ lastReferenceTimeStamp = System.currentTimeMillis();
+ return true;
+ }
+
+ checkIndex();
+ return directories.get(path) != null;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public long getLastModified(RelativeFile path) throws IOException {
+ lock.lock();
+ try {
+ Entry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException();
+ return entry.getLastModified();
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public int length(RelativeFile path) throws IOException {
+ lock.lock();
+ try {
+ Entry 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(RelativeFile path) throws IOException {
+ lock.lock();
+ try {
+ Entry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException("Path not found in ZIP: " + path.path);
+ return read(entry);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ byte[] read(Entry entry) throws IOException {
+ lock.lock();
+ try {
+ openFile();
+ byte[] result = readBytes(entry);
+ closeFile();
+ return result;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ public int read(RelativeFile path, byte[] buffer) throws IOException {
+ lock.lock();
+ try {
+ Entry entry = getZipIndexEntry(path);
+ if (entry == null)
+ throw new FileNotFoundException();
+ return read(entry, buffer);
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ int read(Entry entry, byte[] buffer)
+ throws IOException {
+ lock.lock();
+ try {
+ int result = readBytes(entry, buffer);
+ return result;
+ }
+ finally {
+ lock.unlock();
+ }
+ }
+
+ private byte[] readBytes(Entry 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(Entry 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(Entry 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 RelativeDirectory 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);
+
+ // Add each of the files
+ if (entryCount > 0) {
+ directories = new HashMap<RelativeDirectory, DirectoryEntry>();
+ ArrayList<Entry> entryList = new ArrayList<Entry>();
+ int pos = 2;
+ for (int i = 0; i < entryCount; i++) {
+ pos = readEntry(pos, entryList, directories);
+ }
+
+ // Add the accumulated dirs into the same list
+ for (RelativeDirectory d: directories.keySet()) {
+ // use shared RelativeDirectory objects for parent dirs
+ RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath());
+ String file = d.basename();
+ Entry zipFileIndexEntry = new Entry(parent, file);
+ zipFileIndexEntry.isDir = true;
+ entryList.add(zipFileIndexEntry);
+ }
+
+ entries = entryList.toArray(new Entry[entryList.size()]);
+ Arrays.sort(entries);
+ } else {
+ cleanupState();
+ }
+ }
+
+ private int readEntry(int pos, List<Entry> entryList,
+ Map<RelativeDirectory, 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;
+ }
+ // Force any '\' to '/'. Keep the position of the last separator.
+ for (int index = fileStart; index < fileEnd; index++) {
+ byte nextByte = zipDir[index];
+ if (nextByte == (byte)'\\') {
+ zipDir[index] = (byte)'/';
+ fileStart = index + 1;
+ } else if (nextByte == (byte)'/') {
+ fileStart = index + 1;
+ }
+ }
+
+ RelativeDirectory directory = null;
+ if (fileStart == dirStart)
+ directory = getRelativeDirectory("");
+ 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 = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8"));
+ lastDir = directory;
+
+ // Enter also all the parent directories
+ RelativeDirectory tempDirectory = directory;
+
+ while (directories.get(tempDirectory) == null) {
+ directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
+ if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1)
+ break;
+ else {
+ // use shared RelativeDirectory objects for parent dirs
+ tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath());
+ }
+ }
+ }
+ else {
+ if (directories.get(directory) == null) {
+ directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
+ }
+ }
+
+ // For each dir create also a file
+ if (fileStart != fileEnd) {
+ Entry entry = new Entry(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 RelativeDirectory 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<Entry> zipFileEntries = com.sun.tools.javac.util.List.<Entry>nil();
+
+ private List<Entry> entries = new ArrayList<Entry>();
+
+ private ZipFileIndex zipFileIndex;
+
+ private int numEntries;
+
+ DirectoryEntry(RelativeDirectory dirName, ZipFileIndex index) {
+ filesInited = false;
+ directoriesInited = false;
+ entriesInited = false;
+
+ this.dirName = dirName;
+ this.zipFileIndex = index;
+ }
+
+ private com.sun.tools.javac.util.List<String> getFiles() {
+ if (!filesInited) {
+ initEntries();
+ for (Entry 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) {
+ initEntries();
+ for (Entry e : entries) {
+ if (e.isDir) {
+ zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
+ }
+ }
+ directoriesInited = true;
+ }
+ return zipFileEntriesDirectories;
+ }
+
+ private com.sun.tools.javac.util.List<Entry> getEntries() {
+ if (!zipFileEntriesInited) {
+ initEntries();
+ zipFileEntries = com.sun.tools.javac.util.List.nil();
+ for (Entry zfie : entries) {
+ zipFileEntries = zipFileEntries.append(zfie);
+ }
+ zipFileEntriesInited = true;
+ }
+ return zipFileEntries;
+ }
+
+ private Entry getEntry(String rootName) {
+ initEntries();
+ int index = Collections.binarySearch(entries, new Entry(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 Entry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
+ int to = -Arrays.binarySearch(zipFileIndex.entries,
+ new Entry(dirName, MAX_CHAR)) - 1;
+
+ 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();
+
+ Entry rfie = new Entry(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<Entry> 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<RelativeDirectory, DirectoryEntry>();
+ int numDirs = raf.readInt();
+ for (int nDirs = 0; nDirs < numDirs; nDirs++) {
+ int dirNameBytesLen = raf.readInt();
+ byte [] dirNameBytes = new byte[dirNameBytesLen];
+ raf.read(dirNameBytes);
+
+ RelativeDirectory dirNameStr = getRelativeDirectory(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;
+
+ List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
+ Map<RelativeDirectory, Long> offsets = new HashMap<RelativeDirectory, Long>();
+ raf.writeInt(directories.keySet().size());
+ writtenSoFar += 4;
+
+ for (RelativeDirectory dirName: directories.keySet()) {
+ DirectoryEntry dirEntry = directories.get(dirName);
+
+ directoriesToWrite.add(dirEntry);
+
+ // Write the dir name bytes
+ byte [] dirNameBytes = dirName.getPath().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<Entry> 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<Entry> entries = de.getEntriesAsCollection();
+ for (Entry 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;
+ }
+
+ File getAbsoluteFile() {
+ File absFile = (absFileRef == null ? null : absFileRef.get());
+ if (absFile == null) {
+ absFile = zipFile.getAbsoluteFile();
+ absFileRef = new SoftReference<File>(absFile);
+ }
+ return absFile;
+ }
+
+ private RelativeDirectory getRelativeDirectory(String path) {
+ RelativeDirectory rd;
+ SoftReference<RelativeDirectory> ref = relativeDirectoryCache.get(path);
+ if (ref != null) {
+ rd = ref.get();
+ if (rd != null)
+ return rd;
+ }
+ rd = new RelativeDirectory(path);
+ relativeDirectoryCache.put(path, new SoftReference<RelativeDirectory>(rd));
+ return rd;
+ }
+
+ static class Entry implements Comparable<Entry> {
+ public static final Entry[] EMPTY_ARRAY = {};
+
+ // Directory related
+ RelativeDirectory dir;
+ boolean isDir;
+
+ // File related
+ String name;
+
+ int offset;
+ int size;
+ int compressedSize;
+ long javatime;
+
+ private int nativetime;
+
+ public Entry(RelativePath path) {
+ this(path.dirname(), path.basename());
+ }
+
+ public Entry(RelativeDirectory directory, String name) {
+ this.dir = directory;
+ this.name = name;
+ }
+
+ public String getName() {
+ return new RelativeFile(dir, name).getPath();
+ }
+
+ public String getFileName() {
+ return name;
+ }
+
+ public long getLastModified() {
+ if (javatime == 0) {
+ javatime = dosToJavaTime(nativetime);
+ }
+ return javatime;
+ }
+
+ // based on dosToJavaTime in java.util.Zip, but avoiding the
+ // use of deprecated Date constructor
+ private static long dosToJavaTime(int dtime) {
+ Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, ((dtime >> 25) & 0x7f) + 1980);
+ c.set(Calendar.MONTH, ((dtime >> 21) & 0x0f) - 1);
+ c.set(Calendar.DATE, ((dtime >> 16) & 0x1f));
+ c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
+ c.set(Calendar.MINUTE, ((dtime >> 5) & 0x3f));
+ c.set(Calendar.SECOND, ((dtime << 1) & 0x3e));
+ c.set(Calendar.MILLISECOND, 0);
+ return c.getTimeInMillis();
+ }
+
+ void setNativeTime(int natTime) {
+ nativetime = natTime;
+ }
+
+ public boolean isDirectory() {
+ return isDir;
+ }
+
+ public int compareTo(Entry other) {
+ RelativeDirectory otherD = other.dir;
+ if (dir != otherD) {
+ int c = dir.compareTo(otherD);
+ if (c != 0)
+ return c;
+ }
+ return name.compareTo(other.name);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Entry))
+ return false;
+ Entry other = (Entry) o;
+ return dir.equals(other.dir) && name.equals(other.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 97 * hash + (this.dir != null ? this.dir.hashCode() : 0);
+ hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+
+ public String toString() {
+ return isDir ? ("Dir:" + dir + " : " + name) :
+ (dir + ":" + name);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.file;
+
+import java.io.IOException;
+import java.util.Set;
+import javax.tools.JavaFileObject;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+
+import com.sun.tools.javac.file.JavacFileManager.Archive;
+import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
+import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.List;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * 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 ZipFileIndexArchive implements Archive {
+
+ private final ZipFileIndex zfIndex;
+ private JavacFileManager fileManager;
+
+ public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
+ super();
+ this.fileManager = fileManager;
+ this.zfIndex = zdir;
+ }
+
+ public boolean contains(RelativePath name) {
+ return zfIndex.contains(name);
+ }
+
+ public List<String> getFiles(RelativeDirectory subdirectory) {
+ return zfIndex.getFiles(subdirectory);
+ }
+
+ public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
+ RelativeFile fullZipFileName = new RelativeFile(subdirectory, file);
+ ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName);
+ JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile());
+ return ret;
+ }
+
+ public Set<RelativeDirectory> getSubdirectories() {
+ return zfIndex.getAllDirectories();
+ }
+
+ public void close() throws IOException {
+ zfIndex.close();
+ }
+
+ @Override
+ public String toString() {
+ return "ZipFileIndexArchive[" + zfIndex + "]";
+ }
+
+ /**
+ * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation.
+ */
+ public static class ZipFileIndexFileObject extends BaseFileObject {
+
+ /** The entry's name.
+ */
+ private String name;
+
+ /** The zipfile containing the entry.
+ */
+ ZipFileIndex zfIndex;
+
+ /** The underlying zip entry object.
+ */
+ ZipFileIndex.Entry entry;
+
+ /** The InputStream for this zip entry (file.)
+ */
+ InputStream inputStream = null;
+
+ /** The name of the zip file where this entry resides.
+ */
+ File zipName;
+
+
+ ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) {
+ super(fileManager);
+ this.name = entry.getFileName();
+ this.zfIndex = zfIndex;
+ this.entry = entry;
+ this.zipName = zipFileName;
+ }
+
+ //@Override
+ public URI toUri() {
+ return createJarUri(zipName, getPrefixedEntryName());
+ }
+
+ //@Override
+ public String getName() {
+ return zipName + "(" + getPrefixedEntryName() + ")";
+ }
+
+ //@Override
+ public String getShortName() {
+ return zipName.getName() + "(" + entry.getName() + ")";
+ }
+
+ //@Override
+ public JavaFileObject.Kind getKind() {
+ return getKind(entry.getName());
+ }
+
+ //@Override
+ public InputStream openInputStream() throws IOException {
+ if (inputStream == null) {
+ assert entry != null; // see constructor
+ inputStream = new ByteArrayInputStream(zfIndex.read(entry));
+ }
+ return inputStream;
+ }
+
+ //@Override
+ public OutputStream openOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ CharBuffer cb = fileManager.getCachedContent(this);
+ if (cb == null) {
+ InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
+ try {
+ ByteBuffer bb = fileManager.makeByteBuffer(in);
+ JavaFileObject prev = fileManager.log.useSource(this);
+ try {
+ cb = fileManager.decode(bb, ignoreEncodingErrors);
+ } finally {
+ fileManager.log.useSource(prev);
+ }
+ fileManager.recycleByteBuffer(bb); // save for next time
+ if (!ignoreEncodingErrors)
+ fileManager.cache(this, cb);
+ } finally {
+ in.close();
+ }
+ }
+ return cb;
+ }
+
+ //@Override
+ public Writer openWriter() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ public long getLastModified() {
+ return entry.getLastModified();
+ }
+
+ //@Override
+ public boolean delete() {
+ throw new UnsupportedOperationException();
+ }
+
+ //@Override
+ protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
+ return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
+ }
+
+ //@Override
+ protected String inferBinaryName(Iterable<? extends File> path) {
+ String entryName = entry.getName();
+ if (zfIndex.symbolFilePrefix != null) {
+ String prefix = zfIndex.symbolFilePrefix.path;
+ if (entryName.startsWith(prefix))
+ entryName = entryName.substring(prefix.length());
+ }
+ return removeExtension(entryName).replace('/', '.');
+ }
+
+ //@Override
+ 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);
+ }
+
+ /**
+ * Check if two file objects are equal.
+ * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying
+ * zip files are equal and if the paths within those zip files are equal.
+ */
+ //@Override
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
+ if (!(other instanceof ZipFileIndexFileObject))
+ return false;
+
+ ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
+ return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile())
+ && name.equals(o.name);
+ }
+
+ //@Override
+ public int hashCode() {
+ return zfIndex.getAbsoluteFile().hashCode() + name.hashCode();
+ }
+
+ private String getPrefixedEntryName() {
+ if (zfIndex.symbolFilePrefix != null)
+ return zfIndex.symbolFilePrefix.path + entry.getName();
+ else
+ return entry.getName();
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+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.JCDiagnostic.SimpleDiagnosticPosition;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+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.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+
+/**
+ * Utility methods for building a filemanager.
+ * There are no references here to file-system specific objects such as
+ * java.io.File or java.nio.file.Path.
+ */
+public class BaseFileManager {
+ protected BaseFileManager(Charset charset) {
+ this.charset = charset;
+ byteBufferCache = new ByteBufferCache();
+ }
+
+ /**
+ * Set the context for JavacPathFileManager.
+ */
+ protected void setContext(Context context) {
+ log = Log.instance(context);
+ options = Options.instance(context);
+ classLoaderClass = options.get("procloader");
+ }
+
+ /**
+ * The log to be used for error reporting.
+ */
+ public Log log;
+
+ /**
+ * User provided charset (through javax.tools).
+ */
+ protected Charset charset;
+
+ protected Options options;
+
+ protected String classLoaderClass;
+
+ 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);
+ }
+
+ protected ClassLoader getClassLoader(URL[] urls) {
+ ClassLoader thisClassLoader = getClass().getClassLoader();
+
+ // Bug: 6558476
+ // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
+ // On older versions, try the following, to get a closeable classloader.
+
+ // 1: Allow client to specify the class to use via hidden option
+ if (classLoaderClass != null) {
+ try {
+ Class<? extends ClassLoader> loader =
+ Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
+ Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
+ Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
+ return constr.newInstance(new Object[] { urls, thisClassLoader });
+ } catch (Throwable t) {
+ // ignore errors loading user-provided class loader, fall through
+ }
+ }
+
+ // 2: If URLClassLoader implements Closeable, use that.
+ if (Closeable.class.isAssignableFrom(URLClassLoader.class))
+ return new URLClassLoader(urls, thisClassLoader);
+
+ // 3: Try using private reflection-based CloseableURLClassLoader
+ try {
+ return new CloseableURLClassLoader(urls, thisClassLoader);
+ } catch (Throwable t) {
+ // ignore errors loading workaround class loader, fall through
+ }
+
+ // 4: If all else fails, use plain old standard URLClassLoader
+ return new URLClassLoader(urls, thisClassLoader);
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="Option handling">
+ 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;
+ }
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="Encoding">
+ private String defaultEncodingName;
+ private String getDefaultEncodingName() {
+ if (defaultEncodingName == null) {
+ defaultEncodingName =
+ new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();
+ }
+ return defaultEncodingName;
+ }
+
+ public String getEncodingName() {
+ String encName = options.get(OptionName.ENCODING);
+ if (encName == null)
+ return getDefaultEncodingName();
+ else
+ return encName;
+ }
+
+ public 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 CharsetDecoder getDecoder(String encodingName, boolean ignoreEncodingErrors) {
+ Charset cs = (this.charset == null)
+ ? Charset.forName(encodingName)
+ : this.charset;
+ CharsetDecoder decoder = cs.newDecoder();
+
+ CodingErrorAction action;
+ if (ignoreEncodingErrors)
+ action = CodingErrorAction.REPLACE;
+ else
+ action = CodingErrorAction.REPORT;
+
+ return decoder
+ .onMalformedInput(action)
+ .onUnmappableCharacter(action);
+ }
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
+ /**
+ * Make a byte buffer from an input stream.
+ */
+ public ByteBuffer makeByteBuffer(InputStream in)
+ throws IOException {
+ int limit = in.available();
+ 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();
+ }
+
+ public void recycleByteBuffer(ByteBuffer bb) {
+ byteBufferCache.put(bb);
+ }
+
+ /**
+ * 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;
+ // </editor-fold>
+
+ // <editor-fold defaultstate="collapsed" desc="Content cache">
+ public CharBuffer getCachedContent(JavaFileObject file) {
+ SoftReference<CharBuffer> r = contentCache.get(file);
+ return (r == null ? null : r.get());
+ }
+
+ public void cache(JavaFileObject file, CharBuffer cb) {
+ contentCache.put(file, new SoftReference<CharBuffer>(cb));
+ }
+
+ protected final Map<JavaFileObject, SoftReference<CharBuffer>> contentCache
+ = new HashMap<JavaFileObject, SoftReference<CharBuffer>>();
+ // </editor-fold>
+
+ public static Kind getKind(String name) {
+ if (name.endsWith(Kind.CLASS.extension))
+ return Kind.CLASS;
+ else if (name.endsWith(Kind.SOURCE.extension))
+ return Kind.SOURCE;
+ else if (name.endsWith(Kind.HTML.extension))
+ return Kind.HTML;
+ else
+ return Kind.OTHER;
+ }
+
+ protected static <T> T nullCheck(T o) {
+ o.getClass(); // null check
+ return o;
+ }
+
+ protected static <T> Collection<T> nullCheck(Collection<T> it) {
+ for (T t : it)
+ t.getClass(); // null check
+ return it;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6508981/TestInferBinaryName.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6508981
+ * @summary cleanup file separator handling in JavacFileManager
+ * (This test is specifically to test the new impl of inferBinaryName)
+ * @build p.A
+ * @run main TestInferBinaryName
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Options;
+
+import static javax.tools.JavaFileObject.Kind.*;
+import static javax.tools.StandardLocation.*;
+
+
+/**
+ * Verify the various implementations of inferBinaryName, but configuring
+ * different instances of a file manager, getting a file object, and checking
+ * the impl of inferBinaryName for that file object.
+ */
+public class TestInferBinaryName {
+ static final boolean IGNORE_SYMBOL_FILE = false;
+ static final boolean USE_SYMBOL_FILE = true;
+ static final boolean DONT_USE_ZIP_FILE_INDEX = false;
+ static final boolean USE_ZIP_FILE_INDEX = true;
+
+ public static void main(String... args) throws Exception {
+ new TestInferBinaryName().run();
+ }
+
+ void run() throws Exception {
+ //System.err.println(System.getProperties());
+ testDirectory();
+ testSymbolArchive();
+ testZipArchive();
+ testZipFileIndexArchive();
+ testZipFileIndexArchive2();
+ if (errors > 0)
+ throw new Exception(errors + " error found");
+ }
+
+ void testDirectory() throws IOException {
+ String testClassName = "p.A";
+ JavaFileManager fm =
+ getFileManager("test.classes", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
+ test("testDirectory",
+ fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
+ }
+
+ void testSymbolArchive() throws IOException {
+ String testClassName = "java.lang.String";
+ JavaFileManager fm =
+ getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
+ test("testSymbolArchive",
+ fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject");
+ }
+
+ void testZipArchive() throws IOException {
+ String testClassName = "java.lang.String";
+ JavaFileManager fm =
+ getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
+ test("testZipArchive",
+ fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
+ }
+
+ void testZipFileIndexArchive() throws IOException {
+ String testClassName = "java.lang.String";
+ JavaFileManager fm =
+ getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
+ test("testZipFileIndexArchive",
+ fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ }
+
+ void testZipFileIndexArchive2() throws IOException {
+ String testClassName = "java.lang.String";
+ JavaFileManager fm =
+ getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
+ test("testZipFileIndexArchive2",
+ fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ }
+
+ /**
+ * @param testName for debugging
+ * @param fm suitably configured file manager
+ * @param testClassName the classname to test
+ * @param implClassName the expected classname of the JavaFileObject impl,
+ * used for checking that we are checking the expected impl of
+ * inferBinaryName
+ */
+ void test(String testName,
+ JavaFileManager fm, String testClassName, String implClassName) throws IOException {
+ JavaFileObject fo = fm.getJavaFileForInput(CLASS_PATH, testClassName, CLASS);
+ if (fo == null) {
+ System.err.println("Can't find " + testClassName);
+ errors++;
+ return;
+ }
+
+ String cn = fo.getClass().getName();
+ String bn = fm.inferBinaryName(CLASS_PATH, fo);
+ System.err.println(testName + " " + cn + " " + bn);
+ check(cn, implClassName);
+ check(bn, testClassName);
+ System.err.println("OK");
+ }
+
+ JavaFileManager getFileManager(String classpathProperty,
+ boolean symFileKind,
+ boolean zipFileIndexKind)
+ throws IOException {
+ Context ctx = new Context();
+ // uugh, ugly back door, should be cleaned up, someday
+ if (zipFileIndexKind == USE_ZIP_FILE_INDEX)
+ System.clearProperty("useJavaUtilZip");
+ else
+ System.setProperty("useJavaUtilZip", "true");
+ Options options = Options.instance(ctx);
+ if (symFileKind == IGNORE_SYMBOL_FILE)
+ options.put("ignore.symbol.file", "true");
+ JavacFileManager fm = new JavacFileManager(ctx, false, null);
+ List<File> path = getPath(System.getProperty(classpathProperty));
+ fm.setLocation(CLASS_PATH, path);
+ return fm;
+ }
+
+ List<File> getPath(String s) {
+ List<File> path = new ArrayList<File>();
+ for (String f: s.split(File.pathSeparator)) {
+ if (f.length() > 0)
+ path.add(new File(f));
+ }
+ //System.err.println("path: " + path);
+ return path;
+ }
+
+ void check(String found, String expect) {
+ if (!found.equals(expect)) {
+ System.err.println("Expected: " + expect);
+ System.err.println(" Found: " + found);
+ errors++;
+ }
+ }
+
+ private int errors;
+}
+
+class A { }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6508981/p/A.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package p;
+class A { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/T6625520.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import com.sun.tools.javac.file.*;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.*;
+
+/*
+ * @test
+ * @bug 6625520
+ * @summary javac handles missing entries on classpath badly
+ */
+public class T6625520 {
+ public static void main(String[] args) throws Exception {
+ new T6625520().run();
+ }
+
+ void run() throws Exception {
+ Context c = new Context();
+ DiagnosticCollector<JavaFileObject> dc =
+ new DiagnosticCollector<JavaFileObject>();
+ c.put(DiagnosticListener.class, dc);
+ StandardJavaFileManager fm = new JavacFileManager(c, false, null);
+ fm.setLocation(StandardLocation.CLASS_PATH,
+ Arrays.asList(new File("DOES_NOT_EXIST.jar")));
+ FileObject fo = fm.getFileForInput(StandardLocation.CLASS_PATH,
+ "p", "C.java");
+ System.err.println(fo + "\n" + dc.getDiagnostics());
+ if (dc.getDiagnostics().size() > 0)
+ throw new Exception("unexpected diagnostics found");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/T6705935.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6705935
+ * @summary javac reports path name of entry in ZipFileIndex incorectly
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import com.sun.tools.javac.file.*;
+
+public class T6705935 {
+ public static void main(String... args) throws Exception {
+ new T6705935().run();
+ }
+
+ public void run() throws Exception {
+ File java_home = new File(System.getProperty("java.home"));
+ if (java_home.getName().equals("jre"))
+ java_home = java_home.getParentFile();
+
+ JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+ JavaFileManager fm = c.getStandardFileManager(null, null, null);
+ for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH,
+ "java.lang",
+ Collections.singleton(JavaFileObject.Kind.CLASS),
+ false)) {
+ String p = fo.getName();
+ int bra = p.indexOf("(");
+ int ket = p.indexOf(")");
+ //System.err.println(bra + "," + ket + "," + p.length());
+ if (bra == -1 || ket != p.length() -1)
+ throw new Exception("unexpected path: " + p + "[" + bra + "," + ket + "," + p.length());
+ String part1 = p.substring(0, bra);
+ String part2 = p.substring(bra + 1, ket);
+ //System.err.println("[" + part1 + "|" + part2 + "]" + " " + java_home);
+ if (part1.equals(part2) || !part1.startsWith(java_home.getPath()))
+ throw new Exception("bad path: " + p);
+
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/6411310/Test.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6410367 6411310
+ * @summary FileObject should support user-friendly names via getName()
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.*;
+import javax.tools.*;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Options;
+
+// Test FileObject.getName returned from JavacFileManager and its support classes.
+
+public class Test {
+ public static void main(String... args) throws Exception {
+ new Test().run();
+ }
+
+ Set<String> foundClasses = new TreeSet<String>();
+ Set<String> foundJars = new TreeSet<String>();
+
+ void run() throws Exception {
+ File rt_jar = findRtJar();
+
+ // names for entries to be created in directories and jar files
+ String[] entries = { "p/A.java", "p/A.class", "p/resources/A-1.html" };
+
+ // test various combinations of directories and jar files, intended to
+ // cover all sources of file objects within JavacFileManager's support classes
+
+ test(createFileManager(), createDir("dir", entries), "p", entries);
+ test(createFileManager(), createDir("a b/dir", entries), "p", entries);
+
+ for (boolean useJavaUtilZip: new boolean[] { false, true }) {
+ test(createFileManager(useJavaUtilZip), createJar("jar", entries), "p", entries);
+ test(createFileManager(useJavaUtilZip), createJar("jar jar", entries), "p", entries);
+
+ for (boolean useSymbolFile: new boolean[] { false, true }) {
+ test(createFileManager(useJavaUtilZip, useSymbolFile), rt_jar, "java.lang.ref", null);
+ }
+ }
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+
+ // Verify that we hit all the impl classes we intended
+ checkCoverage("classes", foundClasses,
+ "RegularFileObject", "SymbolFileObject", "ZipFileIndexFileObject", "ZipFileObject");
+
+ // Verify that we hit the jar files we intended, specifically ct.sym as well as rt.jar
+ checkCoverage("jar files", foundJars,
+ "ct.sym", "jar", "jar jar", "rt.jar");
+ }
+
+ // use a new file manager for each test
+ void test(StandardJavaFileManager fm, File f, String pkg, String[] entries) throws Exception {
+ System.err.println("Test " + f);
+ try {
+ if (f.isDirectory()) {
+ for (File dir: new File[] { f, f.getAbsoluteFile() }) {
+ for (String e: entries) {
+ JavaFileObject fo = fm.getJavaFileObjects(new File(dir, e)).iterator().next();
+ test(fo, dir, e);
+ }
+ }
+ }
+
+ fm.setLocation(StandardLocation.CLASS_PATH, Collections.singleton(f));
+ fm.setLocation(StandardLocation.SOURCE_PATH, Collections.singleton(f.getAbsoluteFile()));
+ for (StandardLocation l: EnumSet.of(StandardLocation.CLASS_PATH, StandardLocation.SOURCE_PATH)) {
+ for (JavaFileObject fo: fm.list(l, pkg, EnumSet.allOf(JavaFileObject.Kind.class), true)) {
+ // we could use fm.getLocation but the following guarantees we preserve the original filename
+ File dir = (l == StandardLocation.CLASS_PATH ? f : f.getAbsoluteFile());
+ char sep = (dir.isDirectory() ? File.separatorChar : '/');
+ String b = fm.inferBinaryName(l, fo);
+ String e = fo.getKind().extension;
+ test(fo, dir, b.replace('.', sep) + e);
+ }
+ }
+ } finally {
+ fm.close();
+ }
+ }
+
+ void test(JavaFileObject fo, File dir, String p) {
+ System.err.println("Test: " + fo);
+ String expect = dir.isDirectory() ? new File(dir, p).getPath() : (dir.getPath() + "(" + p + ")");
+ String found = fo.getName();
+ // if ct.sym is found, replace it with the equivalent rt.jar
+ String found2 = found.replaceAll("lib([\\\\/])ct.sym\\(META-INF/sym/rt.jar/", "jre$1lib$1rt.jar(");
+ if (!expect.equals(found2)) {
+ System.err.println("expected: " + expect);
+ System.err.println(" found: " + found);
+ if (!found.equals(found2))
+ System.err.println(" found2: " + found2);
+ error("Failed: " + fo);
+ }
+
+ // record the file object class name for coverage checks later
+ foundClasses.add(fo.getClass().getSimpleName());
+
+ if (found.contains("(")) {
+ // record access to the jar file for coverage checks later
+ foundJars.add(new File(found.substring(0, found.indexOf("("))).getName());
+ }
+ }
+
+ void checkCoverage(String label, Set<String> found, String... expect) throws Exception {
+ Set<String> e = new TreeSet<String>(Arrays.asList(expect));
+ if (!found.equals(e)) {
+ e.removeAll(found);
+ throw new Exception("expected " + label + " not used: " + e);
+ }
+ }
+
+ JavacFileManager createFileManager() {
+ return createFileManager(false, false);
+ }
+
+ JavacFileManager createFileManager(boolean useJavaUtilZip) {
+ return createFileManager(useJavaUtilZip, false);
+ }
+
+ JavacFileManager createFileManager(boolean useJavaUtilZip, boolean useSymbolFile) {
+ // javac should really not be using system properties like this
+ // -- it should really be using (hidden) options -- but until then
+ // take care to leave system properties as we find them, so as not
+ // to adversely affect other tests that might follow.
+ String prev = System.getProperty("useJavaUtilZip");
+ boolean resetProperties = false;
+ try {
+ if (useJavaUtilZip) {
+ System.setProperty("useJavaUtilZip", "true");
+ resetProperties = true;
+ } else if (System.getProperty("useJavaUtilZip") != null) {
+ System.getProperties().remove("useJavaUtilZip");
+ resetProperties = true;
+ }
+
+ Context c = new Context();
+ if (!useSymbolFile) {
+ Options options = Options.instance(c);
+ options.put("ignore.symbol.file", "true");
+ }
+
+ return new JavacFileManager(c, false, null);
+ } finally {
+ if (resetProperties) {
+ if (prev == null) {
+ System.getProperties().remove("useJavaUtilZip");
+ } else {
+ System.setProperty("useJavaUtilZip", prev);
+ }
+ }
+ }
+ }
+
+ File createDir(String name, String... entries) throws Exception {
+ File dir = new File(name);
+ if (!dir.mkdirs())
+ throw new Exception("cannot create directories " + dir);
+ for (String e: entries) {
+ writeFile(new File(dir, e), e);
+ }
+ return dir;
+ }
+
+ File createJar(String name, String... entries) throws IOException {
+ File jar = new File(name);
+ OutputStream out = new FileOutputStream(jar);
+ try {
+ JarOutputStream jos = new JarOutputStream(out);
+ for (String e: entries) {
+ jos.putNextEntry(new ZipEntry(e));
+ jos.write(e.getBytes());
+ }
+ jos.close();
+ } finally {
+ out.close();
+ }
+ return jar;
+ }
+
+ File findRtJar() throws Exception {
+ File java_home = new File(System.getProperty("java.home"));
+ if (java_home.getName().equals("jre"))
+ java_home = java_home.getParentFile();
+ File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar");
+ if (!rt_jar.exists())
+ throw new Exception("can't find rt.jar");
+ return rt_jar;
+ }
+
+ byte[] read(InputStream in) throws IOException {
+ byte[] data = new byte[1024];
+ int offset = 0;
+ try {
+ int n;
+ while ((n = in.read(data, offset, data.length - offset)) != -1) {
+ offset += n;
+ if (offset == data.length)
+ data = Arrays.copyOf(data, 2 * data.length);
+ }
+ } finally {
+ in.close();
+ }
+ return Arrays.copyOf(data, offset);
+ }
+
+ void writeFile(File f, String s) throws IOException {
+ f.getParentFile().mkdirs();
+ FileWriter out = new FileWriter(f);
+ try {
+ out.write(s);
+ } finally {
+ out.close();
+ }
+ }
+
+ void error(String msg) {
+ System.err.println(msg);
+ errors++;
+ }
+
+ int errors;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/6733837/T6733837.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6733837
+ * @summary Compiler API ignores locale settings
+ * @author Maurizio Cimadamore
+ * @library ../lib
+ */
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import static javax.tools.JavaFileObject.Kind;
+import com.sun.source.util.JavacTask;
+
+public class T6733837 extends ToolTester {
+
+ public static void main(String... args) {
+ new T6733837().exec();
+ }
+
+ public void exec() {
+ JavaFileObject sfo = new SimpleJavaFileObject(URI.create("myfo:/Test.java"),Kind.SOURCE) {
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return "\tclass ErroneousWithTab";
+ }
+ };
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+ List<? extends JavaFileObject> files = Arrays.asList(sfo);
+ task = tool.getTask(sw, fm, null, null, null, files);
+ try {
+ ((JavacTask)task).analyze();
+ }
+ catch (Throwable t) {
+ throw new Error("Compiler threw an exception");
+ }
+ System.err.println(sw.toString());
+ if (!sw.toString().contains("/Test.java"))
+ throw new Error("Bad source name in diagnostic");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/T6483788.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6483788
+ * @summary DefaultFileManager.ZipFileObject.toUri() fails to escape space characters
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.Collections;
+import java.util.jar.*;
+import java.util.zip.*;
+import javax.tools.*;
+
+public class T6483788 {
+ public static void main(String[] args) throws Exception {
+ new T6483788().run();
+ }
+
+ void run() throws Exception {
+ File jar = createJar();
+ JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
+ fm.setLocation(StandardLocation.CLASS_PATH, Collections.singleton(jar));
+ JavaFileObject fo = fm.getJavaFileForInput(StandardLocation.CLASS_PATH, "dummy", JavaFileObject.Kind.CLASS);
+ System.err.println("file: " + fo);
+ URI uri = fo.toUri();
+ System.err.println("uri: " + uri);
+ if (uri.toString().contains(" "))
+ throw new Exception("unexpected space character found");
+ }
+
+ File createJar() throws IOException {
+ byte[] dummy_data = new byte[10];
+ File f = new File("a b.jar");
+ OutputStream out = new FileOutputStream(f);
+ try {
+ JarOutputStream jar = new JarOutputStream(out);
+ jar.putNextEntry(new ZipEntry("dummy.class"));
+ jar.write(dummy_data);
+ jar.close();
+ } finally {
+ out.close();
+ }
+ return f;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/T6501502.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6501502 6877206 6483788
+ * @summary JSR 199: FileObject.toUri should return file:///c:/ or file:/c:/ not file://c:/
+ */
+
+import java.io.*;
+import java.net.URI;
+import javax.tools.*;
+
+public class T6501502 {
+ public static void main(String... args) throws Exception {
+ new T6501502().run();
+ }
+
+ // The spec for java.io.File includes the following:
+ // For a given abstract pathname f it is guaranteed that
+ // new File( f.toURI()).equals( f.getAbsoluteFile())
+ // For JavaFileObject we test as follows:
+ // new File( CONVERT_TO_FILEOBJECT(f).toURI()).equals( f.getAbsoluteFile())
+ // to verify that we get reasonable URIs returned from toURI.
+ // To make this a general test, and not just a Windows test,
+ // we test a number of platform-independent paths.
+ void run() throws Exception {
+ JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+ fm = c.getStandardFileManager(null, null, null);
+ System.err.println(System.getProperties());
+ File tmpDir = new File(System.getProperty("java.io.tmpdir"));
+ File testSrcDir = new File(System.getProperty("test.src"));
+ File testClassesDir = new File(System.getProperty("test.classes"));
+ test(new File("abc.tmp"));
+ test(new File(tmpDir, "bad.file"));
+ test(new File(testSrcDir, "T6501501.java"));
+ test(new File(testClassesDir, "T6501501.class"));
+ test(new File("a b"));
+ }
+
+ void test(File f) throws Exception {
+ System.err.println("test " + f);
+ FileObject fo = fm.getJavaFileObjects(f).iterator().next();
+ URI uri = fo.toUri();
+ System.err.println("FileObject uri: " + uri);
+ if (!new File(uri).equals(f.getAbsoluteFile()))
+ throw new Exception("unexpected URI returned");
+ }
+
+ StandardJavaFileManager fm;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/T6838467.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6838467
+ * @summary JSR199 FileObjects don't obey general contract of equals.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import javax.tools.*;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+
+public class T6838467 {
+ boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A"));
+
+ enum FileKind {
+ DIR("dir"),
+ ZIP("zip"),
+ ZIPFILEINDEX("zip");
+ FileKind(String path) {
+ file = new File(path);
+ }
+ final File file;
+ };
+
+ enum CompareKind {
+ SAME {
+ File other(File f) { return f; }
+ },
+ ABSOLUTE {
+ File other(File f) { return f.getAbsoluteFile(); }
+ },
+ DIFFERENT {
+ File other(File f) { return new File("not_" + f.getPath()); }
+ },
+ CASEEQUIV {
+ File other(File f) { return new File(f.getPath().toUpperCase()); }
+ };
+ abstract File other(File f);
+ };
+
+ String[] paths = { "p/A.java", "p/B.java", "p/C.java" };
+
+ public static void main(String... args) throws Exception {
+ new T6838467().run();
+ }
+
+ void run() throws Exception {
+ // on Windows, verify file system is not case significant
+ if (System.getProperty("os.name").toLowerCase().startsWith("windows")
+ && fileSystemIsCaseSignificant) {
+ error("fileSystemIsCaseSignificant is set on Windows.");
+ }
+
+ // create a set of directories and zip files to compare
+ createTestDir(new File("dir"), paths);
+ createTestDir(new File("not_dir"), paths);
+ createTestZip(new File("zip"), paths);
+ createTestZip(new File("not_zip"), paths);
+ if (fileSystemIsCaseSignificant) {
+ createTestDir(new File("DIR"), paths);
+ createTestZip(new File("ZIP"), paths);
+ }
+
+ // test the various sorts of file objects that can be obtained from
+ // the file manager, and for various values that may or may not match.
+ for (FileKind fk: FileKind.values()) {
+ for (CompareKind ck: CompareKind.values()) {
+ test(fk, ck);
+ }
+ }
+
+ // verify that the various different types of file object were all
+ // tested
+ Set<String> expectClasses = new HashSet<String>(Arrays.asList(
+ "RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" ));
+ if (!foundClasses.equals(expectClasses)) {
+ error("expected fileobject classes not found\n"
+ + "expected: " + expectClasses + "\n"
+ + "found: " + foundClasses);
+ }
+
+ if (errors > 0)
+ throw new Exception(errors + " errors");
+ }
+
+ void test(FileKind fk, CompareKind ck) throws IOException {
+ File f1 = fk.file;
+ JavaFileManager fm1 = createFileManager(fk, f1);
+
+ File f2 = ck.other(fk.file);
+ JavaFileManager fm2 = createFileManager(fk, f2);
+
+ try {
+ // If the directories or zip files match, we expect "n" matches in
+ // the "n-squared" comparisons to come, where "n" is the number of
+ // entries in the the directories or zip files.
+ // If the directories or zip files don't themselves match,
+ // we obviously don't expect any of their contents to match either.
+ int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0);
+
+ System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2);
+ test(fm1, fm2, expect);
+
+ } finally {
+ fm1.close();
+ fm2.close();
+ }
+ }
+
+ // For a pair of file managers that may or may not have similar entries
+ // on the classpath, compare all files returned from one against all files
+ // returned from the other. For each pair of files, verify that if they
+ // are equal, the hashcode is equal as well, and finally verify that the
+ // expected number of matches was found.
+ void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException {
+ boolean foundFiles1 = false;
+ boolean foundFiles2 = false;
+ int foundEqualCount = 0;
+ Set<JavaFileObject.Kind> kinds = EnumSet.allOf(JavaFileObject.Kind.class);
+ for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
+ foundFiles1 = true;
+ foundClasses.add(fo1.getClass().getSimpleName());
+ for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) {
+ foundFiles2 = true;
+ foundClasses.add(fo1.getClass().getSimpleName());
+ System.err.println("compare " + fo1 + " " + fo2);
+ if (fo1.equals(fo2)) {
+ foundEqualCount++;
+ int hash1 = fo1.hashCode();
+ int hash2 = fo2.hashCode();
+ if (hash1 != hash2)
+ error("hashCode error: " + fo1 + " [" + hash1 + "] "
+ + fo2 + " [" + hash2 + "]");
+ }
+ }
+ }
+ if (!foundFiles1)
+ error("no files found for file manager 1");
+ if (!foundFiles2)
+ error("no files found for file manager 2");
+ // verify the expected number of matches were found
+ if (foundEqualCount != expectEqualCount)
+ error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount);
+ }
+
+ // create a file manager to test a FileKind, with a given directory
+ // or zip file placed on the classpath
+ JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException {
+ StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP);
+ fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath));
+ return fm;
+ }
+
+ JavacFileManager createFileManager(boolean useJavaUtilZip) {
+ // javac should really not be using system properties like this
+ // -- it should really be using (hidden) options -- but until then
+ // take care to leave system properties as we find them, so as not
+ // to adversely affect other tests that might follow.
+ String prev = System.getProperty("useJavaUtilZip");
+ boolean resetProperties = false;
+ try {
+ if (useJavaUtilZip) {
+ System.setProperty("useJavaUtilZip", "true");
+ resetProperties = true;
+ } else if (System.getProperty("useJavaUtilZip") != null) {
+ System.getProperties().remove("useJavaUtilZip");
+ resetProperties = true;
+ }
+
+ Context c = new Context();
+ return new JavacFileManager(c, false, null);
+ } finally {
+ if (resetProperties) {
+ if (prev == null) {
+ System.getProperties().remove("useJavaUtilZip");
+ } else {
+ System.setProperty("useJavaUtilZip", prev);
+ }
+ }
+ }
+ }
+
+ // create a directory containing a given set of paths
+ void createTestDir(File dir, String[] paths) throws IOException {
+ for (String p: paths) {
+ File file = new File(dir, p);
+ file.getParentFile().mkdirs();
+ FileWriter out = new FileWriter(file);
+ try {
+ out.write(p);
+ } finally {
+ out.close();
+ }
+ }
+ }
+
+ // create a sip file containing a given set of entries
+ void createTestZip(File zip, String[] paths) throws IOException {
+ if (zip.getParentFile() != null)
+ zip.getParentFile().mkdirs();
+ ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
+ try {
+ for (String p: paths) {
+ ZipEntry ze = new ZipEntry(p);
+ zos.putNextEntry(ze);
+ byte[] bytes = p.getBytes();
+ zos.write(bytes, 0, bytes.length);
+ zos.closeEntry();
+ }
+ } finally {
+ zos.close();
+ }
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int count;
+ int errors;
+ Set<String> foundClasses = new HashSet<String>();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/T6877206.java Tue Jun 22 18:30:16 2010 -0700
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6877206
+ * @summary JavaFileObject.toUri returns bogus URI (win)
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.*;
+import javax.tools.*;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Options;
+
+// Test URIs returned from JavacFileManager and its support classes.
+// For a variety of file objects, verify the validity of FileObject.toUri()
+// by verifying the URI exists and points to the same contents as the file
+// object itself
+
+public class T6877206 {
+ public static void main(String... args) throws Exception {
+ new T6877206().run();
+ }
+
+ Set<String> foundClasses = new TreeSet<String>();
+ Set<String> foundJars = new TreeSet<String>();
+
+ void run() throws Exception {
+ File rt_jar = findRtJar();
+
+ // names for entries to be created in directories and jar files
+ String[] entries = { "p/A.class", "p/resources/A-1.jpg" };
+
+ // test various combinations of directories and jar files, intended to
+ // cover all sources of URIs within JavacFileManager's support classes
+
+ test(createFileManager(), createDir("dir", entries), "p", entries.length);
+ test(createFileManager(), createDir("a b/dir", entries), "p", entries.length);
+
+ for (boolean useJavaUtilZip: new boolean[] { false, true }) {
+ test(createFileManager(useJavaUtilZip), createJar("jar", entries), "p", entries.length);
+ test(createFileManager(useJavaUtilZip), createJar("jar jar", entries), "p", entries.length);
+
+ for (boolean useSymbolFile: new boolean[] { false, true }) {
+ test(createFileManager(useJavaUtilZip, useSymbolFile), rt_jar, "java.lang.ref", -1);
+ }
+ }
+
+ // Verify that we hit all the impl classes we intended
+ checkCoverage("classes", foundClasses,
+ "RegularFileObject", "SymbolFileObject", "ZipFileIndexFileObject", "ZipFileObject");
+
+ // Verify that we hit the jar files we intended, specifically ct.sym as well as rt.jar
+ checkCoverage("jar files", foundJars,
+ "ct.sym", "jar", "jar jar", "rt.jar");
+ }
+
+ // use a new file manager for each test
+ void test(StandardJavaFileManager fm, File f, String pkg, int expect) throws Exception {
+ JarURLConnection c;
+ System.err.println("Test " + f);
+ try {
+ fm.setLocation(StandardLocation.CLASS_PATH, Collections.singleton(f));
+
+ int count = 0;
+ for (JavaFileObject fo: fm.list(StandardLocation.CLASS_PATH,
+ pkg, EnumSet.allOf(JavaFileObject.Kind.class), true)) {
+ System.err.println("checking " + fo);
+ // record the file object class name for coverage checks later
+ foundClasses.add(fo.getClass().getSimpleName());
+ testFileObject(fo);
+ count++;
+ }
+
+ if (expect > 0 && count != expect)
+ throw new Exception("wrong number of entries found: "
+ + count + ", expected " + expect);
+ } finally {
+ fm.close();
+ }
+ }
+
+ void testFileObject(JavaFileObject fo) throws Exception {
+ // test the validity of the result of toUri() by using URLConnection
+ // and comparing the results of reading from the connection with the
+ // result of reading from the file object directly.
+ URI uri = fo.toUri();
+ System.err.println("uri: " + uri);
+
+ URLConnection urlconn = uri.toURL().openConnection();
+ if (urlconn instanceof JarURLConnection) {
+ JarURLConnection jarconn = (JarURLConnection) urlconn;
+ File f = new File(jarconn.getJarFile().getName());
+ // record access to the jar file for coverage checks later
+ foundJars.add(f.getName());
+ }
+
+ try {
+ byte[] uriData = read(urlconn.getInputStream());
+ byte[] foData = read(fo.openInputStream());
+ if (!Arrays.equals(uriData, foData)) {
+ if (uriData.length != foData.length)
+ throw new Exception("data size differs: uri data "
+ + uriData.length + " bytes, fo data " + foData.length+ " bytes");
+ for (int i = 0; i < uriData.length; i++) {
+ if (uriData[i] != foData[i])
+ throw new Exception("unexpected data returned at offset " + i
+ + ", uri data " + uriData[i] + ", fo data " + foData[i]);
+ }
+ throw new AssertionError("cannot find difference");
+ }
+ } finally {
+ // In principle, simply closing the result of urlconn.getInputStream()
+ // should have been sufficient. But the internal JarURLConnection
+ // does not close the JarFile in an expeditious manner, thus preventing
+ // jtreg from deleting the jar file before starting the next test.
+ // Therefore we force access to the JarURLConnection to close the
+ // JarFile when necessary.
+ if (urlconn instanceof JarURLConnection) {
+ JarURLConnection jarconn = (JarURLConnection) urlconn;
+ jarconn.getJarFile().close();
+ }
+ }
+ }
+
+ void checkCoverage(String label, Set<String> found, String... expect) throws Exception {
+ Set<String> e = new TreeSet<String>(Arrays.asList(expect));
+ if (!found.equals(e)) {
+ e.removeAll(found);
+ throw new Exception("expected " + label + " not used: " + e);
+ }
+ }
+
+ JavacFileManager createFileManager() {
+ return createFileManager(false, false);
+ }
+
+ JavacFileManager createFileManager(boolean useJavaUtilZip) {
+ return createFileManager(useJavaUtilZip, false);
+ }
+
+ JavacFileManager createFileManager(boolean useJavaUtilZip, boolean useSymbolFile) {
+ // javac should really not be using system properties like this
+ // -- it should really be using (hidden) options -- but until then
+ // take care to leave system properties as we find them, so as not
+ // to adversely affect other tests that might follow.
+ String prev = System.getProperty("useJavaUtilZip");
+ boolean resetProperties = false;
+ try {
+ if (useJavaUtilZip) {
+ System.setProperty("useJavaUtilZip", "true");
+ resetProperties = true;
+ } else if (System.getProperty("useJavaUtilZip") != null) {
+ System.getProperties().remove("useJavaUtilZip");
+ resetProperties = true;
+ }
+
+ Context c = new Context();
+ if (!useSymbolFile) {
+ Options options = Options.instance(c);
+ options.put("ignore.symbol.file", "true");
+ }
+
+ return new JavacFileManager(c, false, null);
+ } finally {
+ if (resetProperties) {
+ if (prev == null) {
+ System.getProperties().remove("useJavaUtilZip");
+ } else {
+ System.setProperty("useJavaUtilZip", prev);
+ }
+ }
+ }
+ }
+
+ File createDir(String name, String... entries) throws Exception {
+ File dir = new File(name);
+ if (!dir.mkdirs())
+ throw new Exception("cannot create directories " + dir);
+ for (String e: entries) {
+ writeFile(new File(dir, e), e);
+ }
+ return dir;
+ }
+
+ File createJar(String name, String... entries) throws IOException {
+ File jar = new File(name);
+ OutputStream out = new FileOutputStream(jar);
+ try {
+ JarOutputStream jos = new JarOutputStream(out);
+ for (String e: entries) {
+ jos.putNextEntry(new ZipEntry(e));
+ jos.write(e.getBytes());
+ }
+ jos.close();
+ } finally {
+ out.close();
+ }
+ return jar;
+ }
+
+ File findRtJar() throws Exception {
+ File java_home = new File(System.getProperty("java.home"));
+ if (java_home.getName().equals("jre"))
+ java_home = java_home.getParentFile();
+ File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar");
+ if (!rt_jar.exists())
+ throw new Exception("can't find rt.jar");
+ return rt_jar;
+ }
+
+ byte[] read(InputStream in) throws IOException {
+ byte[] data = new byte[1024];
+ int offset = 0;
+ try {
+ int n;
+ while ((n = in.read(data, offset, data.length - offset)) != -1) {
+ offset += n;
+ if (offset == data.length)
+ data = Arrays.copyOf(data, 2 * data.length);
+ }
+ } finally {
+ in.close();
+ }
+ return Arrays.copyOf(data, offset);
+ }
+
+ void writeFile(File f, String s) throws IOException {
+ f.getParentFile().mkdirs();
+ FileWriter out = new FileWriter(f);
+ try {
+ out.write(s);
+ } finally {
+ out.close();
+ }
+ }
+}
--- a/src/share/classes/com/sun/tools/javac/util/BaseFileObject.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package 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/src/share/classes/com/sun/tools/javac/util/JavacFileManager.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1754 +0,0 @@
-/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-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.lang.reflect.Constructor;
-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.JCDiagnostic.SimpleDiagnosticPosition;
-
-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;
- protected String classLoaderClass;
-
- /**
- * 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;
- classLoaderClass = options.get("procloader");
- }
-
- 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);
- }
- }
-
- URL[] urls = lb.toArray(new URL[lb.size()]);
- ClassLoader thisClassLoader = getClass().getClassLoader();
-
- // Bug: 6558476
- // Ideally, ClassLoader should be Closeable, but before JDK7 it is not.
- // On older versions, try the following, to get a closeable classloader.
-
- // 1: Allow client to specify the class to use via hidden option
- if (classLoaderClass != null) {
- try {
- Class<? extends ClassLoader> loader =
- Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
- Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
- Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
- return constr.newInstance(new Object[] { urls, thisClassLoader });
- } catch (Throwable t) {
- // ignore errors loading user-provided class loader, fall through
- }
- }
-
- // 2: If URLClassLoader implements Closeable, use that.
- if (Closeable.class.isAssignableFrom(URLClassLoader.class))
- return new URLClassLoader(urls, thisClassLoader);
-
- // 3: Try using private reflection-based CloseableURLClassLoader
- try {
- return new CloseableURLClassLoader(urls, thisClassLoader);
- } catch (Throwable t) {
- // ignore errors loading workaround class loader, fall through
- }
-
- // 4: If all else fails, use plain old standard URLClassLoader
- return new URLClassLoader(urls, thisClassLoader);
- }
-
- 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();
- // allow use of binary package names, per the JavaFileManager spec
- String subdirectory = externalizeFileName(packageName.replace('/', '.'));
- 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.length() == 0)
- dPath = System.getProperty("user.dir");
- 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 entry.getName() + "(" + entry + ")";
- }
-
- 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/src/share/classes/com/sun/tools/javac/util/Old199.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package 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 supported API.
- * 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/src/share/classes/com/sun/tools/javac/util/Paths.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,568 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package 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.ZipException;
-import java.util.zip.ZipFile;
-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 com.sun.tools.javac.util.Position;
-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 supported API.
- * 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. */
- 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);
- }
-
- /**
- * Split a path into its elements. Empty path elements will be ignored.
- * @param path The path to be split
- * @return The elements of the path
- */
- private static Iterable<File> getPathEntries(String path) {
- return getPathEntries(path, null);
- }
-
- /**
- * Split a path into its elements. If emptyPathDefault is not null, all
- * empty elements in the path, including empty elements at either end of
- * the path, will be replaced with the value of emptyPathDefault.
- * @param path The path to be split
- * @param emptyPathDefault The value to substitute for empty path elements,
- * or null, to ignore empty path elements
- * @return The elements of the path
- */
- private static Iterable<File> getPathEntries(String path, File emptyPathDefault) {
- ListBuffer<File> entries = new ListBuffer<File>();
- int start = 0;
- while (start <= path.length()) {
- int sep = path.indexOf(File.pathSeparatorChar, start);
- if (sep == -1)
- sep = path.length();
- if (start < sep)
- entries.append(new File(path.substring(start, sep)));
- else if (emptyPathDefault != null)
- entries.append(emptyPathDefault);
- start = sep + 1;
- }
- return entries;
- }
-
- 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 File emptyPathDefault = null;
-
- public Path emptyPathDefault(File x) {
- emptyPathDefault = x;
- return this;
- }
-
- public Path() { super(); }
-
- public Path addDirectories(String dirs, boolean warn) {
- if (dirs != null)
- for (File dir : getPathEntries(dirs))
- addDirectory(dir, warn);
- return this;
- }
-
- public Path addDirectories(String dirs) {
- return addDirectories(dirs, warn);
- }
-
- private void addDirectory(File dir, boolean warn) {
- if (!dir.isDirectory()) {
- if (warn)
- log.warning("dir.path.element.not.found", dir);
- return;
- }
-
- File[] files = 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 (File file : getPathEntries(files, emptyPathDefault))
- addFile(file, warn);
- return this;
- }
-
- public Path addFiles(String files) {
- return addFiles(files, warn);
- }
-
- 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 (File file : getPathEntries(files)) {
- if (new File(file.getName()).equals(rt_jar))
- bootClassPathRtJar = file;
- }
- }
-
- 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(new File(".")) // 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/src/share/classes/com/sun/tools/javac/zip/ZipFileIndex.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1236 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package 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/src/share/classes/com/sun/tools/javac/zip/ZipFileIndexEntry.java Mon Jun 21 11:43:28 2010 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.zip;
-
-import java.io.File;
-import java.util.Calendar;
-
-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;
- }
-
- // based on dosToJavaTime in java.util.Zip, but avoiding the
- // use of deprecated Date constructor
- private static long dosToJavaTime(int dtime) {
- Calendar c = Calendar.getInstance();
- c.set(Calendar.YEAR, ((dtime >> 25) & 0x7f) + 1980);
- c.set(Calendar.MONTH, ((dtime >> 21) & 0x0f) - 1);
- c.set(Calendar.DATE, ((dtime >> 16) & 0x1f));
- c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
- c.set(Calendar.MINUTE, ((dtime >> 5) & 0x3f));
- c.set(Calendar.SECOND, ((dtime << 1) & 0x3e));
- c.set(Calendar.MILLISECOND, 0);
- return c.getTimeInMillis();
- }
-
- 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);
- }
-}