almost working
[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 =
13         System.getProperty("ibex.mail.root", File.separatorChar + "var" + File.separatorChar + "org.ibex.mail");
14
15     //public final FileBased root = new FileBased(STORAGE_ROOT + File.separatorChar);
16     public static Transcript transcript = null;
17     static {
18         try {
19             transcript = new Transcript(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 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 extends MessageStore {
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 message) throws IOException {
44             File today = new File(path + File.separatorChar + (new SimpleDateFormat("yy-MMM-dd").format(new Date())));
45             today.mkdirs();
46             
47             String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
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             OutputStream os = new FileOutputStream(target);
58             message.dump(os);
59             os.close();
60             return -1; // FIXME
61         }
62     }
63
64     public static class FileBased extends MessageStore {
65         private String path;
66         private FileBased(String path) throws IOException { new File(this.path = path).mkdirs(); }
67         public MessageStore slash(String name) throws IOException { return new FileBased(path + "/" + name); }
68
69         public int[] list() {
70             String[] names = new File(path).list();
71             int[] ret = new int[names.length];
72             for(int i=0, j=0; j<ret.length; i++, j++) {
73                 try {
74                     ret[j] = Integer.parseInt(names[i].substring(0, names[i].length() - 1));
75                 } catch (NumberFormatException nfe) {
76                     Log.warn(FileBased.class, "NumberFormatException: " + names[i].substring(0, names[i].length() - 1));
77                     j--;
78                     int[] newret = new int[ret.length - 1];
79                     System.arraycopy(ret, 0, newret, 0, newret.length);
80                     ret = newret;
81                 }
82             }
83             return ret;
84         }
85
86         /** returns a message identifier */
87         public synchronized int add(Message message) throws IOException {
88             int[] all = list();
89             int max = 0;
90             for(int i=0; i<all.length; i++) max = Math.max(max, all[i]);
91             int target = max++;
92             File f = new File(path + File.separatorChar + max + ".-");
93             FileOutputStream fo = new FileOutputStream(f);
94             message.dump(fo);
95             fo.close();
96             f.renameTo(new File(path + File.separatorChar + max + "."));
97             return target;
98         }
99
100         public Message.StoredMessage get(int messagenum) throws IOException {
101             File f = new File(path + File.separatorChar + messagenum + ".");        
102             if (!f.exists()) throw new FileNotFoundException(f.toString());
103             try {
104                 Message.StoredMessage ret = new Message.StoredMessage(new LineReader(new InputStreamReader(new FileInputStream(f))));
105                 // FIXME: set answered/read/etc here
106                 return ret;
107             } catch (MailException.Malformed malf) {
108                 Log.error(this, "This should never happen");
109                 Log.error(this, malf);
110                 return null;
111             }
112         }
113
114         // query types: stringmatch (headers, body), header element, deletion status, date range, message size
115         public Message.StoredMessage[] query(int maxResults) {
116             throw new RuntimeException("FileBased.query() not implemented yet");
117         }
118
119     }
120
121 }