diff options
Diffstat (limited to 'sources/scalac/util/AbstractFile.java')
-rw-r--r-- | sources/scalac/util/AbstractFile.java | 557 |
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; + } + } +} |