added tons of stuff, including js support
[org.ibex.mail.git] / src / org / ibex / mail / store / MessageStore.java
1 package org.ibex.mail.store;
2 import org.ibex.util.*;
3 import java.io.*;
4 import java.net.*;
5
6 // FIXME: appallingly inefficient
7 public class MessageStore {
8
9     private final String STORAGE_ROOT = System.getProperty("ibex.mail.root",
10                                                            File.separatorChar + "var" + File.separatorChar + "org.ibex.mail");
11
12     //public final FileBased root = new FileBased(STORAGE_ROOT + File.separatorChar);
13     public final FileBased transcript = new FileBased(STORAGE_ROOT + File.separatorChar + "transcript");
14
15     public MessageStore slash(String name) {
16         throw new Error(this.getClass().getName() + " does not support the slash() method"); }
17     public int[] list() { throw new Error(this.getClass().getName() + " does not support the list() method"); }
18     public int add(StoredMessage message) throws IOException {
19         throw new Error(this.getClass().getName() + " does not support the add() method"); }
20     public StoredMessage get(int messagenum) throws IOException {
21         throw new Error(this.getClass().getName() + " does not support the get() method"); }
22     public StoredMessage[] query(int maxResults) {
23         throw new Error(this.getClass().getName() + " does not support the query() method"); }
24
25     /** a fast-write, slow-read place to stash all messages we touch -- in case of a major f*ckup */
26     public static class Transcript {
27         private String path;
28         public Transcript(String path) throws IOException { new File(this.path = path).mkdirs(); }
29         private static String lastTime = null;
30         private static int lastCounter = 0;
31
32         /** returns a message identifier */
33         public synchronized int add(StoredMessage message) throws IOException {
34             File today = new File(path + File.separatorChar + (new SimpleDateFormat("yyyyy.MMMMM.dd").format(new Date())));
35             today.mkdirs();
36             
37             String time = new SimpleDateFormat("").format(new Date("hh.mm.ss"));
38             synchronized (Transcript.class) {
39                 if (lastTime != null && lastTime.equals(time)) {
40                     time += "." + (++lastCounter);
41                 } else {
42                     lastTime = time;
43                 }
44             }
45             
46             File target = new File(today.getPath() + File.separatorChar() + time + ".txt");
47             String msg = message.dumpStoredForm();
48             OutputStream os = new FileOutputStream(target);
49             os.write(msg.getBytes("UTF-8"));  // FIXME: right?
50             os.close();
51             return -1; // FIXME
52         }
53     }
54
55     public static FileBased extends MessageStore {
56         private String path;
57         private FileBased(String path) throws IOException { new File(this.path = path).mkdirs(); }
58         public FileBased slash(String name) { return new FileBased(path + "/" + name); }
59
60         public int[] list() {
61             String[] names = new File(path).list();
62             int[] ret = new int[names.length];
63             for(int i=0, j=0; j<ret.length; i++, j++) {
64                 try {
65                     ret[j] = Integer.parseInt(names[i].substring(0, names[i].length - 1));
66                 } catch (NumberFormatException nfe) {
67                     Log.warn(FileBased.class, "NumberFormatException: " + names[i].substring(0, names[i].length - 1));
68                     j--;
69                     int[] newret = new int[ret.length - 1];
70                     System.arrayCopy(ret, 0, newret, 0, newret.length);
71                     ret = newret;
72                 }
73             }
74             return ret;
75         }
76
77         /** returns a message identifier */
78         public synchronized int add(StoredMessage message) throws IOException {
79             int[] all = list();
80             int max = 0;
81             for(int i=0; i<all.length; i++) max = Math.max(max, all[i]);
82             int target = max++;
83             File f = new File(path + File.separatorChar + max + ".-");
84             FileOutputStream fo = new FileOutputStream(f);
85             message.dump(fo);
86             fo.close();
87             f.renameTo(path + File.separatorChar + max + ".");
88             return target;
89         }
90
91         public StoredMessage get(int messagenum) throws IOException {
92             File f = new File(path + File.separatorChar + messagenum + ".");        
93             if (!f.exists()) throw new FileNotFoundException(f);
94             return StoredMessage.undump(new FileInputStream(f));
95         }
96
97         // query types: stringmatch (headers, body), header element, deletion status, date range, message size
98         public StoredMessage[] query(int maxResults) {
99             throw new RuntimeException("FileBased.query() not implemented yet");
100         }
101
102     }
103
104 }