summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-03-23 02:36:24 +0000
committerpaltherr <paltherr@epfl.ch>2004-03-23 02:36:24 +0000
commita70044860bbd402c4191038615160fb7168572f7 (patch)
tree4644374257c1a4d50d6ffe12d433b1732407d5ab
parent71ac5a4ad27fd6d3ab4da4d551fefa6ae508ff2e (diff)
downloadscala-a70044860bbd402c4191038615160fb7168572f7.tar.gz
scala-a70044860bbd402c4191038615160fb7168572f7.tar.bz2
scala-a70044860bbd402c4191038615160fb7168572f7.zip
- Split scala.tools.util.AbstractFile into seve...
- Split scala.tools.util.AbstractFile into several files Added - scala.tools.util.DirectoryPath Added scala.tools.util.VirtualDirectory - Changed interface of scala.tools.util.AbstractFile Rewrote - scala.tools.util.ZipArchive (merged ZipArchive and JarArchive) Moved - ClassPath to scala.tools.util Changed ClassPath and PackageParser to - rely on DirectoryPath for file lookups
-rw-r--r--config/list/compiler.lst1
-rw-r--r--config/list/util.lst7
-rw-r--r--sources/scala/tools/scaladoc/HTMLGeneratorCommand.java3
-rw-r--r--sources/scala/tools/scalai/Compiler.java2
-rw-r--r--sources/scala/tools/scalai/PathClassLoader.java13
-rw-r--r--sources/scala/tools/util/AbstractFile.java747
-rw-r--r--sources/scala/tools/util/CharArrayFile.java53
-rw-r--r--sources/scala/tools/util/ClassPath.java (renamed from sources/scalac/util/ClassPath.java)57
-rw-r--r--sources/scala/tools/util/DirectoryPath.java222
-rw-r--r--sources/scala/tools/util/PlainFile.java130
-rw-r--r--sources/scala/tools/util/VirtualDirectory.java39
-rw-r--r--sources/scala/tools/util/VirtualFile.java97
-rw-r--r--sources/scala/tools/util/ZipArchive.java229
-rw-r--r--sources/scalac/CompilerCommand.java3
-rw-r--r--sources/scalac/Global.java11
-rw-r--r--sources/scalac/symtab/classfile/CLRPackageParser.java2
-rw-r--r--sources/scalac/symtab/classfile/PackageParser.java72
17 files changed, 928 insertions, 760 deletions
diff --git a/config/list/compiler.lst b/config/list/compiler.lst
index 998d153c7c..e8652d4d74 100644
--- a/config/list/compiler.lst
+++ b/config/list/compiler.lst
@@ -151,7 +151,6 @@ typechecker/RefCheckPhase.java
util/AbstractFileReader.java
util/ArrayApply.java
-util/ClassPath.java
util/Debug.java
util/EmptyPhase.java
util/FreshNameCreator.java
diff --git a/config/list/util.lst b/config/list/util.lst
index 65397167dc..fdfb555d07 100644
--- a/config/list/util.lst
+++ b/config/list/util.lst
@@ -4,9 +4,16 @@
# $Id$
AbstractFile.java
+CharArrayFile.java
+ClassPath.java
+DirectoryPath.java
EmptyIterator.java
+PlainFile.java
Position.java
SourceFile.java
SourceReader.java
+VirtualFile.java
+VirtualDirectory.java
+ZipArchive.java
##############################################################################
diff --git a/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java b/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
index 6aef1f195c..dfdc81d18c 100644
--- a/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
+++ b/sources/scala/tools/scaladoc/HTMLGeneratorCommand.java
@@ -14,9 +14,10 @@ import java.util.List;
import ch.epfl.lamp.util.HTMLPrinter;
import ch.epfl.lamp.util.HTMLRepresentation;
+import scala.tools.util.ClassPath;
+
import scalac.CompilerCommand;
import scalac.util.BooleanOptionParser;
-import scalac.util.ClassPath;
import scalac.util.OptionParser;
import scalac.util.Reporter;
import scalac.util.StringOptionParser;
diff --git a/sources/scala/tools/scalai/Compiler.java b/sources/scala/tools/scalai/Compiler.java
index 97e0c6cb29..a52e002dea 100644
--- a/sources/scala/tools/scalai/Compiler.java
+++ b/sources/scala/tools/scalai/Compiler.java
@@ -54,7 +54,7 @@ public class Compiler {
this.global = global;
this.definitions = global.definitions;
this.constants = new Constants();
- this.loader = new PathClassLoader(global.classPath);
+ this.loader = new PathClassLoader(global.classPath.getRoot());
scala.runtime.RunTime.setClassLoader(loader);
JavaMirror mirror = new JavaMirror(definitions, loader);
this.environment = new Environment(this, mirror);
diff --git a/sources/scala/tools/scalai/PathClassLoader.java b/sources/scala/tools/scalai/PathClassLoader.java
index fb975d4452..251b79661f 100644
--- a/sources/scala/tools/scalai/PathClassLoader.java
+++ b/sources/scala/tools/scalai/PathClassLoader.java
@@ -9,24 +9,23 @@
package scala.tools.scalai;
+import java.io.File;
import java.io.IOException;
import scala.tools.util.AbstractFile;
-import scalac.util.ClassPath;
-
public class PathClassLoader extends ClassLoader {
//########################################################################
// PathClassLoader state
- private final ClassPath classpath;
+ private final AbstractFile root;
//########################################################################
// PathClassLoader constructors
- public PathClassLoader(ClassPath classpath) {
- this.classpath = classpath;
+ public PathClassLoader(AbstractFile root) {
+ this.root = root;
}
//########################################################################
@@ -34,8 +33,8 @@ public class PathClassLoader extends ClassLoader {
public Class findClass(String name) throws ClassNotFoundException {
try {
- String filename = name.replace('.', '/') + ".class";
- AbstractFile file = classpath.openFile(filename);
+ String filename = name.replace('.', File.separatorChar) + ".class";
+ AbstractFile file = root.lookupPath(filename, false);
byte[] bytes = file.read();
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException exception) {
diff --git a/sources/scala/tools/util/AbstractFile.java b/sources/scala/tools/util/AbstractFile.java
index ab4705d085..723d983a4a 100644
--- a/sources/scala/tools/util/AbstractFile.java
+++ b/sources/scala/tools/util/AbstractFile.java
@@ -8,686 +8,121 @@
package scala.tools.util;
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-import java.util.jar.*;
-
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
+
+/**
+ * This class implements an abstract representation of files and
+ * directories. These files and directories may have some real counter
+ * part within the file system but that is not necessarily true. For
+ * example, there exist abstract files that represent files within a
+ * zip archive or files that exist only in memory.
+ *
+ * Every abstract file has a path (i.e. a full name) and a name
+ * (i.e. a short name) and may be backed by some real File. There are
+ * two different kinds of abstract files: regular files and
+ * directories. Regular files may be read and have a last modification
+ * time. Directories may list their content and look for subfiles with
+ * a specified name or path and of a specified kind.
+ */
public abstract class AbstractFile {
- /** separator
- */
- protected char separator = File.separatorChar;
-
- /** table of all opened jar-files
- */
- protected static Hashtable opened = new Hashtable();
-
- /** get name of the file
- */
- public abstract String getName();
-
- /** get path of the file
- */
- public abstract String getPath();
-
- /** does the file exist?
- */
- public abstract boolean exists();
+ //########################################################################
+ // Public Factories
- /** is the file a directory?
- */
- public abstract boolean isDirectory();
-
- /** date file was last modified
- */
- public abstract long lastModified();
-
- /** read content of the file into a byte[] buffer
- */
- public abstract byte[] read() throws IOException;
-
- /** list contents of a directory
- */
- public abstract String[] list() throws IOException;
-
- /** open a new file
- */
- public abstract AbstractFile open(String name);
-
- /** return an input stream for the file
- */
- public InputStream getInputStream() throws IOException {
- return new ByteArrayInputStream(read());
+ /** Returns "getFile(new File(path))". */
+ public static AbstractFile getFile(String path) {
+ return getFile(new File(path));
}
- /** Returns the path of this file. */
- public String toString() {
- return getPath();
- }
-
- /** open file 'name' in directory 'dirname'
+ /**
+ * If the specified File exists and is a regular file, returns an
+ * abstract regular file backed by it. Otherwise, returns null.
*/
- public static AbstractFile open(String dirname, String name) {
- AbstractFile res;
- if (dirname == null)
- res = new PlainFile(new File(name));
- else if (dirname.endsWith(".zip")) {
- AbstractFile dir = (AbstractFile)opened.get(dirname);
- if (dir == null) {
- dir = new ZipDir(new File(dirname));
- if (dir.isDirectory())
- opened.put(dirname, dir);
- }
- res = (name == null) ? dir : dir.open(name);
- } else if (dirname.endsWith(".jar")) {
- AbstractFile dir = (AbstractFile)opened.get(dirname);
- if (dir == null) {
- dir = new JarArchive(new File(dirname));
- if (dir.isDirectory())
- opened.put(dirname, dir);
- }
- res = (name == null) ? dir : dir.open(name);
- } else if (name == null)
- res = new PlainFile(new File(dirname));
- else
- res = new PlainFile(new File(dirname, name));
- if (!res.exists())
- res = null;
- return res;
- }
-
- /** create file given by a fully qualified name from root directory `outdir';
- * create intermediate directories if they do not exist already
- */
- public static File create(File outdir, String name,
- String suffix) throws IOException {
- int start = 0;
- int end = name.indexOf('.');
- while (end >= start) {
- outdir = new File(outdir, name.substring(start, end));
- if (!outdir.exists())
- outdir.mkdir();
- start = end + 1;
- end = name.indexOf('.', start);
- }
- return new File(outdir, name.substring(start) + suffix);
- }
-}
-
-class PlainFile extends AbstractFile {
- File f;
-
- PlainFile(File f) {
- this.f = f;
- }
-
- public String getName() {
- return f.getName();
- }
-
- public String getPath() {
- return f.getPath();
- }
-
- public boolean exists() {
- return f.exists();
- }
-
- public boolean isDirectory() {
- return f.isDirectory();
- }
-
- public long lastModified() {
- return f.lastModified();
- }
-
- public byte[] read() throws IOException {
- FileInputStream in = new FileInputStream(f);
- int rest = (int)f.length();
- byte[] buf = new byte[rest];
- do {
- int res = in.read(buf, buf.length - rest, rest);
- if (res == -1)
- throw new IOException("read error");
- rest -= res;
- } while (rest > 0);
- in.close();
- return buf;
- }
-
- public String[] list() throws IOException {
- File[] fs = f.listFiles();
- if (fs == null)
- return new String[0];
- String[] res = new String[fs.length];
- for (int i = 0; i < fs.length; i++) {
- res[i] = fs[i].getName();
- if (fs[i].isDirectory() &&
- !res[i].endsWith("/"))
- res[i] = res[i] + "/";
- }
- return res;
- }
-
- public AbstractFile open(String name) {
- return new PlainFile(new File(f, name));
- }
-}
-
-class ZippedFile extends AbstractFile {
- ZipDir dir;
- ZipEntry zipEntry;
-
- {
- separator = '/';
- }
-
- ZippedFile(ZipDir dir, String name) {
- this.dir = dir;
- if (dir.zipFile != null) {
- name = name.replace(File.separatorChar, separator);
- zipEntry = this.dir.zipFile.getEntry(name);
- if (zipEntry == null)
- zipEntry = this.dir.zipFile.getEntry(name + separator);
- }
+ public static AbstractFile getFile(File file) {
+ return file.isFile() ? new PlainFile(file) : null;
}
- public String getName() {
- return zipEntry.getName();
- }
-
- public String getPath() {
- return dir.getPath() + "(" + zipEntry.getName() + ")";
- }
-
- public boolean exists() {
- return (zipEntry != null);
- }
-
- public boolean isDirectory() {
- return zipEntry.isDirectory();
- }
-
- public long lastModified() {
- return zipEntry.getTime();
- }
-
- public byte[] read() throws IOException {
- InputStream in = dir.zipFile.getInputStream(zipEntry);
- int rest = (int)zipEntry.getSize();
- byte[] buf = new byte[rest];
- do {
- int res = in.read(buf, buf.length - rest, rest);
- if (res == -1)
- throw new IOException("read error");
- rest -= res;
- } while (rest > 0);
- in.close();
- return buf;
- }
-
- public String[] list() throws IOException {
- if (!isDirectory())
- throw new IOException("not a directory");
- return dir.list(zipEntry.getName());
- }
-
- public AbstractFile open(String name) {
- String pathname = zipEntry.getName();
- return new ZippedFile(dir, pathname + name);
- }
-}
-
-class ZipDir extends AbstractFile {
- File f;
- ZipFile zipFile;
-
- {
- separator = '/';
- }
-
- ZipDir(File f) {
- this.f = f;
- try {
- zipFile = new ZipFile(f);
- } catch (ZipException e) {
- } catch (IOException e) {}
- }
-
- public String getName() {
- return f.getName();
- }
-
- public String getPath() {
- return f.getPath();
- }
-
- public boolean exists() {
- return (zipFile != null);
- }
-
- public boolean isDirectory() {
- return (zipFile != null);
- }
-
- public long lastModified() {
- return -1;
- }
- public byte[] read() throws IOException {
- throw new IOException("cannot read directory");
- }
-
- public String[] list(String prefix) {
- int n = 0;
- for (Enumeration enum = zipFile.entries(); enum.hasMoreElements();) {
- ZipEntry e = (ZipEntry)enum.nextElement();
- if (e.getName().startsWith(prefix)) {
- String candidate = e.getName().substring(prefix.length());
- if (candidate.indexOf(separator) < 0)
- n++;
- }
- }
- String[] filenames = new String[n];
- n = 0;
- for (Enumeration enum = zipFile.entries(); enum.hasMoreElements();) {
- ZipEntry e = (ZipEntry)enum.nextElement();
- if (e.getName().startsWith(prefix)) {
- String candidate = e.getName().substring(prefix.length());
- if (candidate.indexOf(separator) < 0)
- filenames[n++] = candidate;
- }
- }
- return filenames;
- }
-
- public String[] list() throws IOException {
- return list("");
- }
-
- public AbstractFile open(String name) {
- return new ZippedFile(this, name);
- }
-}
-
-final class JarArchive extends AbstractFile {
- File f;
- JarFile jarFile;
- HashMap entries;
-
- public final static String[] EMPTY = new String[0];
-
-
- JarArchive(File f) {
- try {
- jarFile = new JarFile(this.f = f);
- }
- catch (ZipException e) {}
- catch (IOException e) {}
- }
-
- public String getName() {
- return f.getName();
- }
-
- public String getPath() {
- return f.getPath();
- }
-
- public boolean exists() {
- return jarFile != null;
- }
-
- public boolean isDirectory() {
- return jarFile != null;
- }
-
- public long lastModified() {
- return -1;
- }
-
- public byte[] read() throws IOException {
- throw new IOException("cannot read archive");
- }
-
- private void load() {
- entries = new HashMap();
- if (jarFile == null)
- return;
- Enumeration enum = jarFile.entries();
- while (enum.hasMoreElements()) {
- String candidate = ((JarEntry)enum.nextElement()).getName();
- int i = candidate.indexOf('/');
- int j = 0;
- HashMap files = entries;
- while (i >= 0) {
- String dirname = candidate.substring(j, j = (i + 1));
- JarDirEntry dir = (JarDirEntry)files.get(dirname);
- if (dir == null)
- files.put(dirname, dir = new JarDirEntry(
- candidate.substring(0, j)));
- files = dir.entries;
- i = candidate.indexOf('/', j);
- }
- if (j < (candidate.length() - 1)) {
- String filename = candidate.substring(j);
- JarFileEntry file = (JarFileEntry)files.get(filename);
- if (file == null)
- files.put(filename, new JarFileEntry(candidate));
- }
- }
+ /** Returns "getDirectory(new File(path))". */
+ public static AbstractFile getDirectory(String path) {
+ return getDirectory(new File(path));
}
- public String[] list(String prefix) {
- prefix = prefix.replace(File.separatorChar, '/');
- if (entries == null)
- load();
- int i = prefix.indexOf('/');
- int j = 0;
- HashMap files = entries;
- while (i >= 0) {
- String dirname = prefix.substring(j, j = (i + 1));
- JarDirEntry dir = (JarDirEntry)files.get(dirname);
- if (dir == null)
- return EMPTY;
- files = dir.entries;
- i = prefix.indexOf('/', j);
- }
- if (j < (prefix.length() - 1)) {
- String filename = prefix.substring(j);
- return (files.get(filename) != null) ? new String[]{prefix}
- : EMPTY;
- } else
- return (String[])files.keySet().toArray(new String[files.size()]);
- }
-
- public String[] list() throws IOException {
- return list("");
- }
-
- public AbstractFile open(String name) {
- if (entries == null)
- load();
- name = name.replace(File.separatorChar, '/');
- int i = name.indexOf('/');
- int j = 0;
- int namelen = name.length();
- HashMap files = entries;
- while (i >= 0) {
- String dirname = name.substring(j, j = (i + 1));
- if (files != null) {
- JarDirEntry dir = (JarDirEntry)files.get(dirname);
- if (dir == null)
- files = null;
- else if (j == namelen)
- return dir;
- else
- files = dir.entries;
- }
- i = name.indexOf('/', j);
- }
- if (j < (namelen - 1)) {
- String filename = name.substring(j);
- if (files == null)
- return new NoJarFileEntry(name);
- JarFileEntry file = (JarFileEntry)files.get(filename);
- if (file == null)
- return new NoJarFileEntry(name);
- else
- return file;
- } else
- return new NoJarDirEntry(name);
- }
-
- static class NoJarDirEntry extends AbstractFile {
- String name;
-
- NoJarDirEntry(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name.substring(
- name.lastIndexOf('/', name.length() - 2) + 1);
- }
-
- public String getPath() {
- return name;
- }
-
- public String getFullName() {
- return name;
- }
-
- public boolean exists() {
- return false;
- }
-
- public boolean isDirectory() {
- return true;
- }
-
- public long lastModified() {
- return -1;
- }
-
- public String[] list() throws IOException {
- throw new IOException("not a directory");
- }
-
- public byte[] read() throws IOException {
- throw new IOException("cannot read archive");
- }
-
- public AbstractFile open(String fname) {
- throw new Error("cannot open archive entry");
- }
- }
-
- final class JarDirEntry extends NoJarDirEntry {
- HashMap entries;
-
- JarDirEntry(String name) {
- super(name);
- this.entries = new HashMap();
- }
-
- public String getPath() {
- return JarArchive.this.getPath() + "(" + name + ")";
- }
-
- public boolean exists() {
- return true;
- }
-
- public String[] list() throws IOException {
- return JarArchive.this.list(name);
- }
-
- public AbstractFile open(String fname) {
- fname = fname.replace(File.separatorChar, '/');
- return JarArchive.this.open(name + fname);
- }
- }
-
- static class NoJarFileEntry extends AbstractFile {
- String name;
-
- NoJarFileEntry(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name.substring(
- name.lastIndexOf('/', name.length() - 1) + 1);
- }
-
- public String getFullName() {
- return name;
- }
-
- public String getPath() {
- return name;
- }
-
- public boolean exists() {
- return false;
- }
-
- public boolean isDirectory() {
- return false;
- }
-
- public long lastModified() {
- return -1;
- }
-
- public String[] list() throws IOException {
- throw new IOException("not a directory");
- }
-
- public byte[] read() throws IOException {
- throw new IOException("cannot read archive");
- }
-
- public AbstractFile open(String fname) {
- throw new Error("not a directory");
- }
- }
-
- final class JarFileEntry extends NoJarFileEntry {
-
- JarFileEntry(String name) {
- super(name);
- }
-
- public String getPath() {
- return JarArchive.this.getPath() + "(" + name + ")";
- }
-
- public boolean exists() {
- return true;
- }
-
- public long lastModified() {
- return jarFile.getJarEntry(name).getTime();
- }
-
- public byte[] read() throws IOException {
- JarEntry jarEntry = jarFile.getJarEntry(name);
- if (jarEntry == null)
- throw new IOException("unable to read " + name);
- InputStream in = jarFile.getInputStream(jarEntry);
- int rest = (int)jarEntry.getSize();
- byte[] buf = new byte[rest];
- do {
- int res = in.read(buf, buf.length - rest, rest);
- if (res == -1)
- throw new IOException("read error");
- rest -= res;
- } while (rest > 0);
- in.close();
- return buf;
+ /**
+ * if the specified File exists and is either a directory or a
+ * readable zip or jar archive, returns an abstract directory
+ * backed by it. Otherwise, returns null.
+ */
+ public static AbstractFile getDirectory(File file) {
+ if (file.isDirectory()) return new PlainFile(file);
+ if (file.isFile()) {
+ String path = file.getPath();
+ if (path.endsWith(".jar") || path.endsWith(".zip"))
+ return ZipArchive.fromFile(file);
}
- }
-}
-
-
-public class VirtualFile extends AbstractFile {
-
- /** The file name */
- private final String name;
-
- /** The file path */
- private final String path;
-
- public VirtualFile(String name) {
- this(name, name);
- }
-
- public VirtualFile(String name, String path) {
- this.name = name;
- this.path = path;
- }
-
- public String getName() {
- return name;
- }
-
- public String getPath() {
- return path;
- }
-
- public boolean exists() {
- return false;
- }
-
- public boolean isDirectory() {
- return false;
- }
-
- public long lastModified() {
- return Long.MIN_VALUE;
- }
-
- public byte[] read() {
- return new byte[0];
- }
-
- public String[] list() {
- return new String[0];
- }
-
- public AbstractFile open(String name) {
return null;
}
-}
-
-public class ByteArrayFile extends VirtualFile {
-
- private final byte[] bytes;
-
- public ByteArrayFile(String name, byte[] bytes) {
- this(name, name, bytes);
- }
-
- public ByteArrayFile(String name, String path, byte[] bytes) {
- super(name, path);
- this.bytes = bytes;
- }
-
- public boolean exists() {
- return true;
- }
+ //########################################################################
+ // Public Methods
- public byte[] read() {
- return bytes;
- }
+ /** Returns the name of this abstract file. */
+ public abstract String getName();
-}
+ /** Returns the path of this abstract file. */
+ public abstract String getPath();
+ /** Returns the underlying File if any and null otherwise. */
+ public abstract File getFile();
-public class CharArrayFile extends VirtualFile {
+ /** Is this abstract file a directory? */
+ public abstract boolean isDirectory();
- private final char[] chars;
+ /** Returns the time that this abstract file was last modified. */
+ public abstract long lastModified();
- public CharArrayFile(String name, char[] chars) {
- this(name, name, chars);
- }
+ /** Reads the content of this abstract file into a byte array. */
+ public abstract byte[] read() throws IOException;
- public CharArrayFile(String name, String path, char[] chars) {
- super(name, path);
- this.chars = chars;
- }
+ /** Returns all abstract subfiles of this abstract directory. */
+ public abstract Iterator/*<AbstractFile>*/ list();
- public boolean exists() {
- return true;
- }
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ public abstract AbstractFile lookupName(String name, boolean directory);
- public byte[] read() {
- return new String(chars).getBytes(); // !!!
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified path relative to it, If there is no such file,
+ * returns null. The argument "directory" tells whether to look
+ * for a directory or or a regular file.
+ */
+ public final AbstractFile lookupPath(String path, boolean directory) {
+ final int length = path.length();
+ final char separator = File.separatorChar;
+ assert 0 < length && path.lastIndexOf(separator) < length - 1: path;
+ AbstractFile file = this;
+ for (int start = 0, index; true; start = index + 1) {
+ index = path.indexOf(separator, start);
+ assert index < 0 || start < index: path+" - "+start+" - "+index;
+ String name = path.substring(start, index < 0 ? length : index);
+ file = file.lookupName(name, index < 0 ? directory : true);
+ if (file == null || index < 0) return file;
+ }
+ }
+
+ /** Returns the path of this abstract file. */
+ public final String toString() {
+ return getPath();
}
+ //########################################################################
}
diff --git a/sources/scala/tools/util/CharArrayFile.java b/sources/scala/tools/util/CharArrayFile.java
new file mode 100644
index 0000000000..55c8f4a19d
--- /dev/null
+++ b/sources/scala/tools/util/CharArrayFile.java
@@ -0,0 +1,53 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+/**
+ * This class implements an abstract regular file backed by a
+ * character array.
+ */
+public class CharArrayFile extends VirtualFile {
+
+ //########################################################################
+ // Private Fields
+
+ /** The character array */
+ private final char[] chars;
+
+ //########################################################################
+ // Public Constructors
+
+ /**
+ * Initializes this instance with the specified name, an identical
+ * path and the specified character array.
+ */
+ public CharArrayFile(String name, char[] chars) {
+ this(name, name, chars);
+ }
+
+ /**
+ * Initializes this instance with the specified name, path and
+ * character array.
+ */
+ public CharArrayFile(String name, String path, char[] chars) {
+ super(name, path);
+ this.chars = chars;
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Reads the content of this abstract file into a byte array. */
+ public byte[] read() {
+ assert false: "!!! not yet implemented";
+ return new String(chars).getBytes(); // !!!
+ }
+
+ //########################################################################
+}
diff --git a/sources/scalac/util/ClassPath.java b/sources/scala/tools/util/ClassPath.java
index 036af2240e..fee5ca435c 100644
--- a/sources/scalac/util/ClassPath.java
+++ b/sources/scala/tools/util/ClassPath.java
@@ -6,18 +6,14 @@
// $Id$
-package scalac.util;
+package scala.tools.util;
import java.io.File;
-import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
-import scala.tools.util.AbstractFile;
-
-
/** This class represents a Java/Scala class path. */
public class ClassPath {
@@ -100,14 +96,11 @@ public class ClassPath {
return scala == null ? java : java + PATH_SEPARATOR + scala;
}
- /** the various class path roots
- */
- protected String[] root;
-
- /** print searches in the class path
- */
- public boolean printSearch;
+ //########################################################################
+ // Private Fields
+ /** The abstract directory represented by this class path */
+ private final AbstractFile root;
//########################################################################
// Public Constructors
@@ -125,7 +118,6 @@ public class ClassPath {
this(classpath, SOURCEPATH, BOOTCLASSPATH, EXTDIRS);
}
-
/** Initializes this instance with the specified paths. */
public ClassPath(String classpath, String sourcepath, String bootclasspath,
String extdirs)
@@ -146,47 +138,24 @@ public class ClassPath {
addFilesInPath(files, sourcepath);
ArrayList dirs = new ArrayList(files.size());
for (Iterator i = files.iterator(); i.hasNext(); ) {
- File file = (File)i.next();
- if (file.exists()) dirs.add(file.getPath());
+ AbstractFile dir = AbstractFile.getDirectory((File)i.next());
+ if (dir != null) dirs.add(dir);
}
- this.root = (String[])dirs.toArray(new String[dirs.size()]);
+ Object[] array = dirs.toArray(new AbstractFile[dirs.size()]);
+ this.root = DirectoryPath.fromArray("<root>", (AbstractFile[])array);
}
//########################################################################
// Public Methods
- /** find file with given name in class path and return an abstract
- * file representation
- */
- public AbstractFile openFile(String name) throws FileNotFoundException {
- if (printSearch)
- System.out.println("looking for " + name);
- for (int i = 0; i < root.length; i++) {
- if (printSearch)
- System.out.println(" in " + root[i]);
- AbstractFile f = AbstractFile.open(root[i], name);
- if (f != null)
- return f;
- }
- throw new FileNotFoundException("file '" + name +
- "' not found in classpath");
- }
-
- public String[] components() {
+ /** Returns the root of this class path. */
+ public AbstractFile getRoot() {
return root;
}
- /** return a textual representation of this class path
- */
+ /** Returns a string representation of this class path. */
public String toString() {
- if (root.length == 0)
- return "";
- else if (root.length == 1)
- return root[0];
- String path = root[0];
- for (int i = 1; i < root.length; i++)
- path += PATH_SEPARATOR + root[i];
- return path;
+ return root.toString();
}
//########################################################################
diff --git a/sources/scala/tools/util/DirectoryPath.java b/sources/scala/tools/util/DirectoryPath.java
new file mode 100644
index 0000000000..2b114f8efe
--- /dev/null
+++ b/sources/scala/tools/util/DirectoryPath.java
@@ -0,0 +1,222 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+
+/**
+ * This class implements an abstract directory backed by a list of
+ * abstract directories. The content of the directories are merged
+ * together. If a subfile occurs in several directories, then the
+ * first occurrence hides the next ones. If a subdirectory occurs in
+ * several directories then the content of the different occurrences
+ * are merged together in the same way.
+ */
+public class DirectoryPath extends VirtualDirectory {
+
+ //########################################################################
+ // Public Factories
+
+ /**
+ * Returns an abstract directory with the specified name and
+ * backed by the specified array of abstract directories.
+ */
+ public static AbstractFile fromArray(String name, AbstractFile[] dirs) {
+ if (dirs.length == 0) return new VirtualDirectory(name, "");
+ if (dirs.length == 1 && dirs[0].getName().equals(name)) return dirs[1];
+ return new DirectoryPath(name, dirs);
+ }
+
+ //########################################################################
+ // Private Fields
+
+ /** The directories composing this directory path */
+ private final AbstractFile[] dirs;
+
+ //########################################################################
+ // Protected Constructor
+
+ /** Initializes this instance with given name and directories. */
+ protected DirectoryPath(String name, AbstractFile[] dirs) {
+ super(name);
+ this.dirs = dirs;
+ for (int i = 0; i < dirs.length; i++)
+ assert dirs[i].isDirectory(): dirs[i];
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns the path of this abstract file. */
+ public String getPath() {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < dirs.length; i++) {
+ if (i > 0) buffer.append(File.pathSeparator);
+ buffer.append(dirs[i]);
+ }
+ return buffer.toString();
+ }
+
+ /** Returns all abstract subfiles of this abstract directory. */
+ public Iterator/*<AbstractFile>*/ list() {
+ return new ListIterator();
+ }
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ public AbstractFile lookupName(String name, boolean directory) {
+ if (directory) {
+ AbstractFile first = null;
+ AbstractFile[] subdirs = null;
+ int count = 0;
+ for (int i = 0; i < dirs.length; i++) {
+ AbstractFile subdir = dirs[i].lookupName(name, directory);
+ if (subdir == null) continue;
+ if (count == 0) {
+ first = subdir;
+ count++;
+ } else {
+ if (count == 1) {
+ subdirs = new AbstractFile[dirs.length];
+ subdirs[0] = first;
+ }
+ subdirs[count++] = subdir;
+ }
+ }
+ if (count == 0) return null;
+ if (count == 1) return first;
+ if (count != subdirs.length) {
+ AbstractFile[] array = new AbstractFile[count];
+ for (int i = 0; i < array.length; i++) array[i] = subdirs[i];
+ subdirs = array;
+ }
+ return new DirectoryPath(name, subdirs);
+ } else {
+ for (int i = 0; i < dirs.length; i++) {
+ AbstractFile file = dirs[i].lookupName(name, directory);
+ if (file != null) return file;
+ }
+ return null;
+ }
+ }
+
+ //########################################################################
+ // Private Class - ListIterator
+
+ /** An iterator over the files contained in this directory. */
+ private class ListIterator implements Iterator {
+
+ /** The type of the values in the subdirectory table */
+ // type SubDirs = AbstractFile | ArrayList<AbstractFile>
+
+ /** A table to collect subdirectories */
+ private final HashMap/*<String,SubDirs>*/ subdirs = new HashMap();
+
+ /** A table to track already returned regular subfiles */
+ private final HashSet/*<String>*/ subfiles = new HashSet();
+
+ /** The current iterator */
+ private Iterator iterator;
+
+ /** The index of the current directory */
+ private int index;
+
+ /** The next iteration value or null if no more */
+ private Object next;
+
+ /** Initializes this instance. */
+ public ListIterator() {
+ this.next = getNextValue();
+ }
+
+ /** Does this iteration have more elements? */
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ /** Returns the next element in this iteration. */
+ public Object next() {
+ if (next == null) throw new NoSuchElementException();
+ Object value = next;
+ next = getNextValue();
+ return value;
+ }
+
+ /** Throws UnsupportedOperationException. */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** Returns the next iteration value or null if no more. */
+ private AbstractFile getNextValue() {
+ for (; index < dirs.length; iterator = null, index++) {
+ // iterate over the files of directory "index"
+ if (iterator == null) iterator = dirs[index].list();
+ while (iterator.hasNext()) {
+ AbstractFile subfile = (AbstractFile)iterator.next();
+ String name = subfile.getName();
+ if (subfile.isDirectory()) {
+ addSubDir(name, subfile);
+ } else if (!subfiles.contains(name)) {
+ subfiles.add(name);
+ return subfile;
+ }
+ }
+ }
+ // iterate over the collected subdirectories
+ if (iterator == null) iterator = subdirs.entrySet().iterator();
+ if (iterator.hasNext()) return getSubDir((Entry)iterator.next());
+ return null;
+ }
+
+ /** Adds given subdirectory to the subdirectory table. */
+ private void addSubDir(String name, AbstractFile subdir) {
+ Object value = subdirs.get(name);
+ if (value == null) {
+ subdirs.put(name, subdir);
+ } else {
+ ArrayList list;
+ if (value instanceof ArrayList) {
+ list = (ArrayList)value;
+ } else {
+ list = new ArrayList();
+ subdirs.put(name, list);
+ list.add(value);
+ }
+ list.add(subdir);
+ }
+ }
+
+ /** Turns given entry into an abstract directory. */
+ private AbstractFile getSubDir(Entry/*<String,SubDirs>*/ entry) {
+ Object value = entry.getValue();
+ if (value instanceof ArrayList) {
+ ArrayList list = (ArrayList)value;
+ AbstractFile[] array = new AbstractFile[list.size()];
+ list.toArray(array);
+ return new DirectoryPath((String)entry.getKey(), array);
+ } else {
+ return (AbstractFile)value;
+ }
+ }
+
+ }
+
+ //########################################################################
+}
diff --git a/sources/scala/tools/util/PlainFile.java b/sources/scala/tools/util/PlainFile.java
new file mode 100644
index 0000000000..6684774038
--- /dev/null
+++ b/sources/scala/tools/util/PlainFile.java
@@ -0,0 +1,130 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/** This class implements an abstract file backed by a File. */
+public class PlainFile extends AbstractFile {
+
+ //########################################################################
+ // Public Factories
+
+ /** Returns "fromFile(new File(path))". */
+ public static AbstractFile fromPath(String path) {
+ return fromFile(new File(path));
+ }
+
+ /**
+ * If the specified File exists, returns an abstract file backed
+ * by it. Otherwise, returns null.
+ */
+ public static AbstractFile fromFile(File file) {
+ return file.exists() ? new PlainFile(file) : null;
+ }
+
+ //########################################################################
+ // Private Fields
+
+ /** The underlying File */
+ private final File file;
+
+ //########################################################################
+ // Protected Constructors
+
+ /** Initializes this instance with the specified File. */
+ protected PlainFile(File file) {
+ this.file = file;
+ assert file != null;
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns the name of this abstract file. */
+ public String getName() {
+ return file.getName();
+ }
+
+ /** Returns the path of this abstract file. */
+ public String getPath() {
+ return file.getPath();
+ }
+
+ /** Returns the underlying File if any and null otherwise. */
+ public File getFile() {
+ return file;
+ }
+
+ /** Is this abstract file a directory? */
+ public boolean isDirectory() {
+ return file.isDirectory();
+ }
+
+ /** Returns the time that this abstract file was last modified. */
+ public long lastModified() {
+ return file.lastModified();
+ }
+
+ /** Reads the content of this abstract file into a byte array. */
+ public byte[] read() throws IOException {
+ assert !isDirectory(): "cannot read directory '" + this + "'";
+ FileInputStream in = new FileInputStream(file);
+ int rest = (int)file.length();
+ byte[] buf = new byte[rest];
+ do {
+ int res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest -= res;
+ } while (rest > 0);
+ in.close();
+ return buf;
+ }
+
+ /** Returns all abstract subfiles of this abstract directory. */
+ public Iterator/*<AbstractFile>*/ list() {
+ assert isDirectory(): "not a directory '" + this + "'";
+ final String[] names = file.list();
+ if (names == null || names.length == 0) return EmptyIterator.object;
+ class ListIterator implements Iterator {
+ private int i;
+ public boolean hasNext() {
+ return i < names.length;
+ }
+ public Object next() {
+ if (i == names.length) throw new NoSuchElementException();
+ return new PlainFile(new File(file, names[i++]));
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ return new ListIterator();
+ }
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ public AbstractFile lookupName(String name, boolean directory) {
+ assert isDirectory(): "not a directory '" + this + "'";
+ File child = new File(file, name);
+ if (directory ? !child.isDirectory() : !child.isFile()) return null;
+ return new PlainFile(child);
+ }
+
+ //########################################################################
+}
diff --git a/sources/scala/tools/util/VirtualDirectory.java b/sources/scala/tools/util/VirtualDirectory.java
new file mode 100644
index 0000000000..597f52d14b
--- /dev/null
+++ b/sources/scala/tools/util/VirtualDirectory.java
@@ -0,0 +1,39 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+/** This class implements an empty abstract directory. */
+public class VirtualDirectory extends VirtualFile {
+
+ //########################################################################
+ // Public Constructors
+
+ /**
+ * Initializes this instance with the specified name and an
+ * identical path.
+ */
+ public VirtualDirectory(String name) {
+ this(name, name);
+ }
+
+ /** Initializes this instance with the specified name and path. */
+ public VirtualDirectory(String name, String path) {
+ super(name, path);
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Is this abstract file a directory? */
+ public boolean isDirectory() {
+ return true;
+ }
+
+ //########################################################################
+}
diff --git a/sources/scala/tools/util/VirtualFile.java b/sources/scala/tools/util/VirtualFile.java
new file mode 100644
index 0000000000..b0e6e2a897
--- /dev/null
+++ b/sources/scala/tools/util/VirtualFile.java
@@ -0,0 +1,97 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+/** This class implements an empty abstract regular file. */
+public class VirtualFile extends AbstractFile {
+
+ //########################################################################
+ // Private Fields
+
+ /** The file name */
+ private final String name;
+
+ /** The file path */
+ private final String path;
+
+ //########################################################################
+ // Public Constructors
+
+ /**
+ * Initializes this instance with the specified name and an
+ * identical path.
+ */
+ public VirtualFile(String name) {
+ this(name, name);
+ }
+
+ /** Initializes this instance with the specified name and path. */
+ public VirtualFile(String name, String path) {
+ this.name = name;
+ this.path = path;
+ assert name != null && path != null: name + " - " + path;
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns the name of this abstract file. */
+ public String getName() {
+ return name;
+ }
+
+ /** Returns the path of this abstract file. */
+ public String getPath() {
+ return path;
+ }
+
+ /** Returns null. */
+ public final File getFile() {
+ return null;
+ }
+
+ /** Is this abstract file a directory? */
+ public boolean isDirectory() {
+ return false;
+ }
+
+ /** Returns the time that this abstract file was last modified. */
+ public long lastModified() {
+ return Long.MIN_VALUE;
+ }
+
+ /** Reads the content of this abstract file into a byte array. */
+ public byte[] read() throws IOException {
+ assert !isDirectory(): "cannot read directory '" + this + "'";
+ return new byte[0];
+ }
+
+ /** Returns all abstract subfiles of this abstract directory. */
+ public Iterator/*<AbstractFile>*/ list() {
+ assert isDirectory(): "not a directory '" + this + "'";
+ return EmptyIterator.object;
+ }
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ public AbstractFile lookupName(String name, boolean directory) {
+ assert isDirectory(): "not a directory '" + this + "'";
+ return null;
+ }
+
+ //########################################################################
+}
diff --git a/sources/scala/tools/util/ZipArchive.java b/sources/scala/tools/util/ZipArchive.java
new file mode 100644
index 0000000000..c0525a0bcd
--- /dev/null
+++ b/sources/scala/tools/util/ZipArchive.java
@@ -0,0 +1,229 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scala.tools.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * This class implements an abstract directory backed by a zip
+ * archive.
+ */
+public final class ZipArchive extends PlainFile {
+
+ //########################################################################
+ // Public Factories
+
+ /** Returns "fromFile(new File(path))". */
+ public static AbstractFile fromPath(String path) {
+ return fromFile(new File(path));
+ }
+
+ /**
+ * If the specified File exists and is a readable zip archive,
+ * returns an abstract file backed by it. Otherwise, returns null.
+ */
+ public static AbstractFile fromFile(File file) {
+ try {
+ return new ZipArchive(file, new ZipFile(file));
+ } catch (IOException exception) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an abstract directory backed by the specified archive.
+ */
+ public static AbstractFile fromArchive(ZipFile archive) {
+ return new ZipArchive(new File(archive.getName()), archive);
+ }
+
+ //########################################################################
+ // Private Fields
+
+ /** The zip archive */
+ private final ZipFile archive;
+
+ /** The root directory or null if not yet initialized */
+ private DirEntry root;
+
+ //########################################################################
+ // Protected Constructors
+
+ /**
+ * Initializes this instance with the specified File and ZipFile.
+ */
+ protected ZipArchive(File file, ZipFile archive) {
+ super(file);
+ this.archive = archive;
+ assert archive != null;
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns true. */
+ public boolean isDirectory() {
+ return true;
+ }
+
+ /** Returns all abstract subfiles of this abstract directory. */
+ public Iterator/*<AbstractFile>*/ list() {
+ if (root == null) load();
+ return root.list();
+ }
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ public AbstractFile lookupName(String name, boolean directory) {
+ if (root == null) load();
+ return root.lookupName(name, directory);
+ }
+
+ //########################################################################
+ // Private Methods
+
+ /** Loads the archive and creates the root directory. */
+ private void load() {
+ this.root = new DirEntry("<root>", "/");
+ // A path to DirEntry map
+ HashMap/*<String,DirEntry>*/ dirs = new HashMap();
+ dirs.put("/", root);
+ for (Enumeration e = archive.entries(); e.hasMoreElements(); ) {
+ ZipEntry entry = (ZipEntry)e.nextElement();
+ String path = entry.getName();
+ assert entry.isDirectory() == path.endsWith("/"): this +"-"+ path;
+ if (entry.isDirectory()) {
+ DirEntry dir = getDir(dirs, path);
+ assert dir.entry == null: this + " - " + path;
+ dir.entry = entry;
+ } else {
+ int index = path.lastIndexOf('/');
+ String name = index < 0 ? path : path.substring(index + 1);
+ String home = index < 0 ? "/" : path.substring(0, index + 1);
+ DirEntry parent = getDir(dirs, home);
+ assert !parent.entries.containsKey(path): this + " - " + path;
+ parent.entries.put(path, new FileEntry(name, path, entry));
+ }
+ }
+ }
+
+ /**
+ * Lookups the specified table for a DirEntry with the specified
+ * path. If successful, returns the found DirEntry. Otherwise
+ * creates a new DirEntry, enters it into the table and in the
+ * table of its parent ZipDir and returns it.
+ */
+ private DirEntry getDir(HashMap/*<String,DirEntry>*/ dirs, String path) {
+ DirEntry dir = (DirEntry)dirs.get(path);
+ if (dir == null) {
+ int index = path.lastIndexOf('/', path.length() - 2);
+ String name = index < 0 ? path : path.substring(index + 1);
+ String home = index < 0 ? "/" : path.substring(0, index + 1);
+ DirEntry parent = getDir(dirs, home);
+ dir = new DirEntry(name.substring(0, name.length() - 1), path);
+ parent.entries.put(name, dir);
+ dirs.put(path, dir);
+ }
+ return dir;
+ }
+
+ //########################################################################
+ // Private Class - Entry
+
+ /** Superclass of archive entries */
+ private abstract class Entry extends VirtualFile {
+
+ public Entry(String name, String path) {
+ super(name, path);
+ }
+
+ public final String getPath() {
+ return ZipArchive.this + "(" + super.getPath() + ")";
+ }
+
+ }
+
+ //########################################################################
+ // Private Class - DirEntry
+
+ /** A directory archive entry */
+ private final class DirEntry extends Entry {
+
+ public final HashMap/*<String,Entry>*/ entries;
+ public ZipEntry entry;
+
+ public DirEntry(String name, String path) {
+ super(name, path);
+ this.entries = new HashMap();
+ }
+
+ public boolean isDirectory() {
+ return true;
+ }
+
+ public long lastModified() {
+ return entry != null ? entry.getTime() : super.lastModified();
+ }
+
+ public Iterator/*<AbstractFile>*/ list() {
+ return entries.values().iterator();
+ }
+
+ public AbstractFile lookupName(String name, boolean directory) {
+ return (AbstractFile)entries.get(directory ? name + "/" : name);
+ }
+
+ }
+
+ //########################################################################
+ // Private Class - FileEntry
+
+ /** A regular file archive entry */
+ private final class FileEntry extends Entry {
+
+ public final ZipEntry entry;
+
+ public FileEntry(String name, String path, ZipEntry entry) {
+ super(name, path);
+ this.entry = entry;
+ }
+
+ public long lastModified() {
+ return entry.getTime();
+ }
+
+ public byte[] read() throws IOException {
+ InputStream in = archive.getInputStream(entry);
+ int rest = (int)entry.getSize();
+ byte[] buf = new byte[rest];
+ do {
+ int res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest -= res;
+ } while (rest > 0);
+ in.close();
+ return buf;
+ }
+
+ }
+
+ //########################################################################
+}
diff --git a/sources/scalac/CompilerCommand.java b/sources/scalac/CompilerCommand.java
index 80e60e4245..f1d4fa8605 100644
--- a/sources/scalac/CompilerCommand.java
+++ b/sources/scalac/CompilerCommand.java
@@ -12,7 +12,8 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import scalac.util.ClassPath;
+import scala.tools.util.ClassPath;
+
import scalac.util.Reporter;
import scalac.util.CommandParser;
import scalac.util.ArgumentParser;
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 30d385c016..d2d0df060d 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -23,6 +23,7 @@ import java.nio.charset.UnsupportedCharsetException;
import java.util.*;
import scala.tools.util.AbstractFile;
+import scala.tools.util.ClassPath;
import scala.tools.util.Position;
import scala.tools.util.SourceFile;
import scala.tools.util.SourceReader;
@@ -299,7 +300,7 @@ public abstract class Global {
/** Reads and returns the source file in file with given name. */
public SourceFile getSourceFile(String filename) throws IOException {
- AbstractFile file = AbstractFile.open(null, filename);
+ AbstractFile file = AbstractFile.getFile(filename);
if (file == null) throw new FileNotFoundException(
"source file '" + filename + "' could not be found");
return getSourceFile(file);
@@ -307,16 +308,14 @@ public abstract class Global {
/** Reads and returns the source file in given abstract file. */
public SourceFile getSourceFile(AbstractFile file) throws IOException {
- if (!file.exists()) throw new FileNotFoundException(
- "source file '" + file + "' could not be found");
return new SourceFile(file, reader.read(file));
}
/** Reads and returns the source file of given clasz. */
public SourceFile getSourceFile(Symbol clasz) throws IOException {
assert clasz.isClass() && clasz.isStatic(): Debug.show(clasz);
- AbstractFile file = classPath.openFile(
- SourceRepresentation.externalizeFileName(clasz, ".scala"));
+ AbstractFile file = classPath.getRoot().lookupPath(
+ SourceRepresentation.externalizeFileName(clasz, ".scala"), false);
if (file == null) throw new FileNotFoundException(
"source file for " + clasz + " could not be found");
return getSourceFile(file);
@@ -324,7 +323,7 @@ public abstract class Global {
/** Returns the root symbol loader. */
public SymbolLoader getRootLoader() {
- return new PackageParser(this);
+ return new PackageParser(this, classPath.getRoot());
}
/** the top-level compilation process
diff --git a/sources/scalac/symtab/classfile/CLRPackageParser.java b/sources/scalac/symtab/classfile/CLRPackageParser.java
index decce98a26..51ba33edf6 100644
--- a/sources/scalac/symtab/classfile/CLRPackageParser.java
+++ b/sources/scalac/symtab/classfile/CLRPackageParser.java
@@ -75,7 +75,7 @@ public class CLRPackageParser extends SymbolLoader {
private boolean initialized = false;
public void init() {
if (initialized) return;
- scalac.util.ClassPath.addFilesInPath(
+ scala.tools.util.ClassPath.addFilesInPath(
assemrefs, global.args.assemrefs.value);
Assembly mscorlib = findAssembly("mscorlib.dll");
Type.initMSCORLIB(mscorlib);
diff --git a/sources/scalac/symtab/classfile/PackageParser.java b/sources/scalac/symtab/classfile/PackageParser.java
index c28a11f443..13882f7714 100644
--- a/sources/scalac/symtab/classfile/PackageParser.java
+++ b/sources/scalac/symtab/classfile/PackageParser.java
@@ -8,10 +8,8 @@
package scalac.symtab.classfile;
-import java.io.IOException;
import java.util.Iterator;
import java.util.HashMap;
-import java.util.HashSet;
import scala.tools.util.AbstractFile;
import scala.tools.util.Position;
@@ -23,7 +21,6 @@ import scalac.symtab.Symbol;
import scalac.symtab.SymbolLoader;
import scalac.symtab.Type;
import scalac.util.Name;
-import scalac.util.SourceRepresentation;
/**
* This class implements a package member loader. It can be used to
@@ -34,12 +31,16 @@ public class PackageParser extends SymbolLoader {
//########################################################################
// Private Fields
+ /** The directory to read */
+ private final AbstractFile directory;
+
//########################################################################
// Public Constructors
/** Initializes this instance. */
- public PackageParser(Global global) {
+ public PackageParser(Global global, AbstractFile directory) {
super(global);
+ this.directory = directory;
}
//########################################################################
@@ -47,43 +48,27 @@ public class PackageParser extends SymbolLoader {
/** Completes the package symbol by loading all its members. */
protected String doComplete(Symbol peckage) {
- boolean isRoot = peckage.isRoot();
- String dirname = isRoot ? null
- : SourceRepresentation.externalizeFileName(peckage, "/");
-
// collect JVM and source members
+ boolean isRoot = peckage.isRoot();
HashMap sources = new HashMap();
HashMap classes = new HashMap();
- HashSet packages = new HashSet();
- String[] base = global.classPath.components();
- for (int i = 0; i < base.length; i++) {
- AbstractFile dir = AbstractFile.open(base[i], dirname);
- if (dir == null) continue;
- try {
- String[] filenames = dir.list();
- if (filenames == null) continue;
- for (int j = 0; j < filenames.length; j++) {
- String fname = filenames[j];
- if (fname.endsWith("/") && !fname.equals("META-INF/")) {
- String name = fname.substring(0, fname.length() - 1);
- packages.add(name);
- continue;
- }
- if (!isRoot && fname.endsWith(".class")) {
- String name = fname.substring(0, fname.length() - 6);
- if (!classes.containsKey(name))
- classes.put(name, dir.open(fname));
- continue;
- }
- if (!isRoot && fname.endsWith(".scala")) {
- String name = fname.substring(0, fname.length() - 6);
- if (!sources.containsKey(name))
- sources.put(name, dir.open(fname));
- continue;
- }
- }
- } catch (IOException exception) {
- if (global.debug) exception.printStackTrace();
+ HashMap packages = new HashMap();
+ for (Iterator i = directory.list(); i.hasNext(); ) {
+ AbstractFile file = (AbstractFile)i.next();
+ String filename = file.getName();
+ if (file.isDirectory()) {
+ if (filename.equals("META-INF")) continue;
+ packages.put(filename, file);
+ continue;
+ }
+ if (!isRoot && filename.endsWith(".class")) {
+ String name = filename.substring(0, filename.length() - 6);
+ if (!classes.containsKey(name)) classes.put(name, file);
+ continue;
+ }
+ if (!isRoot && filename.endsWith(".scala")) {
+ String name = filename.substring(0, filename.length() - 6);
+ if (!sources.containsKey(name)) sources.put(name, file);
continue;
}
}
@@ -115,9 +100,12 @@ public class PackageParser extends SymbolLoader {
SymbolLoader loader = new ClassParser(global, cfile);
peckage.newLoadedClass(JAVA, classname, loader, members);
}
- for (Iterator i = packages.iterator(); i.hasNext(); ) {
- String name = (String)i.next();
- peckage.newLoadedPackage(Name.fromString(name), this, members);
+ for (Iterator i = packages.entrySet().iterator(); i.hasNext(); ) {
+ HashMap.Entry entry = (HashMap.Entry)i.next();
+ String name = (String)entry.getKey();
+ AbstractFile dfile = (AbstractFile)entry.getValue();
+ SymbolLoader loader = new PackageParser(global, dfile);
+ peckage.newLoadedPackage(Name.fromString(name), loader, members);
}
// collect and create CLR members
@@ -126,7 +114,7 @@ public class PackageParser extends SymbolLoader {
// initialize package
peckage.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, peckage));
- return dirname == null ? "anonymous package" : "package '"+dirname+"'";
+ return "directory path '" + directory + "'";
}
//########################################################################