KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > mbox > MboxDataStorage


1 // The contents of this file are subject to the Mozilla Public License Version
2
// 1.1
3
//(the "License"); you may not use this file except in compliance with the
4
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
5
//
6
//Software distributed under the License is distributed on an "AS IS" basis,
7
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
8
//for the specific language governing rights and
9
//limitations under the License.
10
//
11
//The Original Code is "The Columba Project"
12
//
13
//The Initial Developers of the Original Code are Frederik Dietz and Timo
14
// Stich.
15
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
16
//
17
//All Rights Reserved.
18

19 package org.columba.mail.folder.mbox;
20
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.ObjectInputStream JavaDoc;
27 import java.io.ObjectOutputStream JavaDoc;
28 import java.io.RandomAccessFile JavaDoc;
29 import java.nio.channels.FileChannel JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.Hashtable JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33
34 import org.columba.core.io.StreamUtils;
35 import org.columba.mail.folder.AbstractMessageFolder;
36 import org.columba.mail.folder.FolderInconsistentException;
37 import org.columba.mail.folder.IDataStorage;
38 import org.columba.ristretto.io.FileSource;
39 import org.columba.ristretto.io.Source;
40
41 public class MboxDataStorage implements IDataStorage {
42
43     /** JDK 1.4+ logging framework logger, used for logging. */
44     private static final Logger JavaDoc LOG = Logger
45             .getLogger("org.columba.mail.folder.mbox");
46
47     private static final String JavaDoc FROMLINE = "From \n";
48
49     private static final byte[] TERMLINE = new byte[] { '\n' };
50
51     protected AbstractMessageFolder folder;
52
53     protected File JavaDoc mboxFile;
54
55     protected File JavaDoc messageFile;
56
57     protected Hashtable JavaDoc messages;
58
59     protected Object JavaDoc largestUid;
60
61     /**
62      * Constructs the MboxDataStorage.
63      *
64      * @param folder
65      */

66     public MboxDataStorage(AbstractMessageFolder folder) {
67         this.folder = folder;
68         messages = new Hashtable JavaDoc();
69
70         mboxFile = new File JavaDoc(folder.getDirectoryFile(), folder
71                 .getId());
72
73         messageFile = new File JavaDoc(folder.getDirectoryFile(), ".messages");
74
75         if (!mboxFile.exists()) {
76             try {
77                 mboxFile.createNewFile();
78             } catch (IOException JavaDoc e) {
79                 LOG.severe(e.getLocalizedMessage());
80             }
81         } else {
82             try {
83                 load();
84             } catch (IOException JavaDoc e) {
85                 LOG.severe(e.getLocalizedMessage());
86                     
87                 throw new RuntimeException JavaDoc("Mailbox is corrupted!");
88             }
89         }
90
91     }
92
93     /**
94      * @see org.columba.mail.folder.IDataStorage#removeMessage(java.lang.Object)
95      */

96     public void removeMessage(Object JavaDoc uid) throws Exception JavaDoc {
97         MboxMessage message = (MboxMessage) messages.remove(uid);
98
99         if (uid.equals(largestUid)) {
100             FileChannel JavaDoc channel = new RandomAccessFile JavaDoc(mboxFile, "rw")
101                     .getChannel();
102             channel
103                     .truncate(mboxFile.length()
104                             - (message.getLength() + FROMLINE.length() + TERMLINE.length));
105             channel.close();
106         } else {
107
108             int intUid = ((Integer JavaDoc) uid).intValue();
109
110             deleteFilePart(mboxFile, message.getStart() - FROMLINE.length(),
111                     message.getLength() + FROMLINE.length() + TERMLINE.length);
112
113             // update message starts of following messages
114
Enumeration JavaDoc uids = messages.keys();
115             while (uids.hasMoreElements()) {
116                 Integer JavaDoc actUid = (Integer JavaDoc) uids.nextElement();
117
118                 if (actUid.intValue() > intUid) {
119                     MboxMessage m = (MboxMessage) messages.get(actUid);
120                     m
121                             .setStart(m.getStart()
122                                     - (message.getLength() + FROMLINE.length() + TERMLINE.length));
123                 }
124             }
125         }
126     }
127
128     /**
129      * @see org.columba.mail.folder.IDataStorage#getMessageSource(java.lang.Object)
130      */

131     public Source getMessageSource(Object JavaDoc uid) throws Exception JavaDoc {
132
133         if( ! exists(uid)) throw new FolderInconsistentException();
134         MboxMessage message = (MboxMessage) messages.get(uid);
135         
136         
137         FileInputStream JavaDoc in = new FileInputStream JavaDoc(mboxFile);
138         in.skip(message.getStart());
139
140         File JavaDoc tempFile = File.createTempFile("mbox_message", ".tmp");
141         tempFile.deleteOnExit();
142
143         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(tempFile);
144
145         StreamUtils.streamCopy(in, out, (int) message.getLength());
146
147         in.close();
148         out.close();
149
150         return new FileSource(tempFile);
151     }
152
153     /**
154      * @see org.columba.mail.folder.IDataStorage#getMessageStream(java.lang.Object)
155      */

156     public InputStream JavaDoc getMessageStream(Object JavaDoc uid) throws Exception JavaDoc {
157         MboxMessage message = (MboxMessage) messages.get(uid);
158
159         FileInputStream JavaDoc in = new FileInputStream JavaDoc(mboxFile);
160         in.skip(message.getStart());
161
162         File JavaDoc tempFile = File.createTempFile("mbox_message", ".tmp");
163         tempFile.deleteOnExit();
164
165         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(tempFile);
166
167         StreamUtils.streamCopy(in, out, (int) message.getLength());
168
169         in.close();
170         out.close();
171
172         return new FileInputStream JavaDoc(tempFile);
173     }
174
175     /**
176      * @see org.columba.mail.folder.IDataStorage#saveMessage(java.lang.Object,
177      * java.io.InputStream)
178      */

179     public void saveMessage(Object JavaDoc uid, InputStream JavaDoc source) throws Exception JavaDoc {
180         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(mboxFile, true);
181         out.write(FROMLINE.getBytes("US-ASCII"));
182
183         long pos = mboxFile.length();
184         long length = StreamUtils.streamCopy(source, out);
185
186         out.write(TERMLINE);
187         out.close();
188
189         messages.put(uid, new MboxMessage(uid, pos, length));
190
191         largestUid = uid;
192     }
193
194     /**
195      * @see org.columba.mail.folder.IDataStorage#getMessageCount()
196      */

197     public int getMessageCount() {
198         return messages.size();
199     }
200
201     /**
202      * @see org.columba.mail.folder.IDataStorage#exists(java.lang.Object)
203      */

204     public boolean exists(Object JavaDoc uid) throws Exception JavaDoc {
205         return messages.containsKey(uid);
206     }
207
208     /**
209      * @see org.columba.mail.folder.IDataStorage#getMessageUids()
210      */

211     public Object JavaDoc[] getMessageUids() {
212         return messages.keySet().toArray();
213     }
214
215     /**
216      *
217      *
218      * @param file
219      * @param startpos
220      * @param length
221      * @throws IOException
222      */

223     protected void deleteFilePart(File JavaDoc file, long startpos, long length)
224             throws IOException JavaDoc {
225         RandomAccessFile JavaDoc ramFile = new RandomAccessFile JavaDoc(file, "rw");
226         long oldlength = file.length();
227
228         FileChannel JavaDoc channel1 = ramFile.getChannel();
229         FileChannel JavaDoc channel2 = new FileInputStream JavaDoc(file).getChannel();
230
231         channel2.position(startpos + length);
232         channel1.transferFrom(channel2, startpos, oldlength
233                 - (length + startpos));
234         channel2.close();
235
236         channel1.truncate(oldlength - length);
237         channel1.close();
238     }
239
240     protected void load() throws IOException JavaDoc {
241         ObjectInputStream JavaDoc in = new ObjectInputStream JavaDoc(new FileInputStream JavaDoc(
242                 messageFile));
243         MboxMessage message;
244
245         int size = in.readInt();
246
247         messages = new Hashtable JavaDoc(size);
248         for (int i = 0; i < size; i++) {
249             message = new MboxMessage(new Integer JavaDoc(in.readInt()), in.readLong(),
250                     in.readLong());
251             messages.put(message.getUid(), message);
252         }
253
254         in.close();
255     }
256
257     public void save() throws IOException JavaDoc {
258         ObjectOutputStream JavaDoc out = new ObjectOutputStream JavaDoc(new FileOutputStream JavaDoc(
259                 messageFile, false));
260         MboxMessage message;
261
262         int size = messages.size();
263         out.writeInt(size);
264
265         Enumeration JavaDoc message_enum = messages.elements();
266
267         for (int i = 0; i < size; i++) {
268             message = (MboxMessage) message_enum.nextElement();
269
270             out.writeInt(((Integer JavaDoc) message.getUid()).intValue());
271             out.writeLong(message.getStart());
272             out.writeLong(message.getLength());
273         }
274
275         out.close();
276     }
277
278
279 }
Popular Tags