001: /***
002: * jwma Java WebMail
003: * Copyright (c) 2000-2003 jwma team
004: *
005: * jwma is free software; you can distribute and use this source
006: * under the terms of the BSD-style license received along with
007: * the distribution.
008: ***/package dtw.webmail.model;
009:
010: import java.io.*;
011: import java.util.*;
012: import javax.mail.*;
013:
014: import org.apache.log4j.Logger;
015:
016: //import dtw.webmail.JwmaKernel;
017:
018: /**
019: * Class implementing the <tt>JwmaFolder</tt> model.
020: *
021: * It also implements the <tt>JwmaTrashInfo</tt> and the
022: * <tt>JwmaInboxInfo</tt> models, because both are just
023: * simplified interfaces to a folder.
024: *
025: * @author Dieter Wimberger
026: * @version 0.9.7 07/02/2003
027: */
028: public class JwmaFolderImpl implements JwmaFolder, JwmaTrashInfo,
029: JwmaInboxInfo {
030:
031: //logging
032: private static Logger log = Logger.getLogger(JwmaFolderImpl.class);
033:
034: //associations
035: protected JwmaStoreImpl m_Store;
036: protected Folder m_Folder;
037:
038: //instance attributes
039: protected JwmaFolderList m_Subfolders;
040: protected JwmaMessageInfoListImpl m_MessageInfoList;
041:
042: protected String m_Name;
043: protected String m_Path;
044: protected int m_Type;
045: protected JwmaMessage m_ActualMessage;
046: protected boolean m_OnlineCounting;
047: protected FetchProfile m_DraftProfile;
048:
049: /**
050: * Creates a <tt>JwmaFolderImpl</tt> instance.
051: *
052: * @param f the <tt>javax.mail.Folder</tt> instance to be wrapped.
053: */
054: private JwmaFolderImpl(Folder f) {
055: m_Folder = f;
056: }//constructor
057:
058: /**
059: * Creates a <tt>JwmaFolderImpl</tt> instance.
060: *
061: * @param f the <tt>javax.mail.Folder</tt> instance to be wrapped.
062: */
063: private JwmaFolderImpl(Folder f, JwmaStoreImpl store) {
064: m_Folder = f;
065: m_Store = store;
066: }//constructor
067:
068: /*** Basic info ************************************************************/
069:
070: public String getName() {
071: return m_Name;
072: }//getName
073:
074: /**
075: * Sets this folder's name.
076: *
077: * @param name the name of the folder as <tt>String</tt>.
078: */
079: private void setName(String name) {
080: m_Name = name;
081: }//setName
082:
083: public String getPath() {
084: return m_Path;
085: }//getPath
086:
087: /**
088: * Sets this folder's path.
089: *
090: * @param name the path of the folder as <tt>String</tt>.
091: */
092: private void setPath(String path) {
093: m_Path = path;
094: }//setPath
095:
096: public int getType() {
097: return m_Type;
098: }//getType
099:
100: /**
101: * Sets this folder's type.
102: *
103: * @param type this folder's type as <tt>int</tt>.
104: */
105: private void setType(int type) {
106: m_Type = type;
107: }//setType
108:
109: public boolean isType(int type) {
110: return (m_Type == type);
111: }//isType
112:
113: public boolean isSubscribed() {
114: return m_Folder.isSubscribed();
115: }//isSubscribed
116:
117: public void setSubscribed(boolean b) throws JwmaException {
118: try {
119: m_Folder.setSubscribed(b);
120: } catch (Exception ex) {
121: log.error("setSubscribed()", ex);
122: throw new JwmaException("folder.subscription.failed");
123: }
124: }//setSubscribed
125:
126: /**
127: * Returns this folder's wrapped mail folder instance.
128: *
129: * @return wrapped instance as <tt>javax.mail.Folder</tt>.
130: */
131: public Folder getFolder() {
132: return m_Folder;
133: }//getFolder
134:
135: /**
136: * Tests if this folder returns an online count of the
137: * contained messages.
138: * Online count means that it will request the count
139: * from the JavaMail folder implementation instance, instead of
140: * returning the size of the cached list of messages.
141: *
142: * @return boolean true if online counting, false otherwise.
143: */
144: public boolean isOnlineCounting() {
145: return m_OnlineCounting;
146: }//isOnlineCounting
147:
148: /**
149: * Sets the online counting flag.
150: * This will cause this folder to return the count
151: * of messages as obtained from the JavaMail folder
152: * implementation instance, instead of returning the size
153: * of the cached list of messages.
154: */
155: public void setOnlineCounting(boolean b) {
156: m_OnlineCounting = b;
157: }//setOnlineCounting
158:
159: /*** Subfolders related ****************************************************/
160:
161: /**
162: * Adds a folder to the cached list of subfolders, if
163: * it is a subfolder of this folder.
164: *
165: * @param folder a <tt>JwmaFolderImpl</tt> instance.
166: */
167: public void addIfSubfolder(JwmaFolderImpl folder) {
168: if (isSubfolder(this .getPath(), folder.getPath())) {
169: m_Subfolders.addFolderToList(folder);
170: }
171: }//addIfSubfolder
172:
173: /**
174: * Removes a folder from the cached list of subfolders, if
175: * it is a subfolder of this folder.
176: *
177: * @param path a <tt>String</tt> representing the path of a folder.
178: */
179: public void removeIfSubfolder(String path) {
180: if (isSubfolder(this .getPath(), path)) {
181: m_Subfolders.removeFolderFromList(path);
182: }
183: }//removeIfSubfolder
184:
185: /**
186: * Removes all folder from the cached list of subfolders, if
187: * they are a subfolder of this folder.
188: * This is a convenience method, it iterates over the array and
189: * calls <tt>removeIfSubfolder(String)</tt>
190: *
191: * @param folders a <tt>String[]</tt> containing paths of folders.
192: *
193: * @see #removeIfSubfolder(String)
194: */
195: public void removeIfSubfolder(String[] folders) {
196: for (int i = 0; i < folders.length; i++) {
197: removeIfSubfolder(folders[i]);
198: }
199: }//removeIfSubfolder
200:
201: /**
202: * Tests if a folder is a subfolder of another folder, by using
203: * their respective paths.
204: * A folder is a subfolder if the path starts with the path of
205: * the folder it is tested against.
206: *
207: * @param folder path of a folder as <tt>String</tt>.
208: * @param possiblesubfolder path of a possible subfolder of the folder
209: * as <tt>String</tt>.
210: * @return boolean that is true, if possiblesubfolder is a subfolder
211: * of folder, false otherwise.
212: */
213: public boolean isSubfolder(String folder, String possiblesubfolder) {
214: return possiblesubfolder.startsWith(folder);
215: }//isSubfolder
216:
217: public JwmaFolder[] listSubfolders(int type) {
218: //fetch list with type filter and create array from it
219: return m_Subfolders.createFolderArray(m_Subfolders.sublist(
220: type, JwmaStoreImpl.c_SubscribedOnly));
221: }//listFolders
222:
223: public JwmaFolder[] listSubfolders() {
224: //fetch list with type filter and create array from it
225: return m_Subfolders.createFolderArray(m_Subfolders.sublist(
226: JwmaFolder.TYPE_ALL, JwmaStoreImpl.c_SubscribedOnly));
227: }//listFolders
228:
229: public JwmaFolder[] listSubfolders(int type, boolean subscribed) {
230: String[] excludes = {
231: m_Store.getTrashFolder().getFullName(),
232: m_Store.getDraftFolder().getFullName(),
233: ((m_Store.getReadMailFolder() != null) ? m_Store
234: .getReadMailFolder().getFullName() : ""),
235: ((m_Store.getSentMailFolder() != null) ? m_Store
236: .getSentMailFolder().getFullName() : "") };
237: return m_Subfolders.createFolderArray(m_Subfolders.sublist(
238: type, excludes, subscribed));
239: }//listFolders
240:
241: public boolean hasSubfolders() {
242: if (m_Subfolders != null && m_Subfolders.size() > 0) {
243: return true;
244: } else {
245: return false;
246: }
247: }//hasFolders
248:
249: /*** End subfolder related *************************************************/
250:
251: /*** Messages related ******************************************************/
252:
253: public boolean hasMessages() {
254: if (!isType(TYPE_FOLDER) && getMessageCount() > 0) {
255: return true;
256: } else {
257: return false;
258: }
259: }//hasMessages
260:
261: public int getNewMessageCount() {
262: try {
263: return m_Folder.getNewMessageCount();
264: } catch (MessagingException ex) {
265: return -1;
266: }
267: }//getNewMessageCount
268:
269: public boolean hasNewMessages() {
270: return (getNewMessageCount() > 0);
271: }//hasNewMessages
272:
273: public int getUnreadMessageCount() {
274: try {
275: return m_Folder.getUnreadMessageCount();
276: } catch (MessagingException ex) {
277: return -1;
278: }
279: }//getUnreadMessageCount
280:
281: public boolean hasUnreadMessages() {
282: return (getUnreadMessageCount() > 0);
283: }//hasNewMessages
284:
285: public int getMessageCount() {
286: if (isOnlineCounting()) {
287: try {
288: return m_Folder.getMessageCount();
289: } catch (MessagingException mex) {
290: log.error(mex.getMessage(), mex);
291: //JwmaKernel.getReference().debugLog().writeStackTrace(mex);
292: return 0;
293: }
294: } else {
295: if (m_MessageInfoList != null) {
296: return m_MessageInfoList.size();
297: } else {
298: return 0;
299: }
300: }
301: }//getMessageCount
302:
303: public boolean isEmpty() {
304: return (!hasMessages());
305: }//isEmpty
306:
307: /**
308: * Returns the actual message.
309: * The actual message is a reference to the message wrapper
310: * instance of the message that was requested last.
311: *
312: * @return the <tt>JwmaMessage</tt> instance wrapping the last
313: * requested message.
314: */
315: public JwmaMessage getActualMessage() {
316: return m_ActualMessage;
317: }//getActualMessage
318:
319: /**
320: * Returns the message with the given number from the
321: * mailfolder.
322: *
323: * @return the message with the given number as <tt>javax.mail.Message</tt>.
324: *
325: * @throws <tt>JwmaException</tt> if a message with this number does not exist,
326: * or the message cannot be retrieved from the store.
327: */
328: private Message getMessage(int num) throws JwmaException {
329: try {
330: return m_Folder.getMessage(num);
331: } catch (MessagingException mex) {
332: throw new JwmaException("jwma.folder.getmessage.failed",
333: true).setException(mex);
334: }
335: }//getMessage
336:
337: /**
338: * Returns the numbers of all read messages within
339: * this instance.
340: *
341: * @return array of int's representing the message numbers of
342: * all read messages.
343: * @throws JwmaException if retrieving the numbers from the mailfolder fails.
344: */
345: public int[] getReadMessages() throws JwmaException {
346:
347: int[] readmsg = new int[0];
348:
349: try {
350: m_Folder.open(Folder.READ_ONLY);
351: Message[] messages = m_Folder.getMessages();
352: ArrayList readlist = new ArrayList(messages.length);
353:
354: for (int i = 0; i < messages.length; i++) {
355: if (messages[i].isSet(Flags.Flag.SEEN)) {
356: readlist.add(new Integer(messages[i]
357: .getMessageNumber()));
358: }
359: }
360:
361: readmsg = new int[readlist.size()];
362: int c = 0;
363: for (Iterator iter = readlist.iterator(); iter.hasNext(); c++) {
364: readmsg[c] = ((Integer) iter.next()).intValue();
365: }
366:
367: } catch (MessagingException ex) {
368: //pass it on as JwmaException
369: throw new JwmaException("jwma.folder.readmessages");
370: } finally {
371: //ensure the inbox is closed
372: try {
373: m_Folder.close(false);
374: } catch (MessagingException mex) {
375: //closed anyway regarding to specs
376: }
377: }
378: return readmsg;
379: }//getReadMessages
380:
381: /**
382: * Returns the number of the next message (relative to the actual)
383: * in this folder, observing the actual sorting.
384: * The method returns -1 if the actual message is the last message
385: * in this folder.
386: *
387: * @return the number of the next message as <tt>int</tt> or -1 if
388: * the actual message is the last message in this folder.
389: *
390: */
391: public int getNextMessageNumber() {
392: return m_MessageInfoList.getNextMessageNumber(m_ActualMessage
393: .getMessageNumber());
394: }//getNextMessageNumber
395:
396: /**
397: * Returns the number of the previous message (relative to the actual)
398: * in this folder, observing the actual sorting.
399: * The method returns -1 if the actual message is the first message
400: * in this folder.
401: *
402: * @return the number of the previous message as <tt>int</tt> or -1 if
403: * the actual message is the first message in this folder.
404: *
405: */
406: public int getPreviousMessageNumber() {
407: return m_MessageInfoList
408: .getPreviousMessageNumber(m_ActualMessage
409: .getMessageNumber());
410: }//getPreviousMessageNumber
411:
412: /**
413: * Tests if a message with the given number exists in this folder.
414: *
415: * @return true if it exists, false otherwise.
416: */
417: public boolean checkMessageExistence(int number) {
418: return (number >= 1 && number <= getMessageCount());
419: }//checkMessageExistence
420:
421: /**
422: * Returns a <tt>JwmaMessage</tt> instance that wraps
423: * the mailmessage with the given number.
424: *
425: * @param num the number of the message to be retrieved as <tt>int</tt>.
426: * @return the <tt>JwmaMessage</tt> instance wrapping the retrieved message.
427: * @throws JwmaException if the message does not exist, or
428: * cannot be retrieved from the store.
429: */
430: public JwmaMessage getJwmaMessage(int num) throws JwmaException {
431: try {
432: //we want to change the seen flag if JwmaMessage created
433: m_Folder.open(Folder.READ_WRITE);
434:
435: //get message and create wrapper
436: Message msg = getMessage(num);
437: JwmaMessage message = JwmaDisplayMessage
438: .createJwmaDisplayMessage(msg, m_Store
439: .getPreferences());
440:
441: //set seen flag if not set already
442: if (!msg.isSet(Flags.Flag.SEEN)) {
443: msg.setFlag(Flags.Flag.SEEN, true);
444: }
445: //close without expunge
446: m_Folder.close(false);
447: //store the actual message
448: m_ActualMessage = message;
449:
450: //rebuild the file list
451: return message;
452: } catch (MessagingException mex) {
453: throw new JwmaException("jwma.folder.jwmamessage", true)
454: .setException(mex);
455: } finally {
456: try {
457: //ensure closed the folder
458: if (m_Folder.isOpen()) {
459: m_Folder.close(false);
460: }
461: } catch (MessagingException mesx) {
462: //don't care, the specs say it IS closed anyway
463: }
464: }
465: }//getJwmaMessage
466:
467: public JwmaMessage getDraftMessage(int num) throws JwmaException {
468: //get message and create wrapper
469: try {
470:
471: m_Folder.open(Folder.READ_WRITE);//to ensure message can be changed
472: Message[] msg = { getMessage(num) };
473: if (m_DraftProfile == null) {
474: m_DraftProfile = new FetchProfile();
475: m_DraftProfile.add(FetchProfile.Item.ENVELOPE); //contains the headers
476: m_DraftProfile.add(FetchProfile.Item.FLAGS); //contains the flags;
477: m_DraftProfile.add(FetchProfile.Item.CONTENT_INFO); //contains the content info
478: }
479: m_Folder.fetch(msg, m_DraftProfile);
480: return JwmaComposeMessage.createDraft(msg[0]);
481:
482: } catch (MessagingException ex) {
483: throw new JwmaException("jwma.folder.draftmessage", true)
484: .setException(ex);
485: } finally {
486: try {
487: //ensure closed the folder
488: if (m_Folder.isOpen()) {
489: m_Folder.close(false);
490: }
491: } catch (MessagingException mesx) {
492: //don't care, the specs say it IS closed anyway
493: }
494: }
495:
496: }//getDraftMessage
497:
498: /**
499: * Returns an array of <tt>JwmaMessageInfo[]</tt> listing
500: * the info's of all messages in this folder.
501: * The method actually delegates the job to the associated
502: * <tt>JwmaMessageInfoListImpl</tt> instance.
503: *
504: * @return an array of <tt>JwmaMessageInfo</tt> instances.
505: *
506: * @see dtw.webmail.model.JwmaMessageInfoListImpl#listMessageInfos()
507: */
508: public JwmaMessageInfo[] listMessageInfos() {
509: return m_MessageInfoList.listMessageInfos();
510: }//getMessageInfoList
511:
512: /**
513: * Returns the <tt>JwmaMessageInfoListImpl</tt> instance that
514: * contains a list of stored <tt>JwmaMessageInfoImpl</tt> references
515: * wrapping information about the messages in the wrapped mailfolder.
516: *
517: * @return the list containing the <tt>JwmaMessageInfoImpl</tt> references.
518: */
519: public JwmaMessageInfoListImpl getMessageInfoList() {
520: return m_MessageInfoList;
521: }//getMessageInfoList
522:
523: /**
524: * Deletes the actual message from this folder.
525: *
526: * @return the number of the next message or -1 if there is none.
527: *
528: * @throws JwmaException if it fails to delete the message from the store.
529: */
530: public int deleteActualMessage() throws JwmaException {
531:
532: //remember the next message (or if ther is none)
533: int nextmsgnum = getNextMessageNumber() - 1;
534:
535: //delete message
536: deleteMessage(m_ActualMessage.getMessageNumber());
537:
538: return nextmsgnum;
539: }//deleteActualMessage
540:
541: /**
542: * Deletes the given message from this folder.
543: * Note that this is a convenience method that creates an array with a
544: * single entry, and calls <tt>deleteMessage(int[])</tt>.
545: *
546: * @param number the number of the message to be deleted as <tt>int</tt>.
547: *
548: * @throws JwmaException if it fails to delete the given message.
549: *
550: * @see #deleteMessages(int[])
551: */
552: public void deleteMessage(int number) throws JwmaException {
553: int[] nums = { number };
554: deleteMessages(nums);
555: }//deleteMessage
556:
557: /**
558: * Deletes all messages from this folder.
559: * Note that this is a convenience method that creates an array with a
560: * all message numbers, and calls <tt>deleteMessage(int[])</tt>.
561: * *
562: * @throws JwmaException if it fails to delete any of the messages.
563: *
564: * @see #deleteMessages(int[])
565: */
566: public void deleteAllMessages() throws JwmaException {
567:
568: int[] msgnumbers = new int[getMessageCount()];
569: for (int i = 0; i < getMessageCount(); i++) {
570: msgnumbers[i] = i + 1;
571: }
572: deleteMessages(msgnumbers);
573: }//deleteAllMessages
574:
575: /**
576: * Deletes the messages with the given numbers.
577: *
578: * @param numbers the messages to be deleted as <tt>int[]</tt>.
579: *
580: * @throws JwmaException if it fails to delete any of the given messages.
581: */
582: public void deleteMessages(int[] numbers) throws JwmaException {
583:
584: //dont work with null or empty arrays
585: if (numbers == null || numbers.length == 0) {
586: return;
587: }
588:
589: try {
590:
591: m_Folder.open(Folder.READ_WRITE);
592: Message[] msgs = m_Folder.getMessages(numbers);
593: if (msgs.length != 0) {
594: //if not the trash copy the messages to the trash
595: if (!m_Path.equals(m_Store.getTrashFolder()
596: .getFullName())) {
597: m_Folder.copyMessages(msgs, m_Store
598: .getTrashFolder());
599: }
600: //flag deleted, so when closing with expunge
601: //the messages are erased.
602: m_Folder.setFlags(msgs, new Flags(Flags.Flag.DELETED),
603: true);
604: }
605: //close with expunge
606: m_Folder.close(true);
607: //update messagelist:
608: //deleted and already flagged and now expunged messages
609: m_MessageInfoList.remove(numbers);
610: m_MessageInfoList.removeDeleted();
611: //renumber to reflect standard behaviour
612: m_MessageInfoList.renumber();
613:
614: } catch (MessagingException mex) {
615: throw new JwmaException("jwma.folder.deletemessage.failed",
616: true).setException(mex);
617: } finally {
618: try {
619: //ensure closed the folder
620: if (m_Folder.isOpen()) {
621: m_Folder.close(false);
622: }
623: } catch (MessagingException mesx) {
624: //don't care, the specs say it IS closed anyway
625: }
626: }
627: }//deleteMessages
628:
629: /**
630: * Moves the actual message to the given destination folder.
631: *
632: * @param destfolder the path of the destination folder as <tt>String</tt>.
633: * @return the number of the next message, or -1 if there is none.
634: *
635: * @throws JwmaException if it fails to move the message.
636: *
637: * @see #moveMessage(int,String)
638: */
639: public int moveActualMessage(String destfolder)
640: throws JwmaException {
641:
642: //remember if next messagenum (or if there is one at all)
643: int nextmsgnum = getNextMessageNumber() - 1;
644:
645: //delete message
646: moveMessage(m_ActualMessage.getMessageNumber(), destfolder);
647:
648: return nextmsgnum;
649: }//moveActualMessage
650:
651: /**
652: * Moves the given message to the given destination folder.
653: * Note that this is actually a convenience method. It wraps
654: * the message number into an array and calls
655: * <tt>moveMessages(int[],String)</tt>.
656: *
657: * @param destfolder the path of the destination folder as <tt>String</tt>.
658: *
659: * @return the number of the next message, or -1 if there is none.
660: *
661: * @throws JwmaException if it fails to move the message.
662: *
663: * @see #moveMessages(int[],String)
664: */
665: public void moveMessage(int number, String destfolder)
666: throws JwmaException {
667: int[] nums = { number };
668: moveMessages(nums, destfolder);
669: }//moveMessage
670:
671: /**
672: * Moves the messages with the given numbers to the given destination folder.
673: *
674: * @param numbers the messages to be moved as <tt>int[]</tt>.
675: * @param destfolder the destination folder path as <tt>String</tt>.
676: *
677: * @throws JwmaException if it fails to move if the destination folder does not
678: * exist, or if any of the given messages cannot be moved.
679: */
680: public void moveMessages(int[] numbers, String destfolder)
681: throws JwmaException {
682:
683: //dont work with null or empty arrays
684: if (numbers == null || numbers.length == 0
685: || destfolder == null || destfolder.length() == 0) {
686: return;
687: }
688: //JwmaKernel.getReference().debugLog().write("Moving msgs to->"+destfolder+"<-");
689: try {
690: if (!m_Store.checkFolderExistence(destfolder)) {
691: throw new JwmaException(
692: "jwma.folder.movemessage.destination.missing",
693: true);
694: }
695: Folder dest = m_Store.getFolder(destfolder);
696: //check destination type
697: if (dest.getType() == JwmaFolder.TYPE_FOLDER) {
698: throw new JwmaException(
699: "jwma.folder.movemessage.destination.foul",
700: true);
701: }
702: //Note that apidocs state that only source
703: //has to be opened
704: m_Folder.open(Folder.READ_WRITE);
705: //prepare messages
706: Message[] msgs = m_Folder.getMessages(numbers);
707: if (msgs.length != 0) {
708: m_Folder.copyMessages(msgs, dest);
709: m_Folder.setFlags(msgs, new Flags(Flags.Flag.DELETED),
710: true);
711: }
712: m_Folder.close(true);
713: //update messagelist:
714: //deleted and already flagged and now expunged messages
715: m_MessageInfoList.remove(numbers);
716: m_MessageInfoList.removeDeleted();
717: m_MessageInfoList.renumber();
718: } catch (MessagingException mex) {
719: throw new JwmaException("jwma.folder.movemessage.failed",
720: true).setException(mex);
721: } finally {
722: try {
723: //ensure closed the folder
724: if (m_Folder.isOpen()) {
725: m_Folder.close(false);
726: }
727: } catch (MessagingException mesx) {
728: //don't care, the specs say it IS closed anyway
729: }
730: }
731: }//moveMessages
732:
733: /*** End Messages related ******************************************************/
734:
735: /*** MessageParts related ******************************************************/
736:
737: /**
738: * Writes the given message part from the given message to the given
739: * output stream.
740: *
741: * @param part the part to be written to the output stream.
742: * @param out the <tt>OutputStream</tt> to be written to.
743: *
744: * @throws IOException if an I/O related error occurs.
745: * @throws JwmaException if the message part does not exist, or
746: * cannot be retrieved from the message.
747: */
748: public void writeMessagePart(Part part, OutputStream out)
749: throws IOException, JwmaException {
750:
751: try {
752: m_Folder.open(Folder.READ_ONLY);
753:
754: InputStream in = part.getInputStream();
755:
756: int i;
757: while ((i = in.read()) != -1) {
758: //this is not very efficient, should
759: //write in blocks (byte[]'s)
760: out.write(i);
761: }
762: out.flush();
763:
764: } catch (MessagingException mex) {
765: throw new JwmaException("message.displaypart.failed")
766: .setException(mex);
767: } finally {
768: try {
769: if (m_Folder.isOpen()) {
770: m_Folder.close(false);
771: }
772: } catch (MessagingException ex) {
773: log.error(ex.getMessage(), ex);
774: //JwmaKernel.getReference().debugLog().writeStackTrace(ex);
775: }
776: }
777: }//writeMessagePart
778:
779: /*** End MessageParts related ******************************************************/
780:
781: /**
782: * Tests if this folder instance equals a given object.
783: * Overrides the superclass behaviour to compare the folder's
784: * paths in case the given object is a JwmaFolderImpl.
785: *
786: * @param o the object to compare this folder with.
787: *
788: * @return true if the paths are equal, false otherwise, or when the
789: * object is not an instance of <tt>JwmaFolderImpl</tt>.
790: */
791: public boolean equals(Object o) {
792: if (o instanceof JwmaFolderImpl) {
793: return this .getPath()
794: .equals(((JwmaFolderImpl) o).getPath());
795: } else {
796: return false;
797: }
798: }//equals
799:
800: /**
801: * Prepares this folder instance.
802: * This method fills in values from the wrapped mailfolder instance
803: * and creates the cached subfolder list and the cached messages list.
804: *
805: * @throws JwmaException if it fails to retrieve values from the wrapped instance, or
806: * if it fails to create the subfolder list.
807: */
808: public void prepare() throws JwmaException {
809: try {
810: //set basic data
811: m_Name = m_Folder.getName();
812: m_Path = m_Folder.getFullName();
813: m_Type = m_Folder.getType();
814:
815: //create folder list
816: m_Subfolders = JwmaFolderList.createSubfolderList(m_Folder);
817: if (isType(JwmaFolder.TYPE_MAILBOX)
818: || isType(JwmaFolder.TYPE_MIXED)) {
819: //create m_MessageInfoList, or set null
820: m_MessageInfoList = JwmaMessageInfoListImpl
821: .createJwmaMessageInfoListImpl(m_Folder);
822: }
823: } catch (MessagingException mex) {
824: throw new JwmaException("jwma.folder.failedcreation", true)
825: .setException(mex);
826: }
827: }//prepare
828:
829: /**
830: * Updates this <tt>JwmaFolderImpl</tt> instance by setting the store instance
831: * reference and calling <tt>update()</tt>.
832: * This method can be used on a primarily lightweight created folder, to get it fully
833: * prepared for extended use.
834: *
835: * @param store the reference to the store this folder belongs to.
836: *
837: * @throws JwmaException if the <tt>update()</tt> method fails.
838: *
839: * @see #prepare()
840: */
841: public void update(JwmaStoreImpl store) throws JwmaException {
842: m_Store = store;
843: prepare();
844: }//update
845:
846: /**
847: * Creates a <tt>JwmaFolderImpl</tt> instance from the given
848: * <tt>Folder</tt>.
849: *
850: * @param f mail <tt>Folder</tt> this instance will "wrap".
851: *
852: * @return the newly created instance.
853: *
854: * @throws JwmaException if it fails to create the new instance.
855: */
856: public static JwmaFolderImpl createJwmaFolderImpl(
857: JwmaStoreImpl store, Folder f) throws JwmaException {
858:
859: JwmaFolderImpl folder = new JwmaFolderImpl(f, store);
860: folder.prepare();
861: return folder;
862: }//createJwmaFolderImpl
863:
864: /**
865: * Creates a <tt>JwmaFolderImpl</tt> instance from the given
866: * <tt>Folder</tt>.
867: *
868: * @param f mail <tt>Folder</tt> this instance will "wrap".
869: *
870: * @return the newly created instance.
871: *
872: * @throws JwmaException if it fails to create the new instance.
873: */
874: public static JwmaFolderImpl createJwmaFolderImpl(
875: JwmaStoreImpl store, String fullname) throws JwmaException {
876:
877: //FIXME: What if...the folder name is ""
878: JwmaFolderImpl folder = new JwmaFolderImpl(store
879: .getFolder(fullname), store);
880: folder.prepare();
881: return folder;
882: }//createJwmaFolderImpl
883:
884: /**
885: * Creates a <tt>JwmaFolderImpl</tt> instance from the given
886: * <tt>Folder</tt>.
887: *
888: * @param folder mail <tt>Folder</tt> this instance will "wrap".
889: *
890: * @return the newly created instance.
891: *
892: * @throws JwmaException if it fails to create the new instance.
893: */
894: public static JwmaFolderImpl createLight(Folder folder)
895: throws JwmaException {
896:
897: try {
898: JwmaFolderImpl jwmafolder = new JwmaFolderImpl(folder);
899:
900: jwmafolder.setName(folder.getName());
901: jwmafolder.setPath(folder.getFullName());
902: jwmafolder.setType(folder.getType());
903: return jwmafolder;
904:
905: } catch (MessagingException mex) {
906: throw new JwmaException("jwma.folder.failedcreation", true)
907: .setException(mex);
908: }
909: }//createJwmaFolderImpl
910:
911: }//JwmaFolderImpl
|