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