1 package org.ibex.mail.target;
2 import org.ibex.mail.*;
3 import org.ibex.util.*;
4 import org.ibex.mail.*;
10 public class Mailbox extends Target {
13 public void set(Message m, String key, String val) { throw new MailException.MetadataNotSupported(); }
14 public String get(Message m, String key) { throw new MailException.MetadataNotSupported(); }
17 public final boolean getFlag(Message m, int flags) { return (flags(m) & flag) == flags; }
18 public final void setFlag(Message m, int flag) { flags(m, flags | flag); }
19 public final void clearFlag(Message m, int flag) { flags(m, flags & ~flag); }
20 protected abstract void flags(Message m, int newFlags); // set the flags for a given message
21 protected abstract int flags(Message m); // get the flags for a given message
22 public abstract int uid(Message m); // get the uid for a given message (see IMAP RFC)
23 public abstract int num(Message m); // get the "message number" for a given message (see IMAP RFC)
24 public abstract int uidNext(); // get the next uid to be assigned
25 public abstract int uidValidity(); // get the uid validity identifier (see IMAP RFC)
28 public int add(Message message) throws MailException { throw new Error("not implemented"); }
29 public int delete(Message message) throws MailException { throw new Error("not implemented"); }
30 public void query(Query q, Message.Visitor v) throws MailException { throw new Error("not implemented"); }
31 public int count(Query q) throws MailException { throw new Error("not implemented"); }
32 public void move(Query q, Mailbox dest, boolean copy) throws MailException { throw new Error("not implemented"); }
35 public void rename(String newName) throws MailException { throw new Error("not implemented"); }
36 public void destroy() throws MailException { throw new Error("not implemented"); }
37 public Mailbox slash(String name, boolean create) throws MailException { throw new Error("not implemented"); }
39 /** a fast-write, slow-read place to stash all messages we touch -- in case of a major f*ckup */
40 public static class Transcript extends Mailbox {
42 public Transcript(String path) throws MailException { new File(this.path = path).mkdirs(); }
43 private static String lastTime = null;
44 private static int lastCounter = 0;
46 /** returns a message identifier */
47 public synchronized int add(Message message) throws MailException {
49 File today = new File(path + File.separatorChar + (new SimpleDateFormat("yy-MMM-dd").format(new Date())));
52 String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
53 synchronized (Transcript.class) {
54 if (lastTime != null && lastTime.equals(time)) {
55 time += "." + (++lastCounter);
61 File target = new File(today.getPath() + File.separatorChar + time + ".txt");
62 OutputStream os = new FileOutputStream(target);
66 } catch (IOException e) { throw new MailException.IOException(e); }
70 public static class FileBased extends Mailbox {
72 private FileBased(String path) throws MailException { new File(this.path = path).mkdirs(); }
73 public Mailbox slash(String name, boolean create) throws MailException {
75 return new FileBased(path + "/" + name);
79 String[] names = new File(path).list();
80 int[] ret = new int[names.length];
81 for(int i=0, j=0; j<ret.length; i++, j++) {
83 ret[j] = Integer.parseInt(names[i].substring(0, names[i].length() - 1));
84 } catch (NumberFormatException nfe) {
85 Log.warn(FileBased.class, "NumberFormatException: " + names[i].substring(0, names[i].length() - 1));
87 int[] newret = new int[ret.length - 1];
88 System.arraycopy(ret, 0, newret, 0, newret.length);
95 /** returns a message identifier */
96 public synchronized int add(Message message) throws MailException {
100 for(int i=0; i<all.length; i++) max = Math.max(max, all[i]);
102 File f = new File(path + File.separatorChar + max + ".-");
103 FileOutputStream fo = new FileOutputStream(f);
106 f.renameTo(new File(path + File.separatorChar + max + "."));
108 } catch (IOException e) { throw new MailException.IOException(e); }
111 public Message get(int messagenum) throws MailException {
112 File f = new File(path + File.separatorChar + messagenum + ".");
113 if (!f.exists()) throw new MailException.IOException(new FileNotFoundException(f.toString()));
115 // FIXME: need to store envelope from/to
116 //Message ret = new Message(new LineReader(new InputStreamReader(new FileInputStream(f))));
117 // FIXME: set answered/read/etc here
121 } catch (MailException.Malformed malf) {
122 Log.error(this, "This should never happen");
123 Log.error(this, malf);
130 // query types: stringmatch (headers, body), header element, deletion status, date range, message size
131 public Message[] query(int maxResults) {
132 throw new RuntimeException("FileBased.query() not implemented yet");
139 private static Hashtable cache = new Hashtable();
140 public static Mailbox getForUser(String user) {
141 Mailbox ret = (Mailbox)cache.get(user);
142 if (ret == null) ret = new Mailbox(user);
145 Mailbox(String user) { this.user = user; }
146 public Mailbox slash(String name) throws MailException {
147 throw new Error(this.getClass().getName() + " does not support the slash() method"); }
148 public synchronized int add(Message message) throws MailException {
149 FileOutputStream fos = new FileOutputStream("/var/mail/" + user, true);
150 PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos));
151 pw.println("From " + message.envelopeFrom);
159 private static final String STORAGE_ROOT =
160 System.getProperty("ibex.mail.root", File.separatorChar + "var" + File.separatorChar + "org.ibex.mail");
161 public static FileBased root = null;
162 public static Transcript transcript = null;
165 root = new FileBased(STORAGE_ROOT + File.separatorChar);
166 transcript = new Transcript(STORAGE_ROOT + File.separatorChar + "transcript");
167 } catch (Exception e) {
172 public final void accept(Message m) throws MailException { add(m); }