KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > virtual > VirtualFolder


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

19 package org.columba.mail.folder.virtual;
20
21 import java.io.InputStream JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Comparator JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30
31 import javax.swing.JDialog JavaDoc;
32
33 import org.columba.api.command.IWorkerStatusController;
34 import org.columba.core.filter.Filter;
35 import org.columba.core.filter.FilterCriteria;
36 import org.columba.core.filter.FilterRule;
37 import org.columba.core.filter.IFilter;
38 import org.columba.core.filter.IFilterCriteria;
39 import org.columba.core.filter.IFilterRule;
40 import org.columba.core.xml.XmlElement;
41 import org.columba.mail.config.FolderItem;
42 import org.columba.mail.config.IFolderItem;
43 import org.columba.mail.filter.MailFilterCriteria;
44 import org.columba.mail.folder.AbstractLocalFolder;
45 import org.columba.mail.folder.AbstractMessageFolder;
46 import org.columba.mail.folder.FolderChildrenIterator;
47 import org.columba.mail.folder.FolderFactory;
48 import org.columba.mail.folder.IMailFolder;
49 import org.columba.mail.folder.IMailbox;
50 import org.columba.mail.folder.event.FolderListener;
51 import org.columba.mail.folder.event.IFolderEvent;
52 import org.columba.mail.folder.headercache.CachedHeaderfields;
53 import org.columba.mail.folder.headercache.MemoryHeaderList;
54 import org.columba.mail.folder.imap.IMAPFolder;
55 import org.columba.mail.folder.mh.CachedMHFolder;
56 import org.columba.mail.folder.search.DefaultSearchEngine;
57 import org.columba.mail.gui.config.search.SearchFrame;
58 import org.columba.mail.gui.frame.AbstractMailFrameController;
59 import org.columba.mail.gui.tree.FolderTreeModel;
60 import org.columba.mail.message.ColumbaHeader;
61 import org.columba.mail.message.ICloseableIterator;
62 import org.columba.mail.message.IHeaderList;
63 import org.columba.ristretto.message.Attributes;
64 import org.columba.ristretto.message.Flags;
65 import org.columba.ristretto.message.Header;
66 import org.columba.ristretto.message.MimeTree;
67
68 /**
69  * Virtual folder presenting search results and saving only references to
70  * messages of "real" folders.
71  * <p>
72  * Almost all methods don't do anything here, because the we pass all operatins
73  * to the source folders. This happens on the Command and CommandReference
74  * abstraction level.
75  * <p>
76  *
77  * @author fdietz
78  *
79  */

80 public class VirtualFolder extends AbstractMessageFolder implements
81         FolderListener {
82     /** JDK 1.4+ logging framework logger, used for logging. */
83     private static final Logger JavaDoc LOG = Logger
84             .getLogger("org.columba.mail.folder.virtual"); //$NON-NLS-1$
85

86     protected int nextUid;
87
88     protected IHeaderList headerList;
89
90     private boolean active;
91
92     private IMailFolder sourceFolder;
93
94     // only called by FolderTreeModel.createDirectories() and FolderTreeModel.add()
95
public VirtualFolder(FolderItem item, String JavaDoc path) {
96         super(item);
97
98         headerList = new MemoryHeaderList();
99
100         ensureValidFilterElement();
101     }
102
103 // public VirtualFolder(FolderItem item) {
104
// super(item);
105
//
106
// headerList = new MemoryHeaderList();
107
//
108
// ensureValidFilterElement();
109
// }
110

111
112     public VirtualFolder(String JavaDoc name) {
113         super(name, "VirtualFolder");
114
115         IFolderItem item = getConfiguration();
116         item.setString("property", "accessrights", "user");
117         item.setString("property", "subfolder", "true");
118         item.setString("property", "include_subfolders", "true");
119         item.setString("property", "source_uid", "101");
120
121         headerList = new MemoryHeaderList();
122
123         ensureValidFilterElement();
124     }
125
126     public VirtualFolder(String JavaDoc name, IMailFolder sourceFolder) {
127         this(name);
128
129         this.sourceFolder = sourceFolder;
130     }
131
132
133
134     private void registerWithSource() {
135         IMailFolder folder = getSourceFolder();
136
137         folder.addFolderListener(this);
138
139         if (isRecursive()) {
140             FolderChildrenIterator it = new FolderChildrenIterator(folder);
141
142             while (it.hasMoreChildren()) {
143                 IMailFolder next = it.nextChild();
144
145                 if (!(next instanceof VirtualFolder)
146                         && (next instanceof IMailbox)) {
147                     next.addFolderListener(this);
148                 }
149             }
150         }
151     }
152
153     private void unregisterWithSource() {
154         IMailFolder folder = getSourceFolder();
155
156         folder.removeFolderListener(this);
157
158         if (isRecursive()) {
159             FolderChildrenIterator it = new FolderChildrenIterator(folder);
160
161             while (it.hasMoreChildren()) {
162                 IMailFolder next = it.nextChild();
163
164                 if (!(next instanceof VirtualFolder)) {
165                     next.removeFolderListener(this);
166                 }
167             }
168         }
169     }
170
171     /**
172      * Ensures that there is at least one valid filter entry in the VFolder.
173      */

174     private void ensureValidFilterElement() {
175         XmlElement filter = getConfiguration().getRoot().getElement("filter");
176
177         if (filter == null) {
178             filter = new XmlElement("filter");
179             filter.addAttribute("description", "new filter");
180             filter.addAttribute("enabled", "true");
181             getConfiguration().getRoot().addElement(filter);
182         }
183
184         if (filter.count() == 0) {
185             XmlElement rules = new XmlElement("rules");
186             rules.addAttribute("condition", "matchall");
187
188             XmlElement criteria = new XmlElement("criteria");
189             criteria.addAttribute("type", "Subject");
190             criteria.addAttribute("headerfield", "Subject");
191             criteria.addAttribute("criteria", "contains");
192             criteria.addAttribute("pattern", "pattern");
193             rules.addElement(criteria);
194             filter.addElement(rules);
195         }
196     }
197
198     protected Object JavaDoc generateNextUid() {
199         return new Integer JavaDoc(nextUid++);
200     }
201
202     public void setNextUid(int next) {
203         nextUid = next;
204     }
205
206     public JDialog JavaDoc showFilterDialog(AbstractMailFrameController frameController) {
207         return new SearchFrame(frameController, this);
208     }
209
210     public boolean exists(Object JavaDoc uid) throws Exception JavaDoc {
211         return headerList.exists(uid);
212     }
213
214     public IHeaderList getHeaderList() throws Exception JavaDoc {
215         if (!active) {
216             activate();
217         } else {
218             revalidateSearch();
219         }
220
221         return headerList;
222     }
223
224     /**
225      *
226      */

227     private void revalidateSearch() {
228         VirtualHeader h;
229
230         // Analyze the Filter
231
IFilter filter = (Filter) getFilter().clone();
232         IFilterRule rule = filter.getFilterRule();
233         for (int i = 0; i < rule.count(); i++) {
234             IFilterCriteria c = rule.get(i);
235             if (!c.getTypeString().equalsIgnoreCase("flags")) {
236                 rule.remove(i);
237                 i--;
238             }
239         }
240
241         // If no flags filter the seach is still valid
242
if (rule.count() == 0) {
243             return;
244         }
245
246         // redo the seach for the flags criteria
247
ICloseableIterator it = headerList.headerIterator();
248         while (it.hasNext()) {
249             h = (VirtualHeader) it.next();
250
251             try {
252                 if (h.getSrcFolder().searchMessages(filter,
253                         new Object JavaDoc[] { h.getSrcUid() }).length == 0) {
254                     it.remove();
255
256                     // notify listeners
257
fireMessageRemoved(h.getVirtualUid(), h.getFlags());
258
259                 }
260             } catch (Exception JavaDoc e) {
261                 e.printStackTrace();
262             }
263         }
264         it.close();
265
266     }
267
268     public void addSearchToHistory() throws Exception JavaDoc {
269         VirtualFolder searchFolder = (VirtualFolder) FolderTreeModel
270                 .getInstance().getFolder("106");
271
272         // only create new subfolders if we used the default "Search Folder"
273
if (!searchFolder.equals(this)) {
274             return;
275         }
276
277         // (tstich) reduced to 3 because all need to be
278
// search when activated on startup
279
// we only want 3 subfolders
280
// -> if more children exist remove them
281
if (searchFolder.getChildCount() >= 3) {
282             AbstractMessageFolder child = (AbstractMessageFolder) searchFolder
283                     .getChildAt(0);
284             child.removeFolder();
285         }
286
287         // create new subfolder
288
String JavaDoc name = "search result";
289         VirtualFolder newFolder = null;
290
291         try {
292             newFolder = (VirtualFolder) FolderFactory.getInstance()
293                     .createChild(searchFolder, name, "VirtualFolder");
294         } catch (Exception JavaDoc ex) {
295             ex.printStackTrace();
296
297             return;
298         }
299
300         // if creation failed
301
if (newFolder == null) {
302             return;
303         }
304
305         // copy all properties to the subfolder
306
int uid = getConfiguration().getInteger("property", "source_uid");
307         boolean includes = getConfiguration().getBoolean("property",
308                 "include_subfolders");
309
310         IFolderItem newFolderItem = newFolder.getConfiguration();
311         newFolderItem.setInteger("property", "source_uid", uid);
312         newFolderItem.setBoolean("property", "include_subfolders", includes);
313
314         newFolderItem.getElement("filter").removeFromParent();
315         newFolderItem.getRoot().addElement(
316                 (XmlElement) getConfiguration().getElement("filter").clone());
317
318         MailFilterCriteria newc = new MailFilterCriteria(new Filter(
319                 getConfiguration().getElement("filter")).getFilterRule().get(0));
320
321         /*
322          * FilterCriteria c = new
323          * Filter(getConfiguration().getElement("filter")) .getFilterRule()
324          * .get( 0);
325          *
326          * FilterCriteria newc = new
327          * Filter(getConfiguration().getElement("filter")) .getFilterRule()
328          * .get( 0); newc.setCriteria(c.getCriteriaString());
329          * newc.setHeaderItem(c.getHeaderItemString());
330          * newc.setPattern(c.getPattern()); newc.setType(c.getType());
331          */

332
333         // lets find a good name for our new vfolder
334
StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
335
336         if (newc.getTypeString().equalsIgnoreCase("flags")) {
337             LOG.info("flags found"); //$NON-NLS-1$
338

339             buf.append(newc.getTypeString());
340             buf.append(" (");
341             buf.append(newc.getCriteriaString());
342             buf.append(" ");
343             buf.append(newc.getPatternString());
344             buf.append(")");
345         } else if (newc.getTypeString().equalsIgnoreCase("custom headerfield")) {
346             buf.append(newc.getHeaderfieldString());
347             buf.append(" (");
348             buf.append(newc.getCriteriaString());
349             buf.append(" ");
350             buf.append(newc.getPatternString());
351             buf.append(")");
352         } else {
353             buf.append(newc.getTypeString());
354             buf.append(" (");
355             buf.append(newc.getCriteriaString());
356             buf.append(" ");
357             buf.append(newc.getPatternString());
358             buf.append(")");
359         }
360
361         newFolder.setName(buf.toString());
362
363         // update tree-view
364
FolderTreeModel.getInstance().nodeStructureChanged(searchFolder);
365
366         // update tree-node (for renaming the new folder)
367
FolderTreeModel.getInstance().nodeChanged(newFolder);
368     }
369
370     protected void applySearch() throws Exception JavaDoc {
371         IMailFolder srcFolder = getSourceFolder();
372
373         XmlElement filter = getConfiguration().getRoot().getElement("filter");
374
375         if (filter == null) {
376             filter = new XmlElement("filter");
377             filter.addAttribute("description", "new filter");
378             filter.addAttribute("enabled", "true");
379
380             XmlElement rules = new XmlElement("rules");
381             rules.addAttribute("condition", "match_all");
382
383             XmlElement criteria = new XmlElement("criteria");
384             criteria.addAttribute("type", "Subject");
385             criteria.addAttribute("headerfield", "Subject");
386             criteria.addAttribute("criteria", "contains");
387             criteria.addAttribute("pattern", "pattern");
388             rules.addElement(criteria);
389             filter.addElement(rules);
390             getConfiguration().getRoot().addElement(filter);
391         }
392
393         Filter f = new Filter(getConfiguration().getRoot().getElement("filter"));
394
395         applySearch(srcFolder, f);
396     }
397
398     /**
399      * @return
400      */

401     IMailFolder getSourceFolder() {
402
403         String JavaDoc uid = getConfiguration().getString("property", "source_uid");
404
405         if (sourceFolder != null && sourceFolder.getId().equals(uid)) return sourceFolder;
406
407         IMailFolder folder = (IMailFolder) FolderTreeModel.getInstance()
408                 .getFolder(uid);
409
410         return folder;
411     }
412
413     protected void applySearch(IMailFolder parent, Filter filter)
414             throws Exception JavaDoc {
415
416         if (parent instanceof IMailbox) {
417
418             IMailbox folder = (IMailbox) parent;
419
420             // if the parent is a virtual folder the search cannot be applied directly
421
// look for the correct uids by finding the first non virtual folder
422

423             Object JavaDoc[] resultUids = null;
424
425             if (folder instanceof VirtualFolder)
426                 resultUids = folder.searchMessages(filter, folder.getUids());
427             else
428                 resultUids = folder.searchMessages(filter);
429
430             String JavaDoc[] headerfields = CachedHeaderfields.getDefaultHeaderfields();
431
432             if (resultUids != null) {
433                 for (int i = 0; i < resultUids.length; i++) {
434                     ColumbaHeader header = null;
435
436                     if (folder instanceof VirtualFolder) {
437                         // get source folder reference
438
VirtualHeader virtualHeader = ((VirtualFolder) folder)
439                                 .getVirtualHeader(resultUids[i]);
440                         IMailbox sourceFolder = virtualHeader.getSrcFolder();
441                         Object JavaDoc sourceUid = virtualHeader.getSrcUid();
442
443                         Header h = sourceFolder.getHeaderFields(sourceUid,
444                                 headerfields);
445                         header = new ColumbaHeader(h);
446                         header.setAttributes(sourceFolder
447                                 .getAttributes(sourceUid));
448                         header.setFlags(sourceFolder.getFlags(sourceUid));
449                         Object JavaDoc uid = add((ColumbaHeader) header, sourceFolder,
450                                 sourceUid);
451                         fireMessageAdded(uid, getFlags(uid));
452                     } else {
453                         if (!folder.exists(resultUids[i]))
454                             continue;
455
456                         Header h = folder.getHeaderFields(resultUids[i],
457                                 headerfields);
458                         header = new ColumbaHeader(h);
459                         header.setAttributes(folder
460                                 .getAttributes(resultUids[i]));
461                         header.setFlags(folder.getFlags(resultUids[i]));
462                         Object JavaDoc uid = add(header, folder, resultUids[i]);
463                         fireMessageAdded(uid, getFlags(uid));
464
465                     }
466
467                 }
468             }
469
470         }
471
472         if (isRecursive()) {
473             for (Enumeration JavaDoc e = parent.children(); e.hasMoreElements();) {
474                 IMailFolder folder = (IMailFolder) e.nextElement();
475
476                 if (folder instanceof VirtualFolder) {
477                     continue;
478                 }
479
480                 applySearch(folder, filter);
481             }
482         }
483     }
484
485     private boolean isRecursive() {
486         return Boolean.valueOf(
487                 getConfiguration().getString("property", "include_subfolders"))
488                 .booleanValue();
489     }
490
491     public DefaultSearchEngine getSearchEngine() {
492         return null;
493     }
494
495     public Filter getFilter() {
496         return new Filter(getConfiguration().getRoot().getElement("filter"));
497     }
498
499     public Object JavaDoc add(ColumbaHeader header, IMailbox source, Object JavaDoc uid)
500             throws Exception JavaDoc {
501         Object JavaDoc newUid = generateNextUid();
502
503         // VirtualMessage m = new VirtualMessage(f, uid, index);
504
VirtualHeader virtualHeader = new VirtualHeader((ColumbaHeader) header,
505                 source, uid);
506         virtualHeader.setVirtualUid(newUid);
507
508         headerList.add(virtualHeader, newUid);
509
510         return newUid;
511     }
512
513     /**
514      * @see org.columba.modules.mail.folder.Folder#markMessage(Object[], int,
515      * IMAPFolder)
516      */

517     public void markMessage(Object JavaDoc[] uids, int variant) throws Exception JavaDoc {
518         List JavaDoc list = new ArrayList JavaDoc();
519
520         // Check if all uids are still exisiting
521
for (Object JavaDoc uid : uids) {
522             if (exists(uid)) {
523                 list.add(uid);
524             }
525         }
526         if (list.size() == 0)
527             return;
528
529         Collections.sort(list, new Comparator JavaDoc() {
530
531             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
532                 VirtualHeader h = (VirtualHeader) headerList.get(o1);
533                 String JavaDoc oV1 = h.getSrcFolder().getId();
534
535                 h = (VirtualHeader) headerList.get(o2);
536                 String JavaDoc oV2 = h.getSrcFolder().getId();
537
538                 return oV1.compareTo(oV2);
539             }
540         });
541
542         List JavaDoc folderUids = new ArrayList JavaDoc(uids.length);
543         Iterator JavaDoc it = list.iterator();
544
545         VirtualHeader h = (VirtualHeader) headerList.get(it.next());
546         ;
547         folderUids.add(h.getSrcUid());
548         IMailbox srcFolder = h.getSrcFolder();
549
550         while (it.hasNext()) {
551             h = (VirtualHeader) headerList.get(it.next());
552
553             if (h.getSrcFolder() == srcFolder) {
554                 folderUids.add(h.getSrcUid());
555             } else {
556                 srcFolder.markMessage(folderUids.toArray(), variant);
557
558                 // change to new folder
559
srcFolder = h.getSrcFolder();
560                 folderUids.clear();
561                 folderUids.add(h.getSrcUid());
562             }
563         }
564
565         srcFolder.markMessage(folderUids.toArray(), variant);
566     }
567
568     /**
569      * @see org.columba.modules.mail.folder.Folder#remove(Object)
570      */

571     public void removeMessage(Object JavaDoc uid) throws Exception JavaDoc {
572
573         // get source folder reference
574
VirtualHeader h = (VirtualHeader) headerList.get(uid);
575         IMailbox sourceFolder = h.getSrcFolder();
576         Object JavaDoc sourceUid = h.getSrcUid();
577
578         // remove from source folder
579
sourceFolder.removeMessage(sourceUid);
580
581         // remove from virtual folder
582
headerList.remove(uid);
583
584         // notify listeners
585
fireMessageRemoved(uid, getFlags(uid));
586     }
587
588     /**
589      * @see org.columba.modules.mail.folder.Folder#getMimeTree(Object,
590      * IMAPFolder)
591      */

592     public MimeTree getMimePartTree(Object JavaDoc uid) throws Exception JavaDoc {
593         if (!exists(uid))
594             return null;
595
596         VirtualHeader h = (VirtualHeader) headerList.get(uid);
597         IMailbox sourceFolder = h.getSrcFolder();
598         Object JavaDoc sourceUid = h.getSrcUid();
599
600         return sourceFolder.getMimePartTree(sourceUid);
601     }
602
603     /**
604      * Get virtual header.
605      *
606      * @param virtualUid
607      * virtual uid
608      * @return virtual header
609      */

610     public VirtualHeader getVirtualHeader(Object JavaDoc virtualUid) {
611         return (VirtualHeader) headerList.get(virtualUid);
612     }
613
614     /**
615      * @see org.columba.modules.mail.folder.Folder#searchMessages(Filter,
616      * Object[], IWorkerStatusController)
617      */

618     public Object JavaDoc[] searchMessages(Filter filter, Object JavaDoc[] uids)
619             throws Exception JavaDoc {
620         if (!active) {
621             activate();
622         } else {
623             revalidateSearch();
624         }
625
626         if (uids.length == 0)
627             return new Object JavaDoc[0];
628
629         List JavaDoc list = new ArrayList JavaDoc(Arrays.asList(uids));
630
631         Collections.sort(list, new Comparator JavaDoc() {
632
633             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
634                 VirtualHeader h = (VirtualHeader) headerList.get(o1);
635                 String JavaDoc oV1 = h.getSrcFolder().getId();
636
637                 h = (VirtualHeader) headerList.get(o2);
638                 String JavaDoc oV2 = h.getSrcFolder().getId();
639
640                 return oV1.compareTo(oV2);
641             }
642         });
643
644         List JavaDoc resultList = new ArrayList JavaDoc();
645
646         List JavaDoc virtualHeader = new ArrayList JavaDoc();
647         VirtualHeader h = (VirtualHeader) headerList.get(list.get(0));
648         IMailbox sourceFolder = h.getSrcFolder();
649         virtualHeader.add(h);
650
651         for (int i = 1; i < uids.length; i++) {
652             h = (VirtualHeader) headerList.get(list.get(i));
653
654             if (h.getSrcFolder() != sourceFolder || i == uids.length - 1) {
655                 // Now we can search this folder since no mail from
656
// this folder will come in the list
657

658                 Object JavaDoc[] srcUids = new Object JavaDoc[virtualHeader.size()];
659
660                 // Create a src uid array
661
for (int j = 0; j < virtualHeader.size(); j++) {
662                     srcUids[j] = ((VirtualHeader) virtualHeader.get(j))
663                             .getSrcUid();
664                 }
665
666                 // search the src folder with the src uid array
667
Object JavaDoc[] resultUids = sourceFolder.searchMessages(filter,
668                         srcUids);
669
670                 // Convert the src uids back to virtual uids
671
if ((resultUids != null) && (resultUids.length > 0)) {
672                     Object JavaDoc[] virtualUids = new Object JavaDoc[resultUids.length];
673                     for (int j = 0; j < resultUids.length; j++) {
674                         virtualUids[j] = srcUidToVirtualUid(sourceFolder,
675                                 resultUids[j]);
676                     }
677
678                     // Add all found virtual uids to the result
679
resultList.addAll(Arrays.asList(virtualUids));
680                 }
681
682                 virtualHeader.clear();
683             }
684
685             // Add this header to the list for later searching
686
virtualHeader.add(h);
687             sourceFolder = h.getSrcFolder();
688         }
689         if (virtualHeader.size() > 0) {
690             // Now we can search this folder since no mail from
691
// this folder will come in the list
692

693             Object JavaDoc[] srcUids = new Object JavaDoc[virtualHeader.size()];
694
695             // Create a src uid array
696
for (int j = 0; j < virtualHeader.size(); j++) {
697                 srcUids[j] = ((VirtualHeader) virtualHeader.get(j)).getSrcUid();
698             }
699
700             // search the src folder with the src uid array
701
Object JavaDoc[] resultUids = sourceFolder.searchMessages(filter, srcUids);
702
703             // Convert the src uids back to virtual uids
704
if ((resultUids != null) && (resultUids.length > 0)) {
705                 Object JavaDoc[] virtualUids = new Object JavaDoc[resultUids.length];
706                 for (int j = 0; j < resultUids.length; j++) {
707                     virtualUids[j] = srcUidToVirtualUid(sourceFolder,
708                             resultUids[j]);
709                 }
710
711                 // Add all found virtual uids to the result
712
resultList.addAll(Arrays.asList(virtualUids));
713             }
714
715             virtualHeader.clear();
716         }
717
718         return resultList.toArray();
719     }
720
721     public Object JavaDoc[] searchMessages(Filter filter) throws Exception JavaDoc {
722
723         return searchMessages(filter, getUids());
724     }
725
726     /**
727      * @see org.columba.modules.mail.folder.FolderTreeNode#instanceNewChildNode(AdapterNode,
728      * FolderItem)
729      */

730     public String JavaDoc getDefaultChild() {
731         return null;
732     }
733
734     public static XmlElement getDefaultProperties() {
735         XmlElement props = new XmlElement("property");
736         props.addAttribute("accessrights", "user");
737         props.addAttribute("subfolder", "true");
738         props.addAttribute("include_subfolders", "true");
739         props.addAttribute("source_uid", "101");
740
741         return props;
742     }
743
744     /*
745      * public MailFolderCommandReference getCommandReference(
746      * MailFolderCommandReference r) { MailFolderCommandReference[] newReference =
747      * null;
748      *
749      * Object[] uids = r[0].getUids(); // if we didn't pass uid array here, use
750      * all message in this virtual // folder try { if (uids == null) { uids =
751      * getUids(); } } catch (Exception e1) { e1.printStackTrace(); }
752      *
753      * if (uids == null) { return r; }
754      *
755      * Hashtable list = new Hashtable();
756      *
757      * for (int i = 0; i < uids.length; i++) { VirtualHeader virtualHeader =
758      * (VirtualHeader) headerList .get(uids[i]); AbstractMessageFolder srcFolder =
759      * virtualHeader.getSrcFolder(); Object srcUid = virtualHeader.getSrcUid();
760      *
761      * if (list.containsKey(srcFolder)) { // bucket for this folder exists
762      * already } else { // create new bucket for this folder list.put(srcFolder,
763      * new Vector()); }
764      *
765      * List v = (Vector) list.get(srcFolder); v.add(srcUid); }
766      *
767      * newReference = new MailFolderCommandReference[list.size() + 2];
768      *
769      * int i = 0;
770      *
771      * for (Enumeration e = list.keys(); e.hasMoreElements();) {
772      * AbstractMessageFolder srcFolder = (AbstractMessageFolder)
773      * e.nextElement(); List v = (Vector) list.get(srcFolder);
774      *
775      * newReference[i] = new MailFolderCommandReference(srcFolder);
776      *
777      * Object[] uidArray = new Object[v.size()]; ((Vector)
778      * v).copyInto(uidArray); newReference[i].setUids(uidArray);
779      * newReference[i].setMarkVariant(r[0].getMarkVariant());
780      * newReference[i].setMessage(r[0].getMessage());
781      * newReference[i].setDestFile(r[0].getDestFile());
782      *
783      * i++; }
784      *
785      * if (r.length > 1) { newReference[i] = new
786      * MailFolderCommandReference((AbstractMessageFolder) r[1] .getFolder()); }
787      * else { newReference[i] = null; }
788      *
789      * newReference[i + 1] = r[0];
790      *
791      * return newReference; }
792      */

793
794     /**
795      * @see org.columba.mail.folder.FolderTreeNode#tryToGetLock(java.lang.Object)
796      */

797     public boolean tryToGetLock(Object JavaDoc locker) {
798         // First try to get the lock of the virtual folder
799
boolean success = super.tryToGetLock(locker);
800         if (!success)
801             return false;
802
803         // We need to get the locks of all folders
804
IMailFolder folder = getSourceFolder();
805
806         success &= folder.tryToGetLock(locker);
807
808         if (success && isRecursive()) {
809             FolderChildrenIterator it = new FolderChildrenIterator(folder);
810
811             while (success && it.hasMoreChildren()) {
812                 IMailFolder next = it.nextChild();
813
814                 if (!(next instanceof VirtualFolder)
815                         && (next instanceof IMailbox)) {
816                     success &= next.tryToGetLock(locker);
817                 }
818             }
819         }
820
821         if (!success) {
822             releaseLock(locker);
823         }
824
825         return success;
826     }
827
828     /**
829      * @see org.columba.mail.folder.AbstractFolder#releaseLock(java.lang.Object)
830      */

831     public void releaseLock(Object JavaDoc locker) {
832         super.releaseLock(locker);
833
834         IMailFolder folder = getSourceFolder();
835
836         folder.releaseLock(locker);
837
838         if (isRecursive()) {
839             FolderChildrenIterator it = new FolderChildrenIterator(folder);
840
841             while (it.hasMoreChildren()) {
842                 IMailFolder next = it.nextChild();
843
844                 if (!(next instanceof VirtualFolder)
845                         && (next instanceof IMailbox)) {
846                     next.releaseLock(locker);
847                 }
848             }
849         }
850
851     }
852
853     /*
854      * (non-Javadoc)
855      *
856      * @see org.columba.mail.folder.Folder#getUids(org.columba.api.command.IWorkerStatusController)
857      */

858     public Object JavaDoc[] getUids() throws Exception JavaDoc {
859         if (!active) {
860             activate();
861         }
862
863         return headerList.getUids();
864     }
865
866     protected Object JavaDoc srcUidToVirtualUid(IMailFolder srcFolder, Object JavaDoc uid) {
867         ICloseableIterator it = headerList.headerIterator();
868
869         while (it.hasNext()) {
870             VirtualHeader h = (VirtualHeader) it.next();
871             if (h.getSrcUid().equals(uid) && h.getSrcFolder().equals(srcFolder)) {
872                 it.close();
873                 return h.getVirtualUid();
874             }
875
876         }
877         it.close();
878
879         return null;
880     }
881
882     /*
883      * (non-Javadoc)
884      *
885      * @see org.columba.mail.folder.IMailbox#addMessage(java.io.InputStream)
886      */

887     public Object JavaDoc addMessage(InputStream JavaDoc in) throws Exception JavaDoc {
888         // not supported
889
return null;
890     }
891
892     /*
893      * (non-Javadoc)
894      *
895      * @see org.columba.mail.folder.IMailbox#getAttribute(java.lang.Object,
896      * java.lang.String)
897      */

898     public Object JavaDoc getAttribute(Object JavaDoc uid, String JavaDoc key) throws Exception JavaDoc {
899         VirtualHeader h = (VirtualHeader) headerList.get(uid);
900         IMailbox sourceFolder = h.getSrcFolder();
901         Object JavaDoc sourceUid = h.getSrcUid();
902
903         return sourceFolder.getAttribute(sourceUid, key);
904     }
905
906     /*
907      * (non-Javadoc)
908      *
909      * @see org.columba.mail.folder.IMailbox#getFlags(java.lang.Object)
910      */

911     public Flags getFlags(Object JavaDoc uid) throws Exception JavaDoc {
912
913         VirtualHeader h = (VirtualHeader) headerList.get(uid);
914         IMailbox sourceFolder = h.getSrcFolder();
915
916         Object JavaDoc sourceUid = h.getSrcUid();
917
918         return sourceFolder.getFlags(sourceUid);
919     }
920
921     /*
922      * (non-Javadoc)
923      *
924      * @see org.columba.mail.folder.IMailbox#getHeaderFields(java.lang.Object,
925      * java.lang.String[])
926      */

927     public Header getHeaderFields(Object JavaDoc uid, String JavaDoc[] keys) throws Exception JavaDoc {
928
929         VirtualHeader h = (VirtualHeader) headerList.get(uid);
930         IMailbox sourceFolder = h.getSrcFolder();
931         Object JavaDoc sourceUid = h.getSrcUid();
932
933         return sourceFolder.getHeaderFields(sourceUid, keys);
934     }
935
936     /*
937      * (non-Javadoc)
938      *
939      * @see org.columba.mail.folder.IMailbox#getMessageSourceStream(java.lang.Object)
940      */

941     public InputStream JavaDoc getMessageSourceStream(Object JavaDoc uid) throws Exception JavaDoc {
942
943         VirtualHeader h = (VirtualHeader) headerList.get(uid);
944         IMailbox sourceFolder = h.getSrcFolder();
945         Object JavaDoc sourceUid = h.getSrcUid();
946
947         return sourceFolder.getMessageSourceStream(sourceUid);
948     }
949
950     /*
951      * (non-Javadoc)
952      *
953      * @see org.columba.mail.folder.IMailbox#getMimePartBodyStream(java.lang.Object,
954      * java.lang.Integer[])
955      */

956     public InputStream JavaDoc getMimePartBodyStream(Object JavaDoc uid, Integer JavaDoc[] address)
957             throws Exception JavaDoc {
958
959         VirtualHeader h = (VirtualHeader) headerList.get(uid);
960         IMailbox sourceFolder = h.getSrcFolder();
961         Object JavaDoc sourceUid = h.getSrcUid();
962
963         return sourceFolder.getMimePartBodyStream(sourceUid, address);
964     }
965
966     /*
967      * (non-Javadoc)
968      *
969      * @see org.columba.mail.folder.IMailbox#getMimePartSourceStream(java.lang.Object,
970      * java.lang.Integer[])
971      */

972     public InputStream JavaDoc getMimePartSourceStream(Object JavaDoc uid, Integer JavaDoc[] address)
973             throws Exception JavaDoc {
974
975         VirtualHeader h = (VirtualHeader) headerList.get(uid);
976         IMailbox sourceFolder = h.getSrcFolder();
977         Object JavaDoc sourceUid = h.getSrcUid();
978
979         return sourceFolder.getMimePartSourceStream(sourceUid, address);
980     }
981
982     /**
983      *
984      * VirtualFolder doesn't allow adding messages, in comparison to other
985      * regular mailbox folders.
986      *
987      * @see org.columba.mail.folder.FolderTreeNode#supportsAddMessage()
988      */

989     public boolean supportsAddMessage() {
990         return false;
991     }
992
993     /**
994      * Virtual folders can only accept other Virtual folders as childs.
995      *
996      * @param newFolderType
997      * a folder to check if it is a Virtual folder.
998      * @return true if the folder is a VirtualFolder; false otherwise.
999      */

1000    public boolean supportsAddFolder(String JavaDoc newFolderType) {
1001        return (newFolderType.equals(getType()));
1002    }
1003
1004    public void innerCopy(IMailbox destFolder, Object JavaDoc[] uids) throws Exception JavaDoc {
1005        List JavaDoc list = new ArrayList JavaDoc();
1006
1007        // Check if all uids are still exisiting
1008
for (Object JavaDoc uid : uids) {
1009            if (exists(uid)) {
1010                list.add(uid);
1011            }
1012        }
1013        if (list.size() == 0)
1014            return;
1015
1016        Collections.sort(list, new Comparator JavaDoc() {
1017
1018            public int compare(Object JavaDoc o1, Object JavaDoc o2) {
1019                VirtualHeader h = (VirtualHeader) headerList.get(o1);
1020                String JavaDoc oV1 = h.getSrcFolder().getId();
1021
1022                h = (VirtualHeader) headerList.get(o2);
1023                String JavaDoc oV2 = h.getSrcFolder().getId();
1024
1025                return oV1.compareTo(oV2);
1026            }
1027        });
1028
1029        List JavaDoc folderUids = new ArrayList JavaDoc(uids.length);
1030        Iterator JavaDoc it = list.iterator();
1031
1032        VirtualHeader h = (VirtualHeader) headerList.get(it.next());
1033        ;
1034        folderUids.add(h.getSrcUid());
1035        IMailbox srcFolder = h.getSrcFolder();
1036
1037        while (it.hasNext()) {
1038            h = (VirtualHeader) headerList.get(it.next());
1039
1040            if (h.getSrcFolder() == srcFolder) {
1041                folderUids.add(h.getSrcUid());
1042            } else {
1043                srcFolder.innerCopy(destFolder, folderUids.toArray());
1044
1045                // change to new folder
1046
srcFolder = h.getSrcFolder();
1047                folderUids.clear();
1048                folderUids.add(h.getSrcUid());
1049            }
1050        }
1051
1052        // Copy the rest
1053
srcFolder.innerCopy(destFolder, folderUids.toArray());
1054    }
1055
1056    public void setAttribute(Object JavaDoc uid, String JavaDoc key, Object JavaDoc value)
1057            throws Exception JavaDoc {
1058        // get header with UID
1059
/*
1060         * ColumbaHeader header = (ColumbaHeader) headerList.get(uid);
1061         * header.getAttributes().put(key, value);
1062         */

1063
1064        VirtualHeader h = (VirtualHeader) headerList.get(uid);
1065        h.getAttributes().put(key, value);
1066        IMailbox sourceFolder = h.getSrcFolder();
1067        Object JavaDoc sourceUid = h.getSrcUid();
1068
1069        sourceFolder.setAttribute(sourceUid, key, value);
1070    }
1071
1072    public Attributes getAttributes(Object JavaDoc uid) throws Exception JavaDoc {
1073        VirtualHeader h = (VirtualHeader) headerList.get(uid);
1074        IMailbox sourceFolder = h.getSrcFolder();
1075        Object JavaDoc sourceUid = h.getSrcUid();
1076
1077        return sourceFolder.getAttributes(sourceUid);
1078
1079        /*
1080         * if (getHeaderList().containsKey(uid)) { return
1081         * getHeaderList().get(uid).getAttributes(); } else { return null; }
1082         */

1083    }
1084
1085    /*
1086     * (non-Javadoc)
1087     *
1088     * @see org.columba.mail.folder.IMailbox#addMessage(java.io.InputStream,
1089     * org.columba.ristretto.message.Attributes)
1090     */

1091    public Object JavaDoc addMessage(InputStream JavaDoc in, Attributes attributes, Flags flags)
1092            throws Exception JavaDoc {
1093
1094        // not supported
1095

1096        return null;
1097    }
1098
1099    /**
1100     * @see org.columba.mail.folder.AbstractFolder#supportsMove()
1101     */

1102    public boolean supportsMove() {
1103        return true;
1104    }
1105
1106    /**
1107     * @see org.columba.mail.folder.IMailbox#getAllHeaderFields(java.lang.Object)
1108     */

1109    public Header getAllHeaderFields(Object JavaDoc uid) throws Exception JavaDoc {
1110        VirtualHeader h = (VirtualHeader) headerList.get(uid);
1111        IMailbox sourceFolder = h.getSrcFolder();
1112        Object JavaDoc sourceUid = h.getSrcUid();
1113
1114        return sourceFolder.getAllHeaderFields(sourceUid);
1115    }
1116
1117    /**
1118     * @see org.columba.mail.folder.IMailbox#expungeFolder()
1119     */

1120    public void expungeFolder() throws Exception JavaDoc {
1121        IMailFolder srcFolder = getSourceFolder();
1122
1123        boolean isInclude = Boolean.valueOf(
1124                getConfiguration().getString("property", "include_subfolders"))
1125                .booleanValue();
1126
1127        if (isInclude) {
1128            recursiveExpunge(srcFolder);
1129        } else {
1130            if (srcFolder instanceof IMailbox)
1131                ((IMailbox) srcFolder).expungeFolder();
1132        }
1133    }
1134
1135    private void recursiveExpunge(IMailFolder srcFolder) throws Exception JavaDoc {
1136        IMailFolder folder;
1137
1138        if (srcFolder instanceof IMailbox)
1139            ((IMailbox) srcFolder).expungeFolder();
1140
1141        for (Enumeration JavaDoc e = srcFolder.children(); e.hasMoreElements();) {
1142            folder = (IMailFolder) e.nextElement();
1143
1144            if (folder instanceof VirtualFolder) {
1145                continue;
1146            }
1147
1148            recursiveExpunge(folder);
1149        }
1150
1151    }
1152
1153    /*
1154     * (non-Javadoc)
1155     *
1156     * @see org.columba.mail.folder.IMailFolder#getRootFolder()
1157     */

1158    public IMailFolder getRootFolder() {
1159        return getSourceFolder().getRootFolder();
1160    }
1161
1162    /*
1163     * (non-Javadoc)
1164     *
1165     * @see org.columba.mail.folder.event.IFolderListener#messageAdded(org.columba.mail.folder.event.IFolderEvent)
1166     */

1167    public void messageAdded(IFolderEvent e) {
1168        // deactivate the folder
1169
deactivate();
1170        return;
1171        /*
1172         * AbstractMessageFolder folder = (AbstractMessageFolder)e.getSource();
1173         *
1174         * try { Object[] resultUids = folder.searchMessages(getFilter(), new
1175         * Object[] {e.getChanges()});
1176         *
1177         * if( resultUids.length > 0 ) { Header h =
1178         * folder.getHeaderFields(resultUids[0],
1179         * CachedHeaderfields.getDefaultHeaderfields()); ColumbaHeader header =
1180         * new ColumbaHeader(h);
1181         * header.setAttributes(folder.getAttributes(resultUids[0]));
1182         * header.setFlags(folder.getFlags(resultUids[0]));
1183         *
1184         * Object uid = add(header, folder, resultUids[0]);
1185         * fireMessageAdded(uid, getFlags(uid)); } } catch (Exception e1) {
1186         * e1.printStackTrace(); }
1187         */

1188    }
1189
1190    /*
1191     * (non-Javadoc)
1192     *
1193     * @see org.columba.mail.folder.event.IFolderListener#messageRemoved(org.columba.mail.folder.event.IFolderEvent)
1194     */

1195    public void messageRemoved(IFolderEvent e) {
1196        Object JavaDoc srcUid = e.getChanges();
1197
1198        Object JavaDoc vUid = srcUidToVirtualUid((IMailFolder) e.getSource(), srcUid);
1199        if (vUid != null) {
1200            headerList.remove(vUid);
1201
1202            // notify listeners
1203
fireMessageRemoved(vUid, null);
1204        }
1205    }
1206
1207    protected boolean hasFlagsCriteria() {
1208        boolean result = false;
1209
1210        IFilterRule rule = getFilter().getFilterRule();
1211
1212        for (int i = 0; i < rule.count() && !result; i++) {
1213            result = rule.get(i).getTypeString().equalsIgnoreCase("FLAGS");
1214        }
1215
1216        return result;
1217    }
1218
1219    /*
1220     * (non-Javadoc)
1221     *
1222     * @see org.columba.mail.folder.event.IFolderListener#messageFlagChanged(org.columba.mail.folder.event.IFolderEvent)
1223     */

1224    public void messageFlagChanged(IFolderEvent e) {
1225        Object JavaDoc virtualUid = srcUidToVirtualUid((IMailFolder) e.getSource(), e
1226                .getChanges());
1227
1228        if (virtualUid == null && hasFlagsCriteria()) {
1229
1230            AbstractMessageFolder folder = (AbstractMessageFolder) e
1231                    .getSource();
1232            try {
1233                Object JavaDoc[] resultUids = folder.searchMessages(getFilter(),
1234                        new Object JavaDoc[] { e.getChanges() });
1235
1236                if (resultUids.length > 0) {
1237                    Header h = folder.getHeaderFields(resultUids[0],
1238                            CachedHeaderfields.getDefaultHeaderfields());
1239                    ColumbaHeader header = new ColumbaHeader(h);
1240                    header.setAttributes(folder.getAttributes(resultUids[0]));
1241                    header.setFlags(folder.getFlags(resultUids[0]));
1242
1243                    Object JavaDoc uid = add(header, folder, resultUids[0]);
1244                    fireMessageAdded(uid, getFlags(uid));
1245                }
1246            } catch (Exception JavaDoc e1) {
1247                e1.printStackTrace();
1248            }
1249        }
1250
1251        if (virtualUid != null) {
1252            // Update the Virtual Header
1253

1254            VirtualHeader h = (VirtualHeader) headerList.get(virtualUid);
1255            AbstractMessageFolder folder = (AbstractMessageFolder) e
1256                    .getSource();
1257            try {
1258                h.setAttributes(folder.getAttributes(e.getChanges()));
1259                h.setFlags(folder.getFlags(e.getChanges()));
1260
1261                updateMailFolderInfo(e.getOldFlags(), e.getParameter());
1262            } catch (Exception JavaDoc e1) {
1263            }
1264
1265            // fire updates
1266
fireMessageFlagChanged(virtualUid, e.getOldFlags(), e
1267                    .getParameter());
1268        }
1269    }
1270
1271    /*
1272     * (non-Javadoc)
1273     *
1274     * @see org.columba.mail.folder.event.IFolderListener#folderPropertyChanged(org.columba.mail.folder.event.IFolderEvent)
1275     */

1276    public void folderPropertyChanged(IFolderEvent e) {
1277        // don't care
1278
}
1279
1280    /*
1281     * (non-Javadoc)
1282     *
1283     * @see org.columba.mail.folder.event.IFolderListener#folderAdded(org.columba.mail.folder.event.IFolderEvent)
1284     */

1285    public void folderAdded(IFolderEvent e) {
1286        if (isRecursive() && !(e.getChanges() instanceof VirtualFolder)) {
1287            AbstractMessageFolder folder = (AbstractMessageFolder) e
1288                    .getChanges();
1289            folder.addFolderListener(this);
1290        }
1291    }
1292
1293    /*
1294     * (non-Javadoc)
1295     *
1296     * @see org.columba.mail.folder.event.IFolderListener#folderRemoved(org.columba.mail.folder.event.IFolderEvent)
1297     */

1298    public void folderRemoved(IFolderEvent e) {
1299        AbstractMessageFolder folder = (AbstractMessageFolder) e.getChanges();
1300        folder.removeFolderListener(this);
1301    }
1302
1303    /**
1304     *
1305     */

1306    public void activate() throws Exception JavaDoc {
1307        if (active)
1308            return;
1309
1310        LOG.fine("Activating virtual folder " + getName());
1311        getMessageFolderInfo().reset();
1312        applySearch();
1313        registerWithSource();
1314        active = true;
1315    }
1316
1317    public void deactivate() {
1318        active = false;
1319        headerList.clear();
1320        getMessageFolderInfo().reset();
1321
1322        unregisterWithSource();
1323    }
1324
1325    /*
1326     * (non-Javadoc)
1327     *
1328     * @see org.columba.mail.folder.IMailFolder#removeFolder()
1329     */

1330    public void removeFolder() throws Exception JavaDoc {
1331        if (active) {
1332            deactivate();
1333        }
1334        super.removeFolder();
1335    }
1336
1337    /**
1338     * @see org.columba.mail.folder.AbstractMessageFolder#getLastSelection()
1339     */

1340    public Object JavaDoc getLastSelection() {
1341        // not supported by virtual folder
1342
return null;
1343    }
1344
1345}
Popular Tags