KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > imap > IMAPRootFolder


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

17 package org.columba.mail.folder.imap;
18
19 import java.util.logging.Logger JavaDoc;
20
21 import org.columba.api.command.ICommand;
22 import org.columba.api.command.IStatusObservable;
23 import org.columba.core.command.Command;
24 import org.columba.core.command.CommandProcessor;
25 import org.columba.core.command.NullWorkerStatusController;
26 import org.columba.core.command.StatusObservableImpl;
27 import org.columba.core.connectionstate.ConnectionStateImpl;
28 import org.columba.core.filter.Filter;
29 import org.columba.mail.command.MailFolderCommandReference;
30 import org.columba.mail.config.AccountItem;
31 import org.columba.mail.config.FolderItem;
32 import org.columba.mail.config.IFolderItem;
33 import org.columba.mail.config.MailConfig;
34 import org.columba.mail.config.SpecialFoldersItem;
35 import org.columba.mail.folder.AbstractFolder;
36 import org.columba.mail.folder.IMailFolder;
37 import org.columba.mail.folder.RootFolder;
38 import org.columba.mail.gui.tree.FolderTreeModel;
39 import org.columba.mail.imap.FetchSubFolderListCommand;
40 import org.columba.mail.imap.IExistsChangedAction;
41 import org.columba.mail.imap.IFirstLoginAction;
42 import org.columba.mail.imap.IImapServer;
43 import org.columba.mail.imap.IMAPServer;
44 import org.columba.mail.imap.IMAPServerOwner;
45 import org.columba.mail.imap.IUpdateFlagAction;
46 import org.columba.mail.util.MailResourceLoader;
47 import org.columba.ristretto.imap.IMAPFlags;
48 import org.columba.ristretto.imap.ListInfo;
49
50 /**
51  * Root folder for IMAP folders.
52  */

53 public class IMAPRootFolder extends AbstractFolder implements RootFolder,
54         IMAPServerOwner {
55
56     /** JDK 1.4+ logging framework logger, used for logging. */
57     private static final Logger JavaDoc LOG = Logger
58             .getLogger("org.columba.mail.folder.imap");
59
60     private static final String JavaDoc[] SPECIAL_FOLDER_NAMES = { "trash", "drafts",
61             "templates", "sent" };
62
63     // private ImapOperator operator;
64
private AccountItem accountItem;
65
66     private IImapServer server;
67
68     private IMAPRootFolder thisFolder = this;
69
70     /**
71      * parent directory for mail folders
72      *
73      * for example: "/home/donald/.columba/mail/"
74      */

75     private String JavaDoc parentPath;
76
77     /**
78      * Status information updates are handled in using IStatusObservable.
79      * <p>
80      * Every command has to register its interest to this events before
81      * accessing the folder.
82      */

83     protected IStatusObservable observable;
84
85     public IMAPRootFolder(FolderItem folderItem, String JavaDoc path) {
86         // super(node, folderItem);
87
super(folderItem);
88
89         // remember parent path
90
// (this is necessary for IMAPRootFolder sync operations)
91
parentPath = path;
92
93         observable = new StatusObservableImpl();
94
95         accountItem = MailConfig.getInstance().getAccountList().uidGet(
96                 folderItem.getInteger("account_uid"));
97
98         updateConfiguration();
99     }
100
101     public IMAPRootFolder(AccountItem accountItem, String JavaDoc path) {
102         // super(node, folderItem);
103
// super(getDefaultItem("IMAPRootFolder", getDefaultProperties()));
104
super(accountItem.get("name"), "IMAPRootFolder");
105         observable = new StatusObservableImpl();
106
107         // remember parent path
108
// (this is necessary for IMAPRootFolder sync operations)
109
parentPath = path;
110
111         this.accountItem = accountItem;
112
113         getConfiguration().setInteger("account_uid",
114                 accountItem.getInteger("uid"));
115
116         updateConfiguration();
117     }
118
119     /**
120      * @param type
121      */

122 // public IMAPRootFolder(String name, String type) {
123
// super(name, type);
124
//
125
// IFolderItem item = getConfiguration();
126
// item.setString("property", "accessrights", "system");
127
// item.setString("property", "subfolder", "true");
128
// }
129

130     public String JavaDoc getDefaultChild() {
131         return "IMAPFolder";
132     }
133
134     /**
135      * @return observable containing status information
136      */

137     public IStatusObservable getObservable() {
138         return observable;
139     }
140
141     protected void syncFolder(AbstractFolder parent, String JavaDoc name, ListInfo info)
142             throws Exception JavaDoc {
143
144         if ((name.indexOf(server.getDelimiter()) != -1)
145                 && (name.indexOf(server.getDelimiter()) != (name.length() - 1))) {
146             // delimiter found
147
// -> recursively create all necessary folders to create
148
// -> the final folder
149
String JavaDoc subchild = name.substring(0, name.indexOf(server
150                     .getDelimiter()));
151             AbstractFolder subFolder = (AbstractFolder) parent
152                     .findChildWithName(subchild, false, IMAPFolder.class);
153
154             // if folder doesn't exist already
155
if (subFolder == null) {
156                 subFolder = new IMAPFolder(subchild, "IMAPFolder",
157                         getParentPath());
158                 parent.add(subFolder);
159                 parent.getConfiguration().getRoot().addElement(
160                         subFolder.getConfiguration().getRoot());
161                 FolderTreeModel.getInstance().insertNodeInto(subFolder, parent,
162                         parent.getIndex(subFolder));
163
164                 ((IMAPFolder) subFolder).existsOnServer = true;
165                 subFolder.getConfiguration().setString("selectable", "false");
166
167                 // this is the final folder
168
// subFolder = addIMAPChildFolder(parent, info, subchild);
169
} else {
170                 if (!((IMAPFolder) subFolder).existsOnServer) {
171                     ((IMAPFolder) subFolder).existsOnServer = true;
172                     subFolder.getConfiguration().setString("selectable",
173                             "false");
174                 }
175             }
176
177             // recursively go on
178
syncFolder(subFolder, name.substring(name.indexOf(server
179                     .getDelimiter())
180                     + server.getDelimiter().length()), info);
181         } else {
182             // no delimiter found
183
// -> this is already the final folder
184
// if folder doesn't exist already
185
AbstractFolder subFolder = (AbstractFolder) parent
186                     .findChildWithName(name, false, IMAPFolder.class);
187
188             if (subFolder == null) {
189                 subFolder = new IMAPFolder(name, "IMAPFolder", getParentPath());
190                 parent.add(subFolder);
191                 parent.getConfiguration().getRoot().addElement(
192                         subFolder.getConfiguration().getRoot());
193                 FolderTreeModel.getInstance().insertNodeInto(subFolder, parent,
194                         parent.getIndex(subFolder));
195             }
196             ((IMAPFolder) subFolder).existsOnServer = true;
197
198             // Check the Noselect flag
199
if (info.getParameter(ListInfo.NOSELECT)) {
200                 subFolder.getConfiguration().setString("selectable", "false");
201             } else {
202                 subFolder.getConfiguration().setString("selectable", "true");
203             }
204
205             // Check the Noinferior flag
206
if (info.getParameter(ListInfo.NOINFERIORS)
207                     && info.getDelimiter() != null) {
208                 subFolder.getConfiguration().setString("noinferiors", "true");
209             } else {
210                 subFolder.getConfiguration().setString("noinferiors", "false");
211             }
212         }
213     }
214
215     protected void markAllSubfoldersAsExistOnServer(AbstractFolder parent,
216             boolean value) {
217         AbstractFolder child;
218
219         for (int i = 0; i < parent.getChildCount(); i++) {
220             child = (AbstractFolder) parent.getChildAt(i);
221
222             if (child instanceof IMAPFolder) {
223                 markAllSubfoldersAsExistOnServer(child, value);
224             }
225         }
226
227         if (parent instanceof IMAPFolder) {
228             ((IMAPFolder) parent).existsOnServer = value;
229         }
230     }
231
232     private boolean removeNotMarkedSubfolders(AbstractFolder parent)
233             throws Exception JavaDoc {
234         AbstractFolder child;
235
236         // first remove all subfolders recursively
237
for (int i = 0; i < parent.getChildCount(); i++) {
238             child = (AbstractFolder) parent.getChildAt(i);
239
240             if (child instanceof IMAPFolder) {
241                 if (removeNotMarkedSubfolders(child)) {
242                     // A child got removed -> stay at this position to
243
// get the next
244
i--;
245                 }
246             }
247         }
248
249         // maybe remove this folder
250
if (parent instanceof IMAPFolder) {
251             if (!((IMAPFolder) parent).existsOnServer) {
252                 FolderTreeModel.getInstance().removeNodeFromParent(parent);
253                 parent.removeFolder();
254                 return true;
255             }
256         }
257
258         return false;
259     }
260
261     public void findSpecialFolders() {
262         SpecialFoldersItem folders = accountItem.getSpecialFoldersItem();
263
264         for (int i = 0; i < SPECIAL_FOLDER_NAMES.length; i++) {
265             // Find special
266
String JavaDoc specialUid = folders.get(SPECIAL_FOLDER_NAMES[i]);
267
268             // if have already a suitable folder skip the search
269
if (this.findChildWithUID(specialUid, true) == null) {
270                 // search for a folder thats on the IMAP account
271
// first try to find the local translation of special
272
AbstractFolder specialFolder = this.findChildWithName(
273                         MailResourceLoader.getString("tree",
274                                 SPECIAL_FOLDER_NAMES[i]), true);
275
276                 if (specialFolder == null) {
277                     // fall back to the english version
278
specialFolder = this.findChildWithName(
279                             SPECIAL_FOLDER_NAMES[i], true);
280                 }
281
282                 if (specialFolder != null) {
283                     // we found a suitable folder -> set it
284
folders.setString(SPECIAL_FOLDER_NAMES[i], specialFolder
285                             .getId());
286                 }
287             }
288         }
289     }
290
291     public void syncSubscribedFolders() throws Exception JavaDoc {
292         // first clear all flags
293
markAllSubfoldersAsExistOnServer(this, false);
294
295         IMAPFolder inbox = (IMAPFolder) this.findChildWithName("INBOX", false);
296         inbox.existsOnServer = true;
297
298         try {
299             // create and tag all subfolders on server
300
ListInfo[] listInfo = getServer().fetchSubscribedFolders();
301
302             for (int i = 0; i < listInfo.length; i++) {
303                 ListInfo info = listInfo[i];
304                 LOG.fine("delimiter=" + getServer().getDelimiter());
305
306                 String JavaDoc folderPath = info.getName();
307
308                 syncFolder(this, folderPath, info);
309             }
310
311         } catch (Exception JavaDoc ex) {
312             ex.printStackTrace();
313         }
314
315         // This fixes the strange behaviour of the courier imapserver
316
// which sets the \Noselect flag on INBOX
317
inbox.getConfiguration().setString("selectable", "true");
318
319         removeNotMarkedSubfolders(this);
320
321         findSpecialFolders();
322     }
323
324     public IImapServer getServer() {
325         return server;
326     }
327
328     public void updateConfiguration() {
329         try {
330             if (server != null)
331                 server.logout();
332         } catch (Exception JavaDoc e1) {
333             // don't care
334
}
335         server = new IMAPServer(accountItem.getImapItem());
336         server.setObservable(observable);
337
338         server.setFirstLoginAction(new IFirstLoginAction() {
339             public void actionPerformed() {
340                 // If we are online sync the subscribed folders on first
341
// connection
342
if (ConnectionStateImpl.getInstance().isOnline()) {
343                     ICommand c = new FetchSubFolderListCommand(
344                             new MailFolderCommandReference(thisFolder));
345                     try {
346                         // MainInterface.processor.addOp(c);
347
c.execute(NullWorkerStatusController.getInstance());
348                         c.updateGUI();
349                     } catch (Exception JavaDoc e) {
350                         e.printStackTrace();
351                     }
352                 }
353             }
354
355         });
356
357         server.setExistsChangedAction(new IExistsChangedAction() {
358
359             public void actionPerformed(IMailFolder folder) {
360                 // Trigger synchronization of the selected Folder
361
Command updateFolderCommand = new CheckForNewMessagesCommand(
362                         null, new MailFolderCommandReference(folder));
363                 CommandProcessor.getInstance().addOp(updateFolderCommand);
364             }
365
366         });
367
368         server.setUpdateFlagAction(new IUpdateFlagAction() {
369
370             public void actionPerformed(IMailFolder folder, IMAPFlags flags) {
371                 // Trigger synchronization of the IMAPFolder
372
Command updateFlagCommand = new UpdateFlagCommand(
373                         new MailFolderCommandReference(folder), flags);
374                 CommandProcessor.getInstance().addOp(updateFlagCommand);
375
376             }
377
378         });
379     }
380
381     /**
382      * @see org.columba.mail.folder.Folder#searchMessages(org.columba.mail.filter.Filter,
383      * java.lang.Object, org.columba.api.command.IWorkerStatusController)
384      */

385     public Object JavaDoc[] searchMessages(Filter filter, Object JavaDoc[] uids)
386             throws Exception JavaDoc {
387         return null;
388     }
389
390     /**
391      * @see org.columba.mail.folder.Folder#searchMessages(org.columba.mail.filter.Filter,
392      * org.columba.api.command.IWorkerStatusController)
393      */

394     public Object JavaDoc[] searchMessages(Filter filter) throws Exception JavaDoc {
395         return null;
396     }
397
398     /**
399      * @return
400      */

401     public AccountItem getAccountItem() {
402         return accountItem;
403     }
404
405     /*
406      * (non-Javadoc)
407      *
408      * @see org.columba.mail.folder.FolderTreeNode#addSubfolder(org.columba.mail.folder.FolderTreeNode)
409      */

410     public void addSubfolder(IMailFolder child) throws Exception JavaDoc {
411         if (child instanceof IMAPFolder) {
412             getServer().createMailbox(child.getName(), null);
413         }
414
415
416         super.addSubfolder(child);
417     }
418
419     public void setInbox(IMAPFolder inbox) throws Exception JavaDoc {
420         super.addSubfolder(inbox);
421         super.add(inbox);
422     }
423
424     /*
425      * (non-Javadoc)
426      *
427      * @see org.columba.mail.folder.Folder#save()
428      */

429     public void save() throws Exception JavaDoc {
430         LOG.info("Logout from IMAPServer " + getName());
431
432         getServer().logout();
433     }
434
435     /*
436      * (non-Javadoc)
437      *
438      * @see org.columba.mail.folder.RootFolder#getTrashFolder()
439      */

440     public AbstractFolder getTrashFolder() {
441         AbstractFolder ret = findChildWithUID(accountItem
442                 .getSpecialFoldersItem().get("trash"), true);
443
444         // has the imap account no trash folder using the default trash folder
445
if (ret == null) {
446             ret = (AbstractFolder) FolderTreeModel.getInstance()
447                     .getTrashFolder();
448         }
449
450         return ret;
451     }
452
453     /*
454      * (non-Javadoc)
455      *
456      * @see org.columba.mail.folder.RootFolder#getInbox()
457      */

458     public AbstractFolder getInboxFolder() {
459         return (IMAPFolder) this.findChildWithName("INBOX", false);
460     }
461
462     /**
463      * Parent directory for mail folders.
464      * <p>
465      * For example: /home/donald/.columba/mail
466      *
467      * @return Returns the parentPath.
468      */

469     public String JavaDoc getParentPath() {
470         return parentPath;
471     }
472
473     /**
474      * @see org.columba.mail.folder.AbstractFolder#supportsAddFolder()
475      */

476     public boolean supportsAddFolder(String JavaDoc folder) {
477         return true;
478     }
479 }
Popular Tags