1 /*****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.apache.james.mailrepository;
47
48 import org.apache.avalon.framework.activity.Initializable;
49 import org.apache.avalon.framework.service.ServiceException;
50 import org.apache.avalon.framework.service.ServiceManager;
51 import org.apache.avalon.framework.service.Serviceable;
52 import org.apache.avalon.framework.configuration.Configurable;
53 import org.apache.avalon.framework.configuration.Configuration;
54 import org.apache.avalon.framework.configuration.ConfigurationException;
55 import org.apache.avalon.framework.logger.AbstractLogEnabled;
56 import org.apache.james.core.MailImpl;
57 import org.apache.james.services.MailRepository;
58 import org.apache.mailet.Mail;
59 import org.apache.oro.text.regex.MalformedPatternException;
60 import org.apache.oro.text.regex.Perl5Compiler;
61 import org.apache.oro.text.regex.Pattern;
62 import org.apache.oro.text.regex.Perl5Matcher;
63
64 import javax.mail.MessagingException;
65 import javax.mail.Session;
66 import javax.mail.internet.MimeMessage;
67
68 import java.io.ByteArrayInputStream;
69 import java.io.ByteArrayOutputStream;
70 import java.io.File;
71 import java.io.FileNotFoundException;
72 import java.io.IOException;
73 import java.io.RandomAccessFile;
74 import java.security.NoSuchAlgorithmException;
75 import java.security.MessageDigest;
76 import java.text.SimpleDateFormat;
77 import java.util.ArrayList;
78 import java.util.Calendar;
79 import java.util.Collection;
80 import java.util.Hashtable;
81 import java.util.Iterator;
82 import java.util.Locale;
83 import java.util.Properties;
84
85 /***
86 * Implementation of a MailRepository using UNIX mbox files.
87 *
88 * <p>Requires a configuration element in the .conf.xml file of the form:
89 * <br><repository destinationURL="mbox://<directory>"
90 * <br> type="MAIL"
91 * <br></directory> is where the individual mbox files are read from/written to
92 * <br>Type can ONLY be MAIL (SPOOL is NOT supported)
93 *
94 * <p>Requires a logger called MailRepository.
95 *
96 * <p> Implementation notes:
97 * <p>
98 * This class keeps an internal store of the mbox file
99 * When the internal mbox file is updated (added/deleted)
100 * then the file will be re-read from disk and then written back.
101 * This is a bit inefficent but means that the file on disk
102 * should be correct.
103 * <p>
104 * The mbox store is mainly meant to be used as a one-way street.
105 * Storing new emails is very fast (append to file) whereas reading them (via POP3) is
106 * slower (read from disk and parse).
107 * Therefore this implementation is best suited to people who wish to use the mbox format
108 * for taking data out of James and into something else (IMAP server or mail list displayer)
109 *
110 * @version CVS $Revision: 495537 $
111 */
112
113
114 public class MBoxMailRepository
115 extends AbstractLogEnabled
116 implements MailRepository, Serviceable, Configurable, Initializable {
117
118
119 static final SimpleDateFormat dy = new SimpleDateFormat("EE MMM dd HH:mm:ss yyyy", Locale.US);
120 static final String LOCKEXT = ".lock";
121 static final String WORKEXT = ".work";
122 static final int LOCKSLEEPDELAY = 2000;
123 static final int MAXSLEEPTIMES = 100;
124 static final long MLISTPRESIZEFACTOR = 10 * 1024;
125 static final long DEFAULTMLISTCAPACITY = 20;
126
127 /***
128 * Whether line buffering is turned used.
129 */
130 private static boolean BUFFERING = true;
131
132 /***
133 * Whether 'deep debugging' is turned on.
134 */
135 private static final boolean DEEP_DEBUG = true;
136
137 /***
138 * The internal list of the emails
139 * The key is an adapted MD5 checksum of the mail
140 */
141 private Hashtable mList = null;
142 /***
143 * The filename to read & write the mbox from/to
144 */
145 private String mboxFile;
146
147 /***
148 * A callback used when a message is read from the mbox file
149 */
150 public interface MessageAction {
151 public boolean isComplete();
152 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart);
153 }
154
155
156 /***
157 * Convert a MimeMessage into raw text
158 * @param mc The mime message to convert
159 * @return A string representation of the mime message
160 * @throws IOException
161 * @throws MessagingException
162 */
163 private String getRawMessage(MimeMessage mc) throws IOException, MessagingException {
164
165 ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
166 mc.writeTo(rawMessage);
167 return rawMessage.toString();
168 }
169
170 /***
171 * Parse a text block as an email and convert it into a mime message
172 * @param emailBody The headers and body of an email. This will be parsed into a mime message and stored
173 */
174 private MimeMessage convertTextToMimeMessage(String emailBody) {
175
176 MimeMessage mimeMessage = null;
177
178 ByteArrayInputStream mb = new ByteArrayInputStream(emailBody.getBytes());
179 Properties props = System.getProperties();
180 Session session = Session.getDefaultInstance(props);
181 try {
182 mimeMessage = new MimeMessage(session, mb);
183
184
185 } catch (MessagingException e) {
186 getLogger().error("Unable to parse mime message!", e);
187 }
188
189 if (mimeMessage == null && getLogger().isDebugEnabled()) {
190 StringBuffer logBuffer =
191 new StringBuffer(128)
192 .append(this.getClass().getName())
193 .append(" Mime message is null");
194 getLogger().debug(logBuffer.toString());
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 return mimeMessage;
220 }
221
222 /***
223 * Generate a hex representation of an MD5 checksum on the emailbody
224 * @param emailBody
225 * @return A hex representation of the text
226 * @throws NoSuchAlgorithmException
227 */
228 private String generateKeyValue(String emailBody) throws NoSuchAlgorithmException {
229
230 byte[] digArray = MessageDigest.getInstance("MD5").digest(emailBody.getBytes());
231 StringBuffer digest = new StringBuffer();
232 for (int i = 0; i < digArray.length; i++) {
233 digest.append(Integer.toString(digArray[i], Character.MAX_RADIX).toUpperCase(Locale.US));
234 }
235 return digest.toString();
236 }
237
238 /***
239 * Parse the mbox file.
240 * @param ins The random access file to load. Note that the file may or may not start at offset 0 in the file
241 * @param messAct The action to take when a message is found
242 */
243 private MimeMessage parseMboxFile(RandomAccessFile ins, MessageAction messAct) {
244 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
245 StringBuffer logBuffer =
246 new StringBuffer(128)
247 .append(this.getClass().getName())
248 .append(" Start parsing ")
249 .append(mboxFile);
250
251 getLogger().debug(logBuffer.toString());
252 }
253 try {
254
255 Perl5Compiler sepMatchCompiler = new Perl5Compiler();
256 Pattern sepMatchPattern = sepMatchCompiler.compile("^From (.*) (.*):(.*):(.*)$");
257 Perl5Matcher sepMatch = new Perl5Matcher();
258
259 int c;
260 boolean inMessage = false;
261 StringBuffer messageBuffer = new StringBuffer();
262 String previousMessageSeparator = null;
263 boolean foundSep = false;
264
265 long prevMessageStart = ins.getFilePointer();
266 if (BUFFERING) {
267 String line = null;
268 while ((line = ins.readLine()) != null) {
269 foundSep = sepMatch.contains(line + "\n", sepMatchPattern);
270
271 if (foundSep && inMessage) {
272
273
274
275 MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
276 if (messAct.isComplete()) {
277
278 return endResult;
279 }
280 previousMessageSeparator = line;
281 prevMessageStart = ins.getFilePointer() - line.length();
282 messageBuffer = new StringBuffer();
283 inMessage = true;
284 }
285
286 if (foundSep && !inMessage) {
287 previousMessageSeparator = line.toString();
288 inMessage = true;
289 }
290 if (!foundSep && inMessage) {
291 messageBuffer.append(line).append("\n");
292 }
293 }
294 } else {
295 StringBuffer line = new StringBuffer();
296 while ((c = ins.read()) != -1) {
297 if (c == 10) {
298 foundSep = sepMatch.contains(line.toString(), sepMatchPattern);
299 if (foundSep && inMessage) {
300
301
302
303 MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
304 if (messAct.isComplete()) {
305
306 return endResult;
307 }
308 previousMessageSeparator = line.toString();
309 prevMessageStart = ins.getFilePointer() - line.length();
310 messageBuffer = new StringBuffer();
311 inMessage = true;
312 }
313
314 if (foundSep && inMessage == false) {
315 previousMessageSeparator = line.toString();
316 inMessage = true;
317 }
318 if (!foundSep) {
319 messageBuffer.append(line).append((char) c);
320 }
321 line = new StringBuffer();
322 } else {
323 line.append((char) c);
324 }
325 }
326 }
327
328 if (messageBuffer.length() != 0) {
329
330 return messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
331 }
332 } catch (IOException ioEx) {
333 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, ioEx);
334 } catch (MalformedPatternException e) {
335 getLogger().error("Bad regex passed " + mboxFile, e);
336 } finally {
337 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
338 StringBuffer logBuffer =
339 new StringBuffer(128)
340 .append(this.getClass().getName())
341 .append(" Finished parsing ")
342 .append(mboxFile);
343
344 getLogger().debug(logBuffer.toString());
345 }
346 }
347 return null;
348 }
349
350 /***
351 * Find a given message
352 * This method will first use selectMessage(key) to see if the key/offset combination allows us to skip
353 * parts of the file and only load the message we are interested in
354 *
355 * @param key The key of the message to find
356 */
357 private MimeMessage findMessage(String key) {
358 MimeMessage foundMessage = null;
359
360
361 foundMessage = selectMessage(key);
362 if (foundMessage == null) {
363
364
365
366
367 mList = null;
368 loadKeys();
369 foundMessage = selectMessage(key);
370 }
371 return foundMessage;
372 }
373
374 /***
375 * Quickly find a message by using the stored message offsets
376 * @param key The key of the message to find
377 */
378 private MimeMessage selectMessage(final String key) {
379 MimeMessage foundMessage = null;
380
381 if (mList == null || !mList.containsKey(key)) {
382
383 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
384 StringBuffer logBuffer =
385 new StringBuffer(128)
386 .append(this.getClass().getName())
387 .append(" mList - key not found ")
388 .append(mboxFile);
389
390 getLogger().debug(logBuffer.toString());
391 }
392 return foundMessage;
393 }
394 long messageStart = ((Long) mList.get(key)).longValue();
395 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
396 StringBuffer logBuffer =
397 new StringBuffer(128)
398 .append(this.getClass().getName())
399 .append(" Load message starting at offset ")
400 .append(messageStart)
401 .append(" from file ")
402 .append(mboxFile);
403
404 getLogger().debug(logBuffer.toString());
405 }
406
407 RandomAccessFile ins = null;
408 try {
409 ins = new RandomAccessFile(mboxFile, "r");
410 if (messageStart != 0) {
411 ins.seek(messageStart - 1);
412 }
413 MessageAction op = new MessageAction() {
414 public boolean isComplete() { return true; }
415 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
416 try {
417 if (key.equals(generateKeyValue(bodyText))) {
418 getLogger().debug(this.getClass().getName() + " Located message. Returning MIME message");
419 return convertTextToMimeMessage(bodyText);
420 }
421 } catch (NoSuchAlgorithmException e) {
422 getLogger().error("MD5 not supported! ",e);
423 }
424 return null;
425 }
426 };
427 foundMessage = this.parseMboxFile(ins, op);
428 } catch (FileNotFoundException e) {
429 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
430 } catch (IOException e) {
431 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
432 } finally {
433 if (foundMessage == null) {
434 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
435 StringBuffer logBuffer =
436 new StringBuffer(128)
437 .append(this.getClass().getName())
438 .append(" select - message not found ")
439 .append(mboxFile);
440
441 getLogger().debug(logBuffer.toString());
442 }
443 }
444 if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
445 }
446 return foundMessage;
447 }
448
449 /***
450 * Load the message keys and file pointer offsets from disk
451 */
452 private synchronized void loadKeys() {
453 if (mList!=null) {
454 return;
455 }
456 RandomAccessFile ins = null;
457 try {
458 ins = new RandomAccessFile(mboxFile, "r");
459 long initialCapacity = (ins.length() > MLISTPRESIZEFACTOR ? ins.length() /MLISTPRESIZEFACTOR : 0);
460 if (initialCapacity < DEFAULTMLISTCAPACITY ) {
461 initialCapacity = DEFAULTMLISTCAPACITY;
462 }
463 if (initialCapacity > Integer.MAX_VALUE) {
464 initialCapacity = Integer.MAX_VALUE - 1;
465 }
466 this.mList = new Hashtable((int)initialCapacity);
467 this.parseMboxFile(ins, new MessageAction() {
468 public boolean isComplete() { return false; }
469 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
470 try {
471 String key = generateKeyValue(bodyText);
472 mList.put(key, new Long(messageStart));
473 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
474 getLogger().debug(this.getClass().getName() + " Key " + key + " at " + messageStart);
475 }
476
477 } catch (NoSuchAlgorithmException e) {
478 getLogger().error("MD5 not supported! ",e);
479 }
480 return null;
481 }
482 });
483
484 } catch (FileNotFoundException e) {
485 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
486 this.mList = new Hashtable((int)DEFAULTMLISTCAPACITY);
487 } catch (IOException e) {
488 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
489 } finally {
490 if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
491 }
492 }
493
494
495 /***
496 * Store the given email in the current mbox file
497 * @param mc The mail to store
498 */
499 public void store(Mail mc) {
500
501 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
502 StringBuffer logBuffer =
503 new StringBuffer(128)
504 .append(this.getClass().getName())
505 .append(" Will store message to file ")
506 .append(mboxFile);
507
508 getLogger().debug(logBuffer.toString());
509 }
510 this.mList = null;
511
512 String fromHeader = null;
513 String message = null;
514 try {
515 message = getRawMessage(mc.getMessage());
516
517 if (mc.getMessage().getFrom() == null) {
518 fromHeader = "From " + dy.format(Calendar.getInstance().getTime());
519 } else {
520 fromHeader = "From " + mc.getMessage().getFrom()[0] + " " + dy.format(Calendar.getInstance().getTime());
521 }
522
523 } catch (IOException e) {
524 getLogger().error("Unable to parse mime message for " + mboxFile, e);
525 } catch (MessagingException e) {
526 getLogger().error("Unable to parse mime message for " + mboxFile, e);
527 }
528
529 RandomAccessFile saveFile = null;
530 try {
531 saveFile = new RandomAccessFile(mboxFile, "rw");
532 saveFile.seek(saveFile.length());
533 saveFile.writeBytes((fromHeader + "\n"));
534 saveFile.writeBytes((message + "\n"));
535 saveFile.close();
536
537 } catch (FileNotFoundException e) {
538 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
539 } catch (IOException e) {
540 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
541 }
542 }
543
544 /***
545 * Return the list of the current messages' keys
546 * @return A list of the keys of the emails currently loaded
547 */
548 public Iterator list() {
549 loadKeys();
550
551 if (mList.keySet().isEmpty() == false) {
552
553
554
555 findMessage((String) mList.keySet().iterator().next());
556 }
557 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
558 StringBuffer logBuffer =
559 new StringBuffer(128)
560 .append(this.getClass().getName())
561 .append(" ")
562 .append(mList.size())
563 .append(" keys to be iterated over.");
564
565 getLogger().debug(logBuffer.toString());
566 }
567 return mList.keySet().iterator();
568 }
569
570 /***
571 * Get a message from the backing store (disk)
572 * @param key
573 * @return The mail found from the key. Returns null if the key is not found
574 */
575 public Mail retrieve(String key) {
576
577 loadKeys();
578 MailImpl res = null;
579 try {
580 MimeMessage foundMessage = findMessage(key);
581 if (foundMessage == null) {
582 getLogger().error("found message is null!");
583 return null;
584 }
585 res = new MailImpl(foundMessage);
586 res.setName(key);
587 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
588 StringBuffer logBuffer =
589 new StringBuffer(128)
590 .append(this.getClass().getName())
591 .append(" Retrieving entry for key ")
592 .append(key);
593
594 getLogger().debug(logBuffer.toString());
595 }
596 } catch (MessagingException e) {
597 getLogger().error("Unable to parse mime message for " + mboxFile + "\n" + e.getMessage(), e);
598 }
599 return res;
600 }
601
602 /***
603 * Remove an existing message
604 * @param mail
605 */
606 public void remove(Mail mail) {
607 ArrayList remArray = new ArrayList();
608 remArray.add(mail);
609 remove(remArray);
610 }
611
612 /***
613 * Attempt to get a lock on the mbox by creating
614 * the file mboxname.lock
615 * @throws Exception
616 */
617 private void lockMBox() throws Exception {
618
619 String lockFileName = mboxFile + LOCKEXT;
620 int sleepCount = 0;
621 File mBoxLock = new File(lockFileName);
622 if (!mBoxLock.createNewFile()) {
623
624
625 while (!mBoxLock.createNewFile() && sleepCount < MAXSLEEPTIMES) {
626 try {
627 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
628 StringBuffer logBuffer =
629 new StringBuffer(128)
630 .append(this.getClass().getName())
631 .append(" Waiting for lock on file ")
632 .append(mboxFile);
633
634 getLogger().debug(logBuffer.toString());
635 }
636
637 Thread.sleep(LOCKSLEEPDELAY);
638 sleepCount++;
639 } catch (InterruptedException e) {
640 getLogger().error("File lock wait for " + mboxFile + " interrupted!",e);
641
642 }
643 }
644 if (sleepCount >= MAXSLEEPTIMES) {
645 throw new Exception("Unable to get lock on file " + mboxFile);
646 }
647 }
648 }
649
650 /***
651 * Unlock a previously locked mbox file
652 */
653 private void unlockMBox() {
654
655 String lockFileName = mboxFile + LOCKEXT;
656 File mBoxLock = new File(lockFileName);
657 if (!mBoxLock.delete()) {
658 StringBuffer logBuffer =
659 new StringBuffer(128)
660 .append(this.getClass().getName())
661 .append(" Failed to delete lock file ")
662 .append(lockFileName);
663 getLogger().error(logBuffer.toString());
664 }
665 }
666
667
668
669 /***
670 * Remove a list of messages from disk
671 * The collection is simply a list of mails to delete
672 * @param mails
673 */
674 public void remove(final Collection mails)
675 {
676 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
677 StringBuffer logBuffer =
678 new StringBuffer(128)
679 .append(this.getClass().getName())
680 .append(" Removing entry for key ")
681 .append(mails);
682
683 getLogger().debug(logBuffer.toString());
684 }
685
686
687
688
689 try {
690 RandomAccessFile ins = new RandomAccessFile(mboxFile, "r");
691 final RandomAccessFile outputFile = new RandomAccessFile(mboxFile + WORKEXT, "rw");
692 parseMboxFile(ins, new MessageAction() {
693 public boolean isComplete() { return false; }
694 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
695
696 try {
697 String currentKey=generateKeyValue(bodyText);
698 boolean foundKey=false;
699 Iterator mailList = mails.iterator();
700 String key;
701 while (mailList.hasNext()) {
702
703 key = ((Mail)mailList.next()).getName();
704 if (key.equals(currentKey)) {
705
706 foundKey = true;
707 break;
708 }
709 }
710 if (foundKey == false)
711 {
712
713 outputFile.writeBytes(messageSeparator + "\n");
714 outputFile.writeBytes(bodyText);
715
716 }
717 } catch (NoSuchAlgorithmException e) {
718 getLogger().error("MD5 not supported! ",e);
719 } catch (IOException e) {
720 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
721 }
722 return null;
723 }
724 });
725 ins.close();
726 outputFile.close();
727
728 File mbox = new File(mboxFile);
729 mbox.delete();
730
731 mbox = new File(mboxFile + WORKEXT);
732 if (!mbox.renameTo(new File(mboxFile)))
733 {
734 System.out.println("Failed to rename file!");
735 }
736
737
738 Iterator mailList = mails.iterator();
739 String key;
740 while (mailList.hasNext()) {
741
742 key = ((Mail)mailList.next()).getName();
743 mList.remove(key);
744 }
745
746
747 } catch (FileNotFoundException e) {
748 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
749 } catch (IOException e) {
750 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
751 }
752 }
753
754 /***
755 * Remove a mail from the mbox file
756 * @param key The key of the mail to delete
757 */
758 public void remove(String key) {
759 loadKeys();
760 try {
761 lockMBox();
762 } catch (Exception e) {
763 getLogger().error("Lock failed!",e);
764 return;
765 }
766 ArrayList keys = new ArrayList();
767 keys.add(retrieve(key));
768
769 this.remove(keys);
770 unlockMBox();
771 }
772
773 /***
774 * Not implemented
775 * @param key
776 * @return
777 */
778 public boolean lock(String key) {
779 return false;
780 }
781
782 /***
783 * Not implemented
784 * @param key
785 * @return
786 */
787 public boolean unlock(String key) {
788 return false;
789 }
790
791
792 /***
793 * @see org.apache.avalon.framework.service.Serviceable#compose(ServiceManager )
794 */
795 public void service( final ServiceManager componentManager )
796 throws ServiceException {
797 }
798
799 /***
800 * Configure the component
801 * @param conf
802 * @throws ConfigurationException
803 */
804 public void configure(Configuration conf) throws ConfigurationException {
805 String destination;
806 this.mList = null;
807 BUFFERING = conf.getAttributeAsBoolean("BUFFERING", true);
808 destination = conf.getAttribute("destinationURL");
809 if (destination.charAt(destination.length() - 1) == '/') {
810
811 mboxFile = destination.substring("mbox://".length(), destination.lastIndexOf("/"));
812 } else {
813 mboxFile = destination.substring("mbox://".length());
814 }
815
816 if (getLogger().isDebugEnabled()) {
817 getLogger().debug("MBoxMailRepository.destinationURL: " + destination);
818 }
819
820 String checkType = conf.getAttribute("type");
821 if (!(checkType.equals("MAIL") || checkType.equals("SPOOL"))) {
822 String exceptionString = "Attempt to configure MboxMailRepository as " + checkType;
823 if (getLogger().isWarnEnabled()) {
824 getLogger().warn(exceptionString);
825 }
826 throw new ConfigurationException(exceptionString);
827 }
828 }
829
830
831 /***
832 * Initialise the component
833 * @throws Exception
834 */
835 public void initialize() throws Exception {
836 }
837
838
839 public static void main(String[] args) {
840
841 MBoxMailRepository mbx = new MBoxMailRepository();
842 mbx.mboxFile = "C://java//test//1998-05.txt";
843 Iterator mList = mbx.list();
844 while (mList.hasNext()) {
845
846
847
848
849
850
851
852
853
854
855
856
857 }
858
859
860
861
862
863
864
865
866
867 }
868 }