KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mail > providers > imap4 > IMAPFolder


1 /*
2  * IMAPFolder.java
3  * Copyright (C) 2003 Chris Burdess <dog@gnu.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * You also have permission to link it with the Sun Microsystems, Inc.
11  * JavaMail(tm) extension and run that combination.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */

22
23 package gnu.mail.providers.imap4;
24
25 import java.io.ByteArrayOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.List JavaDoc;
28 import javax.mail.FetchProfile JavaDoc;
29 import javax.mail.Flags JavaDoc;
30 import javax.mail.Folder JavaDoc;
31 import javax.mail.FolderNotFoundException JavaDoc;
32 import javax.mail.IllegalWriteException JavaDoc;
33 import javax.mail.Message JavaDoc;
34 import javax.mail.MessagingException JavaDoc;
35 import javax.mail.Store JavaDoc;
36 import javax.mail.event.ConnectionEvent JavaDoc;
37 import javax.mail.event.FolderEvent JavaDoc;
38 import javax.mail.internet.MimeMessage JavaDoc;
39
40 /**
41  * The folder class implementing the IMAP4rev1 mail protocol.
42  *
43  * @author <a HREF='mailto:dog@gnu.org'>Chris Burdess</a>
44  * @version 0.1
45  */

46 public class IMAPFolder
47   extends Folder JavaDoc
48   implements IMAPConstants
49 {
50
51   /**
52    * The folder path.
53    */

54   protected String JavaDoc path;
55
56   /**
57    * The type of this folder (HOLDS_MESSAGES or HOLDS_FOLDERS).
58    */

59   protected int type;
60
61   /**
62    * The open state of this folder (READ_ONLY, READ_WRITE, or -1).
63    */

64   protected int mode;
65
66   protected Flags JavaDoc permanentFlags = new Flags JavaDoc();
67
68   protected char delimiter = '\u0000';
69
70   protected int messageCount = -1;
71
72   protected int newMessageCount = -1;
73
74   /**
75    * Constructor.
76    */

77   protected IMAPFolder(Store JavaDoc store, String JavaDoc path)
78   {
79     super(store);
80     this.path = path;
81   }
82
83   /*
84    * Updates this folder from the specified mailbox status object.
85    */

86   void update(MailboxStatus status, boolean fireEvents)
87     throws MessagingException JavaDoc
88   {
89     if (status==null)
90       throw new FolderNotFoundException JavaDoc(this);
91     mode = status.readWrite ? Folder.READ_WRITE : Folder.READ_ONLY;
92     if (status.permanentFlags!=null)
93       permanentFlags = readFlags(status.permanentFlags);
94     // message counts
95
int oldMessageCount = messageCount;
96     messageCount = status.messageCount;
97     newMessageCount = status.newMessageCount;
98     // fire events if necessary
99
if (fireEvents)
100     {
101       if (messageCount>oldMessageCount)
102       {
103         Message JavaDoc[] m = new Message JavaDoc[messageCount-oldMessageCount];
104         for (int i=oldMessageCount; i<messageCount; i++)
105           m[i-oldMessageCount] = getMessage(i);
106         notifyMessageAddedListeners(m);
107       }
108       else if (messageCount<oldMessageCount)
109       {
110         Message JavaDoc[] m = new Message JavaDoc[oldMessageCount-messageCount];
111         for (int i=messageCount; i<oldMessageCount; i++)
112           m[i-messageCount] = getMessage(i);
113         notifyMessageRemovedListeners(false, m);
114       }
115     }
116   }
117
118   Flags JavaDoc readFlags(List JavaDoc sflags)
119   {
120     Flags JavaDoc flags = new Flags JavaDoc();
121     int len = sflags.size();
122     for (int i=0; i<len; i++)
123     {
124       String JavaDoc flag = (String JavaDoc)sflags.get(i);
125       if (flag==FLAG_ANSWERED)
126         flags.add(Flags.Flag.ANSWERED);
127       else if (flag==FLAG_DELETED)
128         flags.add(Flags.Flag.DELETED);
129       else if (flag==FLAG_DRAFT)
130         flags.add(Flags.Flag.DRAFT);
131       else if (flag==FLAG_FLAGGED)
132         flags.add(Flags.Flag.FLAGGED);
133       else if (flag==FLAG_RECENT)
134         flags.add(Flags.Flag.RECENT);
135       else if (flag==FLAG_SEEN)
136         flags.add(Flags.Flag.SEEN);
137       // user flags?
138
}
139     return flags;
140   }
141
142   /**
143    * Returns the name of this folder.
144    */

145   public String JavaDoc getName()
146   {
147     int di = path.lastIndexOf(delimiter);
148     return (di==-1) ? path : path.substring(di+1);
149   }
150
151   /**
152    * Returns the full path of this folder.
153    */

154   public String JavaDoc getFullName()
155   {
156     return path;
157   }
158
159   /**
160    * Returns the type of this folder.
161    * @exception MessagingException if a messaging error occurred
162    */

163   public int getType()
164     throws MessagingException JavaDoc
165   {
166     // TODO
167
return type;
168   }
169
170   /**
171    * Indicates whether this folder exists.
172    * @exception MessagingException if a messaging error occurred
173    */

174   public boolean exists()
175     throws MessagingException JavaDoc
176   {
177     return false; // TODO
178
}
179
180   /**
181    * Indicates whether this folder contains new messages.
182    * @exception MessagingException if a messaging error occurred
183    */

184   public boolean hasNewMessages()
185     throws MessagingException JavaDoc
186   {
187     return getNewMessageCount()>0; // TODO
188
}
189
190   /**
191    * Opens this folder.
192    * @exception MessagingException if a messaging error occurred
193    */

194   public void open(int mode)
195     throws MessagingException JavaDoc
196   {
197     IMAPConnection connection = ((IMAPStore)store).connection;
198     try
199     {
200       MailboxStatus status = null;
201       switch (mode)
202       {
203         case Folder.READ_WRITE:
204           status = connection.select(getFullName());
205           break;
206         case Folder.READ_ONLY:
207           status = connection.examine(getFullName());
208           break;
209         default:
210           throw new MessagingException JavaDoc("No such mode: "+mode);
211       }
212       update(status, false);
213       notifyConnectionListeners(ConnectionEvent.OPENED);
214     }
215     catch (IOException JavaDoc e)
216     {
217       throw new MessagingException JavaDoc(e.getMessage(), e);
218     }
219   }
220
221   /**
222    * Create this folder.
223    */

224   public boolean create(int type)
225     throws MessagingException JavaDoc
226   {
227     IMAPConnection connection = ((IMAPStore)store).connection;
228     try
229     {
230       String JavaDoc path = this.path;
231       if (type==HOLDS_FOLDERS)
232         path = new StringBuffer JavaDoc(path)
233           .append(getSeparator())
234           .toString();
235       if (connection.create(path))
236       {
237         notifyFolderListeners(FolderEvent.CREATED);
238         return true;
239       }
240       else
241         return false;
242     }
243     catch (IOException JavaDoc e)
244     {
245       throw new MessagingException JavaDoc(e.getMessage(), e);
246     }
247   }
248
249   /**
250    * Delete this folder.
251    */

252   public boolean delete(boolean flag)
253     throws MessagingException JavaDoc
254   {
255     IMAPConnection connection = ((IMAPStore)store).connection;
256     try
257     {
258       if (connection.delete(path))
259       {
260         notifyFolderListeners(FolderEvent.DELETED);
261         return true;
262       }
263       else
264         return false;
265     }
266     catch (IOException JavaDoc e)
267     {
268       throw new MessagingException JavaDoc(e.getMessage(), e);
269     }
270   }
271
272   /**
273    * Rename this folder.
274    */

275   public boolean renameTo(Folder JavaDoc folder)
276     throws MessagingException JavaDoc
277   {
278     IMAPConnection connection = ((IMAPStore)store).connection;
279     try
280     {
281       if (connection.rename(path, folder.getFullName()))
282       {
283         // do we have to close?
284
notifyFolderRenamedListeners(folder);
285         return true;
286       }
287       else
288         return false;
289     }
290     catch (IOException JavaDoc e)
291     {
292       throw new MessagingException JavaDoc(e.getMessage(), e);
293     }
294   }
295
296   /**
297    * Closes this folder.
298    * @param expunge if the folder is to be expunged before it is closed
299    * @exception MessagingException if a messaging error occurred
300    */

301   public void close(boolean expunge)
302     throws MessagingException JavaDoc
303   {
304     if (!isOpen())
305       throw new MessagingException JavaDoc("Folder is not open");
306     if (expunge)
307       expunge();
308     IMAPConnection connection = ((IMAPStore)store).connection;
309     try
310     {
311       connection.close();
312     }
313     catch (IOException JavaDoc e)
314     {
315       throw new MessagingException JavaDoc(e.getMessage(), e);
316     }
317     mode = -1;
318     notifyConnectionListeners(ConnectionEvent.CLOSED);
319   }
320
321   /**
322    * Expunges this folder.
323    * This deletes all the messages marked as deleted.
324    * @exception MessagingException if a messaging error occurred
325    */

326   public Message JavaDoc[] expunge()
327     throws MessagingException JavaDoc
328   {
329     if (!isOpen())
330       throw new MessagingException JavaDoc("Folder is not open");
331     if (mode==Folder.READ_ONLY)
332       throw new MessagingException JavaDoc("Folder was opened read-only");
333     IMAPConnection connection = ((IMAPStore)store).connection;
334     try
335     {
336       int[] messageNumbers = connection.expunge();
337       // construct empty IMAPMessages for the messageNumbers
338
IMAPMessage[] messages = new IMAPMessage[messageNumbers.length];
339       for (int i=0; i<messages.length; i++)
340         messages[i] = new IMAPMessage(this, messageNumbers[i]);
341       // do we need to do this?
342
notifyMessageRemovedListeners(true, messages);
343       return messages;
344     }
345     catch (IOException JavaDoc e)
346     {
347       throw new MessagingException JavaDoc(e.getMessage(), e);
348     }
349   }
350
351   /**
352    * Indicates whether this folder is open.
353    */

354   public boolean isOpen()
355   {
356     return (mode!=-1);
357   }
358
359   /**
360    * Returns the permanent flags for this folder.
361    */

362   public Flags JavaDoc getPermanentFlags()
363   {
364     return permanentFlags;
365   }
366
367   /**
368    * Returns the number of messages in this folder.
369    * @exception MessagingException if a messaging error occurred
370    */

371   public int getMessageCount()
372     throws MessagingException JavaDoc
373   {
374     if (mode==-1 || messageCount<0)
375     {
376       IMAPConnection connection = ((IMAPStore)store).connection;
377       try
378       {
379         String JavaDoc[] items = new String JavaDoc[1];
380         items[0] = IMAPConnection.MESSAGES;
381         MailboxStatus ms = connection.status(path, items);
382         update(ms, true);
383       }
384       catch (IOException JavaDoc e)
385       {
386         throw new MessagingException JavaDoc(e.getMessage(), e);
387       }
388     }
389     // TODO else NOOP
390
return messageCount;
391   }
392
393   /**
394    * Returns the number of new messages in this folder.
395    * @exception MessagingException if a messaging error occurred
396    */

397   public int getNewMessageCount()
398     throws MessagingException JavaDoc
399   {
400     if (mode==-1 || newMessageCount<0)
401     {
402       IMAPConnection connection = ((IMAPStore)store).connection;
403       try
404       {
405         String JavaDoc[] items = new String JavaDoc[1];
406         items[0] = IMAPConnection.RECENT;
407         MailboxStatus ms = connection.status(path, items);
408         update(ms, true);
409       }
410       catch (IOException JavaDoc e)
411       {
412         throw new MessagingException JavaDoc(e.getMessage(), e);
413       }
414     }
415     // TODO else NOOP
416
return newMessageCount;
417   }
418
419   /**
420    * Returns the specified message number from this folder.
421    * The message is only retrieved once from the server.
422    * Subsequent getMessage() calls to the same message are cached.
423    * Since POP3 does not provide a mechanism for retrieving only part of
424    * the message (headers, etc), the entire message is retrieved.
425    * @exception MessagingException if a messaging error occurred
426    */

427   public Message JavaDoc getMessage(int msgnum)
428     throws MessagingException JavaDoc
429   {
430     if (mode==-1)
431       throw new MessagingException JavaDoc("Folder is not open");
432     return new IMAPMessage(this, msgnum);
433   }
434
435   /**
436    * Appends the specified set of messages to this folder.
437    * Only <code>MimeMessage</code>s are accepted.
438    */

439   public void appendMessages(Message JavaDoc[] messages)
440     throws MessagingException JavaDoc
441   {
442     if (mode==Folder.READ_ONLY)
443       throw new IllegalWriteException JavaDoc("Folder is read-only");
444     MimeMessage JavaDoc[] m = new MimeMessage JavaDoc[messages.length];
445     try
446     {
447       for (int i=0; i<messages.length; i++)
448         m[i] = (MimeMessage JavaDoc)messages[i];
449     }
450     catch (ClassCastException JavaDoc e)
451     {
452       throw new MessagingException JavaDoc("Only MimeMessages can be appended to "+
453           "this folder");
454     }
455     try
456     {
457       IMAPStore s = (IMAPStore)store;
458       for (int i=0; i<m.length; i++)
459       {
460         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
461         m[i].writeTo(out);
462         byte[] content = out.toByteArray();
463         out = null;
464         s.connection.append(path, null, content);
465       }
466     }
467     catch (IOException JavaDoc e)
468     {
469       throw new MessagingException JavaDoc(e.getMessage(), e);
470     }
471     notifyMessageAddedListeners(m);
472   }
473
474   public void fetch(Message JavaDoc[] messages, FetchProfile JavaDoc fetchprofile)
475     throws MessagingException JavaDoc
476   {
477     // TODO
478
}
479
480   /**
481    * Returns the subfolders for this folder.
482    */

483   public Folder JavaDoc[] list(String JavaDoc pattern)
484     throws MessagingException JavaDoc
485   {
486     IMAPConnection connection = ((IMAPStore)store).connection;
487     try
488     {
489       ListEntry[] entries = connection.list(path, pattern);
490       Folder JavaDoc[] folders = new Folder JavaDoc[entries.length];
491       for (int i=0; i<folders.length; i++)
492         folders[i] = getFolder(entries[i].mailbox);
493       return folders;
494     }
495     catch (IOException JavaDoc e)
496     {
497       throw new MessagingException JavaDoc(e.getMessage(), e);
498     }
499   }
500   
501   /**
502    * Returns the subscribed subfolders for this folder.
503    */

504   public Folder JavaDoc[] listSubscribed(String JavaDoc pattern)
505     throws MessagingException JavaDoc
506   {
507     IMAPConnection connection = ((IMAPStore)store).connection;
508     try
509     {
510       ListEntry[] entries = connection.lsub(path, pattern);
511       Folder JavaDoc[] folders = new Folder JavaDoc[entries.length];
512       for (int i=0; i<folders.length; i++)
513         folders[i] = getFolder(entries[i].mailbox);
514       return folders;
515     }
516     catch (IOException JavaDoc e)
517     {
518       throw new MessagingException JavaDoc(e.getMessage(), e);
519     }
520   }
521
522   /**
523    * Returns the parent folder of this folder.
524    */

525   public Folder JavaDoc getParent()
526     throws MessagingException JavaDoc
527   {
528     IMAPConnection connection = ((IMAPStore)store).connection;
529     int di = path.lastIndexOf(getSeparator());
530     if (di==-1)
531       return null;
532     return store.getFolder(path.substring(0, di));
533   }
534
535   /**
536    * Returns a subfolder with the specified name.
537    */

538   public Folder JavaDoc getFolder(String JavaDoc name)
539     throws MessagingException JavaDoc
540   {
541     IMAPConnection connection = ((IMAPStore)store).connection;
542     return store.getFolder(new StringBuffer JavaDoc(path)
543         .append(getSeparator())
544         .append(name)
545         .toString());
546   }
547
548   /**
549    * Returns the path separator charcter.
550    */

551   public char getSeparator()
552     throws MessagingException JavaDoc
553   {
554     if (delimiter=='\u0000')
555     {
556       try
557       {
558         IMAPConnection connection = ((IMAPStore)store).connection;
559         ListEntry[] entries = connection.list(path, null);
560         if (entries.length>0)
561           delimiter = entries[0].delimiter;
562       }
563       catch (IOException JavaDoc e)
564       {
565         throw new MessagingException JavaDoc(e.getMessage(), e);
566       }
567     }
568     return delimiter;
569   }
570
571
572 }
573
Popular Tags