1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
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 package org.apache.james.mailrepository;
45
46 import org.apache.avalon.framework.activity.Initializable;
47 import org.apache.avalon.framework.service.ServiceException;
48 import org.apache.avalon.framework.service.ServiceManager;
49 import org.apache.avalon.framework.service.Serviceable;
50 import org.apache.avalon.framework.configuration.Configurable;
51 import org.apache.avalon.framework.configuration.Configuration;
52 import org.apache.avalon.framework.configuration.ConfigurationException;
53 import org.apache.avalon.framework.logger.AbstractLogEnabled;
54 import org.apache.james.core.MailImpl;
55 import org.apache.james.services.MailRepository;
56 import org.apache.mailet.Mail;
57 import org.apache.oro.text.regex.MalformedPatternException;
58 import org.apache.oro.text.regex.Perl5Compiler;
59 import org.apache.oro.text.regex.Pattern;
60 import org.apache.oro.text.regex.Perl5Matcher;
61
62 import javax.mail.MessagingException;
63 import javax.mail.Session;
64 import javax.mail.internet.MimeMessage;
65
66 import java.io.ByteArrayInputStream;
67 import java.io.ByteArrayOutputStream;
68 import java.io.File;
69 import java.io.FileNotFoundException;
70 import java.io.IOException;
71 import java.io.RandomAccessFile;
72 import java.security.NoSuchAlgorithmException;
73 import java.security.MessageDigest;
74 import java.text.SimpleDateFormat;
75 import java.util.ArrayList;
76 import java.util.Calendar;
77 import java.util.Collection;
78 import java.util.Hashtable;
79 import java.util.Iterator;
80 import java.util.Locale;
81 import java.util.Properties;
82 import java.util.Vector;
83
84 /***
85 * Implementation of a MailRepository using UNIX mbox files.
86 *
87 * <p>Requires a configuration element in the .conf.xml file of the form:
88 * <br><repository destinationURL="mbox://<directory>"
89 * <br> type="MAIL"
90 * <br></directory> is where the individual mbox files are read from/written to
91 * <br>Type can ONLY be MAIL (SPOOL is NOT supported)
92 *
93 * <p>Requires a logger called MailRepository.
94 *
95 * <p> Implementation notes:
96 * <p>
97 * This class keeps an internal store of the mbox file
98 * When the internal mbox file is updated (added/deleted)
99 * then the file will be re-read from disk and then written back.
100 * This is a bit inefficent but means that the file on disk
101 * should be correct.
102 * <p>
103 * The mbox store is mainly meant to be used as a one-way street.
104 * Storing new emails is very fast (append to file) whereas reading them (via POP3) is
105 * slower (read from disk and parse).
106 * Therefore this implementation is best suited to people who wish to use the mbox format
107 * for taking data out of James and into something else (IMAP server or mail list displayer)
108 *
109 * @version CVS $Revision: 454176 $
110 */
111
112
113 public class MBoxMailRepository
114 extends AbstractLogEnabled
115 implements MailRepository, Serviceable, Configurable, Initializable {
116
117
118 static final SimpleDateFormat dy = new SimpleDateFormat("EE MMM dd HH:mm:ss yyyy", Locale.US);
119 static final String LOCKEXT = ".lock";
120 static final String WORKEXT = ".work";
121 static final int LOCKSLEEPDELAY = 2000;
122 static final int MAXSLEEPTIMES = 100;
123 static final long MLISTPRESIZEFACTOR = 10 * 1024;
124 static final long DEFAULTMLISTCAPACITY = 20;
125
126 /***
127 * Whether line buffering is turned used.
128 */
129 private static boolean BUFFERING = true;
130
131 /***
132 * Whether 'deep debugging' is turned on.
133 */
134 private static final boolean DEEP_DEBUG = true;
135
136 /***
137 * The internal list of the emails
138 * The key is an adapted MD5 checksum of the mail
139 */
140 private Hashtable mList = null;
141 /***
142 * The filename to read & write the mbox from/to
143 */
144 private String mboxFile;
145
146 /***
147 * A callback used when a message is read from the mbox file
148 */
149 public interface MessageAction {
150 public boolean isComplete();
151 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart);
152 }
153
154
155 /***
156 * Convert a MimeMessage into raw text
157 * @param mc The mime message to convert
158 * @return A string representation of the mime message
159 * @throws IOException
160 * @throws MessagingException
161 */
162 private String getRawMessage(MimeMessage mc) throws IOException, MessagingException {
163
164 ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
165 mc.writeTo(rawMessage);
166 return rawMessage.toString();
167 }
168
169 /***
170 * Parse a text block as an email and convert it into a mime message
171 * @param emailBody The headers and body of an email. This will be parsed into a mime message and stored
172 */
173 private MimeMessage convertTextToMimeMessage(String emailBody) {
174
175 MimeMessage mimeMessage = null;
176
177 ByteArrayInputStream mb = new ByteArrayInputStream(emailBody.getBytes());
178 Properties props = System.getProperties();
179 Session session = Session.getDefaultInstance(props);
180 try {
181 mimeMessage = new MimeMessage(session, mb);
182
183
184 } catch (MessagingException e) {
185 getLogger().error("Unable to parse mime message!", e);
186 }
187
188 if (mimeMessage == null && getLogger().isDebugEnabled()) {
189 StringBuffer logBuffer =
190 new StringBuffer(128)
191 .append(this.getClass().getName())
192 .append(" Mime message is null");
193 getLogger().debug(logBuffer.toString());
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218 return mimeMessage;
219 }
220
221 /***
222 * Generate a hex representation of an MD5 checksum on the emailbody
223 * @param emailBody
224 * @return A hex representation of the text
225 * @throws NoSuchAlgorithmException
226 */
227 private String generateKeyValue(String emailBody) throws NoSuchAlgorithmException {
228
229 byte[] digArray = MessageDigest.getInstance("MD5").digest(emailBody.getBytes());
230 StringBuffer digest = new StringBuffer();
231 for (int i = 0; i < digArray.length; i++) {
232 digest.append(Integer.toString(digArray[i], Character.MAX_RADIX).toUpperCase(Locale.US));
233 }
234 return digest.toString();
235 }
236
237 /***
238 * Parse the mbox file.
239 * @param ins The random access file to load. Note that the file may or may not start at offset 0 in the file
240 * @param messAct The action to take when a message is found
241 */
242 private MimeMessage parseMboxFile(RandomAccessFile ins, MessageAction messAct) {
243 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
244 StringBuffer logBuffer =
245 new StringBuffer(128)
246 .append(this.getClass().getName())
247 .append(" Start parsing ")
248 .append(mboxFile);
249
250 getLogger().debug(logBuffer.toString());
251 }
252 try {
253
254 Perl5Compiler sepMatchCompiler = new Perl5Compiler();
255 Pattern sepMatchPattern = sepMatchCompiler.compile("^From (.*) (.*):(.*):(.*)$");
256 Perl5Matcher sepMatch = new Perl5Matcher();
257
258 int c;
259 boolean inMessage = false;
260 StringBuffer messageBuffer = new StringBuffer();
261 String previousMessageSeparator = null;
262 boolean foundSep = false;
263
264 long prevMessageStart = ins.getFilePointer();
265 if (BUFFERING) {
266 String line = null;
267 while ((line = ins.readLine()) != null) {
268 foundSep = sepMatch.contains(line + "\n", sepMatchPattern);
269
270 if (foundSep && inMessage) {
271
272
273
274 MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
275 if (messAct.isComplete()) {
276
277 return endResult;
278 }
279 previousMessageSeparator = line;
280 prevMessageStart = ins.getFilePointer() - line.length();
281 messageBuffer = new StringBuffer();
282 inMessage = true;
283 }
284
285 if (foundSep && !inMessage) {
286 previousMessageSeparator = line.toString();
287 inMessage = true;
288 }
289 if (!foundSep && inMessage) {
290 messageBuffer.append(line).append("\n");
291 }
292 }
293 } else {
294 StringBuffer line = new StringBuffer();
295 while ((c = ins.read()) != -1) {
296 if (c == 10) {
297 foundSep = sepMatch.contains(line.toString(), sepMatchPattern);
298 if (foundSep && inMessage) {
299
300
301
302 MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
303 if (messAct.isComplete()) {
304
305 return endResult;
306 }
307 previousMessageSeparator = line.toString();
308 prevMessageStart = ins.getFilePointer() - line.length();
309 messageBuffer = new StringBuffer();
310 inMessage = true;
311 }
312
313 if (foundSep && inMessage == false) {
314 previousMessageSeparator = line.toString();
315 inMessage = true;
316 }
317 if (!foundSep) {
318 messageBuffer.append(line).append((char) c);
319 }
320 line = new StringBuffer();
321 } else {
322 line.append((char) c);
323 }
324 }
325 }
326
327 if (messageBuffer.length() != 0) {
328
329 return messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);
330 }
331 } catch (IOException ioEx) {
332 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, ioEx);
333 } catch (MalformedPatternException e) {
334 getLogger().error("Bad regex passed " + mboxFile, e);
335 } finally {
336 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
337 StringBuffer logBuffer =
338 new StringBuffer(128)
339 .append(this.getClass().getName())
340 .append(" Finished parsing ")
341 .append(mboxFile);
342
343 getLogger().debug(logBuffer.toString());
344 }
345 }
346 return null;
347 }
348
349 /***
350 * Find a given message
351 * This method will first use selectMessage(key) to see if the key/offset combination allows us to skip
352 * parts of the file and only load the message we are interested in
353 *
354 * @param key The key of the message to find
355 */
356 private MimeMessage findMessage(String key) {
357 MimeMessage foundMessage = null;
358
359
360 foundMessage = selectMessage(key);
361 if (foundMessage == null) {
362
363
364
365
366 mList = null;
367 loadKeys();
368 foundMessage = selectMessage(key);
369 }
370 return foundMessage;
371 }
372
373 /***
374 * Quickly find a message by using the stored message offsets
375 * @param key The key of the message to find
376 */
377 private MimeMessage selectMessage(final String key) {
378 MimeMessage foundMessage = null;
379
380 if (mList == null || !mList.containsKey(key)) {
381
382 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
383 StringBuffer logBuffer =
384 new StringBuffer(128)
385 .append(this.getClass().getName())
386 .append(" mList - key not found ")
387 .append(mboxFile);
388
389 getLogger().debug(logBuffer.toString());
390 }
391 return foundMessage;
392 }
393 long messageStart = ((Long) mList.get(key)).longValue();
394 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
395 StringBuffer logBuffer =
396 new StringBuffer(128)
397 .append(this.getClass().getName())
398 .append(" Load message starting at offset ")
399 .append(messageStart)
400 .append(" from file ")
401 .append(mboxFile);
402
403 getLogger().debug(logBuffer.toString());
404 }
405
406 RandomAccessFile ins = null;
407 try {
408 ins = new RandomAccessFile(mboxFile, "r");
409 if (messageStart != 0) {
410 ins.seek(messageStart - 1);
411 }
412 MessageAction op = new MessageAction() {
413 public boolean isComplete() { return true; }
414 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
415 try {
416 if (key.equals(generateKeyValue(bodyText))) {
417 getLogger().debug(this.getClass().getName() + " Located message. Returning MIME message");
418 return convertTextToMimeMessage(bodyText);
419 }
420 } catch (NoSuchAlgorithmException e) {
421 getLogger().error("MD5 not supported! ",e);
422 }
423 return null;
424 }
425 };
426 foundMessage = this.parseMboxFile(ins, op);
427 } catch (FileNotFoundException e) {
428 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
429 } catch (IOException e) {
430 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
431 } finally {
432 if (foundMessage == null) {
433 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
434 StringBuffer logBuffer =
435 new StringBuffer(128)
436 .append(this.getClass().getName())
437 .append(" select - message not found ")
438 .append(mboxFile);
439
440 getLogger().debug(logBuffer.toString());
441 }
442 }
443 if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
444 }
445 return foundMessage;
446 }
447
448 /***
449 * Load the message keys and file pointer offsets from disk
450 */
451 private synchronized void loadKeys() {
452 if (mList!=null) {
453 return;
454 }
455 RandomAccessFile ins = null;
456 try {
457 ins = new RandomAccessFile(mboxFile, "r");
458 long initialCapacity = (ins.length() > MLISTPRESIZEFACTOR ? ins.length() /MLISTPRESIZEFACTOR : 0);
459 if (initialCapacity < DEFAULTMLISTCAPACITY ) {
460 initialCapacity = DEFAULTMLISTCAPACITY;
461 }
462 if (initialCapacity > Integer.MAX_VALUE) {
463 initialCapacity = Integer.MAX_VALUE - 1;
464 }
465 this.mList = new Hashtable((int)initialCapacity);
466 this.parseMboxFile(ins, new MessageAction() {
467 public boolean isComplete() { return false; }
468 public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart) {
469 try {
470 String key = generateKeyValue(bodyText);
471 mList.put(key, new Long(messageStart));
472 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
473 getLogger().debug(this.getClass().getName() + " Key " + key + " at " + messageStart);
474 }
475
476 } catch (NoSuchAlgorithmException e) {
477 getLogger().error("MD5 not supported! ",e);
478 }
479 return null;
480 }
481 });
482
483 } catch (FileNotFoundException e) {
484 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
485 this.mList = new Hashtable((int)DEFAULTMLISTCAPACITY);
486 } catch (IOException e) {
487 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
488 } finally {
489 if (ins != null) try { ins.close(); } catch (IOException e) { getLogger().error("Unable to close file (General I/O problem) " + mboxFile, e); }
490 }
491 }
492
493
494 /***
495 * Store the given email in the current mbox file
496 * @param mc The mail to store
497 */
498 public void store(Mail mc) {
499
500 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
501 StringBuffer logBuffer =
502 new StringBuffer(128)
503 .append(this.getClass().getName())
504 .append(" Will store message to file ")
505 .append(mboxFile);
506
507 getLogger().debug(logBuffer.toString());
508 }
509 this.mList = null;
510
511 String fromHeader = null;
512 String message = null;
513 try {
514 message = getRawMessage(mc.getMessage());
515
516 if (mc.getMessage().getFrom() == null) {
517 fromHeader = "From " + dy.format(Calendar.getInstance().getTime());
518 } else {
519 fromHeader = "From " + mc.getMessage().getFrom()[0] + " " + dy.format(Calendar.getInstance().getTime());
520 }
521
522 } catch (IOException e) {
523 getLogger().error("Unable to parse mime message for " + mboxFile, e);
524 } catch (MessagingException e) {
525 getLogger().error("Unable to parse mime message for " + mboxFile, e);
526 }
527
528 RandomAccessFile saveFile = null;
529 try {
530 saveFile = new RandomAccessFile(mboxFile, "rw");
531 saveFile.seek(saveFile.length());
532 saveFile.writeBytes((fromHeader + "\n"));
533 saveFile.writeBytes((message + "\n"));
534 saveFile.close();
535
536 } catch (FileNotFoundException e) {
537 getLogger().error("Unable to save(open) file (File not found) " + mboxFile, e);
538 } catch (IOException e) {
539 getLogger().error("Unable to write file (General I/O problem) " + mboxFile, e);
540 }
541 }
542
543 /***
544 * Return the list of the current messages' keys
545 * @return A list of the keys of the emails currently loaded
546 */
547 public Iterator list() {
548 loadKeys();
549
550 if (mList.keySet().isEmpty() == false) {
551
552
553
554 findMessage((String) mList.keySet().iterator().next());
555 }
556 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
557 StringBuffer logBuffer =
558 new StringBuffer(128)
559 .append(this.getClass().getName())
560 .append(" ")
561 .append(mList.size())
562 .append(" keys to be iterated over.");
563
564 getLogger().debug(logBuffer.toString());
565 }
566 return mList.keySet().iterator();
567 }
568
569 /***
570 * Get a message from the backing store (disk)
571 * @param key
572 * @return The mail found from the key. Returns null if the key is not found
573 */
574 public Mail retrieve(String key) {
575
576 loadKeys();
577 MailImpl res = null;
578 try {
579 MimeMessage foundMessage = findMessage(key);
580 if (foundMessage == null) {
581 getLogger().error("found message is null!");
582 return null;
583 }
584 res = new MailImpl(foundMessage);
585 res.setName(key);
586 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {
587 StringBuffer logBuffer =
588 new StringBuffer(128)
589 .append(this.getClass().getName())
590 .append(" Retrieving entry for key ")
591 .append(key);
592
593 getLogger().debug(logBuffer.toString());
594 }
595 } catch (MessagingException e) {
596 getLogger().error("Unable to parse mime message for " + mboxFile + "\n" + e.getMessage(), e);
597 }
598 return res;
599 }
600
601 /***
602 * Remove an existing message
603 * @param mail
604 */
605 public void remove(Mail mail) {
606
607 Vector delVec = new Vector();
608 delVec.addElement(mail);
609 remove(delVec);
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(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 }