added org.ibex.js.Directory: simple JS filesystem interface
authoradam <adam@megacz.com>
Sun, 9 May 2004 23:27:08 +0000 (23:27 +0000)
committeradam <adam@megacz.com>
Sun, 9 May 2004 23:27:08 +0000 (23:27 +0000)
darcs-hash:20040509232708-5007d-7bb9bb2a6ceff2121ff652bd66aa2164b1f9c951.gz

src/org/ibex/js/Directory.java [new file with mode: 0644]

diff --git a/src/org/ibex/js/Directory.java b/src/org/ibex/js/Directory.java
new file mode 100644 (file)
index 0000000..5f5ac38
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] 
+package org.ibex.js; 
+
+import org.ibex.util.*; 
+import java.util.*;
+import java.io.*;
+
+// FEATURE: support for move
+// FEATURE: support for bytestreams
+// FEATURE: cache directories so we can do equality checking on them?
+// FEATURE: autoconvert "true" to true and "0.3" to 0.3 on readback
+
+/** 
+ * A crude mechanism for using a filesystem as object storage.
+ *
+ *  This object represents a directory; writing a string, number, or
+ *  boolean to any of its properties will create a file with the
+ *  (encoded) property name as its filename and the "stringified"
+ *  value as its contents.
+ *
+ *  Writing 'null' to one of this object's properties will
+ *  [recursively if necessary] delete the corresponding directory
+ *  entry.
+ *  
+ *  Writing any other object to one of this object's properties will
+ *  create a new Directory object and copy the other object's keys()
+ *  into the new Directory.  This means that assigning one directory
+ *  to a property of another directory will <i>copy</i> the directory,
+ *  not move it.  There is currently no way to move directories.
+ *
+ *  If an object is written to a property that already has an entry,
+ *  the old one is deleted (equivalent to writing 'null') first.
+ * 
+ *  WARNING: when instantiating a Directory object with a file
+ *  argument that points to a non-directory File, this class will
+ *  delete that file and create a directory!
+ */
+public class Directory extends JS {
+
+    File f;
+
+    /** 
+     *  Create the directory object.  Existing directories will be
+     *  preserved; if a file is present it will be obliterated.
+     */ 
+    public Directory(File f) throws IOException {
+        this.f = f;
+        if (!f.exists()) new Directory(new File(f.getParent()));
+        if (!f.isDirectory()) destroy(f);
+        f.mkdirs();
+    }
+
+    private static void destroy(File f) throws IOException {
+        if (!f.exists()) return;
+        if (f.isDirectory()) {
+            String[] entries = f.list();
+            for(int i=0; i<entries.length; i++) destroy(new File(f.getAbsolutePath() + File.separatorChar + entries[i]));
+        }
+        f.delete();
+    }
+
+    public void put(Object key0, Object val) throws JSExn {
+        try {
+            if (key0 == null) return;
+            String key = toString(key0);
+            File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key));
+            destroy(f2);
+            if (val == null) return;
+            if (val instanceof JS) {
+                Directory d2 = new Directory(f2);
+                Enumeration e = ((JS)val).keys();
+                while(e.hasMoreElements()) {
+                    String k = (String)e.nextElement();
+                    Object v = ((JS)val).get(k);
+                    d2.put(k, v);
+                }
+            } else {
+                OutputStream out = new FileOutputStream(f2);
+                Writer w = new OutputStreamWriter(out);
+                w.write(toString(val));
+                w.flush();
+                out.close();
+            }
+        } catch (IOException ioe) {
+            throw new JSExn.IO(ioe);
+        }
+    }
+
+    public Object get(Object key0) throws JSExn {
+        try {
+            if (key0 == null) return null;
+            String key = toString(key0);
+            File f2 = new File(f.getAbsolutePath() + File.separatorChar + FileNameEncoder.encode(key));
+            if (!f2.exists()) return null;
+            if (f2.isDirectory()) return new Directory(f2);
+            char[] chars = new char[(int)f2.length()];
+            int numchars = 0;
+            Reader r = new InputStreamReader(new FileInputStream(f2));
+            while(true) {
+                int numread = r.read(chars, numchars, chars.length - numchars);
+                if (numread == -1) return new String(chars, 0, numchars);
+                numchars += numread;
+            }
+        } catch (IOException ioe) {
+            throw new JSExn.IO(ioe);
+        }
+    }
+
+    public Enumeration keys() {
+        final String[] elements = f.list();
+        return new Enumeration() {
+                int i = 0;
+                public boolean hasMoreElements() { return i < elements.length; }
+                public Object nextElement() { return FileNameEncoder.decode(elements[i++]); }
+            };
+    }
+}