summaryrefslogtreecommitdiff
path: root/sources/scalac/util/AbstractFile.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/util/AbstractFile.java')
-rw-r--r--sources/scalac/util/AbstractFile.java557
1 files changed, 557 insertions, 0 deletions
diff --git a/sources/scalac/util/AbstractFile.java b/sources/scalac/util/AbstractFile.java
new file mode 100644
index 0000000000..2487e07ca3
--- /dev/null
+++ b/sources/scalac/util/AbstractFile.java
@@ -0,0 +1,557 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scalac.util;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+
+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();
+
+ /** is the file a directory?
+ */
+ public abstract boolean isDirectory();
+
+ /** 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());
+ }
+
+ /** open file 'name' in directory 'dirname'
+ */
+ 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 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 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 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 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 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));
+ }
+ }
+ }
+
+ 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 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 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 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;
+ }
+ }
+}