Source Code Cross Referenced for IMAPFolder.java in  » Mail-Clients » columba-1.4 » org » columba » mail » folder » imap » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Mail Clients » columba 1.4 » org.columba.mail.folder.imap 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // The contents of this file are subject to the Mozilla Public License Version
0002:        // 1.1
0003:        //(the "License"); you may not use this file except in compliance with the
0004:        //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
0005:        //
0006:        //Software distributed under the License is distributed on an "AS IS" basis,
0007:        //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0008:        //for the specific language governing rights and
0009:        //limitations under the License.
0010:        //
0011:        //The Original Code is "The Columba Project"
0012:        //
0013:        //The Initial Developers of the Original Code are Frederik Dietz and Timo
0014:        // Stich.
0015:        //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
0016:        //
0017:        //All Rights Reserved.
0018:
0019:        package org.columba.mail.folder.imap;
0020:
0021:        import java.io.File;
0022:        import java.io.IOException;
0023:        import java.io.InputStream;
0024:        import java.util.ArrayList;
0025:        import java.util.Arrays;
0026:        import java.util.Collections;
0027:        import java.util.LinkedList;
0028:        import java.util.List;
0029:        import java.util.logging.Logger;
0030:
0031:        import org.columba.api.command.IStatusObservable;
0032:        import org.columba.core.base.ListTools;
0033:        import org.columba.core.command.CommandCancelledException;
0034:        import org.columba.core.command.CommandProcessor;
0035:        import org.columba.core.connectionstate.ConnectionStateImpl;
0036:        import org.columba.core.xml.XmlElement;
0037:        import org.columba.mail.command.MailFolderCommandReference;
0038:        import org.columba.mail.config.FolderItem;
0039:        import org.columba.mail.config.IFolderItem;
0040:        import org.columba.mail.config.ImapItem;
0041:        import org.columba.mail.folder.AbstractRemoteFolder;
0042:        import org.columba.mail.folder.IHeaderListCorruptedListener;
0043:        import org.columba.mail.folder.IMailFolder;
0044:        import org.columba.mail.folder.IMailbox;
0045:        import org.columba.mail.folder.RootFolder;
0046:        import org.columba.mail.folder.command.ApplyFilterCommand;
0047:        import org.columba.mail.folder.headercache.BerkeleyDBHeaderList;
0048:        import org.columba.mail.folder.headercache.CachedHeaderfields;
0049:        import org.columba.mail.folder.search.DefaultSearchEngine;
0050:        import org.columba.mail.folder.search.IMAPQueryEngine;
0051:        import org.columba.mail.imap.IImapServer;
0052:        import org.columba.mail.message.ColumbaHeader;
0053:        import org.columba.mail.message.ICloseableIterator;
0054:        import org.columba.mail.message.IColumbaHeader;
0055:        import org.columba.mail.message.IHeaderList;
0056:        import org.columba.mail.message.IPersistantHeaderList;
0057:        import org.columba.mail.parser.PassiveHeaderParserInputStream;
0058:        import org.columba.mail.util.MailResourceLoader;
0059:        import org.columba.ristretto.imap.IMAPException;
0060:        import org.columba.ristretto.imap.IMAPFlags;
0061:        import org.columba.ristretto.imap.MailboxStatus;
0062:        import org.columba.ristretto.imap.SearchKey;
0063:        import org.columba.ristretto.imap.SequenceEntry;
0064:        import org.columba.ristretto.imap.SequenceSet;
0065:        import org.columba.ristretto.message.Attributes;
0066:        import org.columba.ristretto.message.Flags;
0067:        import org.columba.ristretto.message.Header;
0068:        import org.columba.ristretto.message.MimeTree;
0069:
0070:        public class IMAPFolder extends AbstractRemoteFolder {
0071:
0072:            /** JDK 1.4+ logging framework logger, used for logging. */
0073:            private static final Logger LOG = Logger
0074:                    .getLogger("org.columba.mail.folder.imap");
0075:
0076:            /**
0077:             *
0078:             */
0079:            private IImapServer store;
0080:
0081:            private IStatusObservable observable;
0082:
0083:            /**
0084:             *
0085:             */
0086:            protected boolean existsOnServer = true;
0087:
0088:            private boolean readOnly;
0089:
0090:            private IPersistantHeaderList headerList;
0091:
0092:            private boolean firstSync = true;
0093:
0094:            private boolean mailboxSyncEnabled = true;
0095:
0096:            /**
0097:             * @see org.columba.mail.folder.IMailbox#isReadOnly()
0098:             */
0099:            public boolean isReadOnly() {
0100:                return readOnly;
0101:            }
0102:
0103:            /**
0104:             * Constructor for testing purposes only!
0105:             *
0106:             */
0107:            public IMAPFolder(IPersistantHeaderList headerList,
0108:                    IImapServer server) {
0109:                super ("test", "IMAPFolder", "/tmp/");
0110:                this .headerList = headerList;
0111:                this .observable = new DummyObservable();
0112:
0113:                store = server;
0114:            }
0115:
0116:            /**
0117:             * @see org.columba.mail.folder.FolderTreeNode#FolderTreeNode(org.columba.mail.config.FolderItem)
0118:             */
0119:            public IMAPFolder(FolderItem folderItem, String path) {
0120:                super (folderItem, path);
0121:
0122:                DefaultSearchEngine engine = new DefaultSearchEngine(this );
0123:                engine.setNonDefaultEngine(new IMAPQueryEngine(this ));
0124:                setSearchEngine(engine);
0125:
0126:            }
0127:
0128:            /**
0129:             * @param type
0130:             */
0131:            // only called by FolderFactory
0132:            public IMAPFolder(String name, String type, String path)
0133:                    throws Exception {
0134:                super (name, type, path);
0135:
0136:                IFolderItem item = getConfiguration();
0137:                item.setString("property", "accessrights", "user");
0138:                item.setString("property", "subfolder", "true");
0139:            }
0140:
0141:            /**
0142:             * @see org.columba.mail.folder.FolderTreeNode#removeFolder()
0143:             */
0144:            public void removeFolder() throws Exception {
0145:                try {
0146:                    if (existsOnServer) {
0147:                        String path = getImapPath();
0148:
0149:                        getServer().deleteFolder(path);
0150:                    }
0151:
0152:                    super .removeFolder();
0153:                } catch (Exception e) {
0154:                    throw e;
0155:                }
0156:            }
0157:
0158:            public void setName(String name) throws Exception {
0159:                if (getName() == null) { // if creating new folder
0160:                    super .setName(name);
0161:                    return;
0162:                }
0163:
0164:                String oldPath = getImapPath();
0165:                LOG.info("old path=" + oldPath);
0166:
0167:                String newPath = null;
0168:
0169:                if (getParent() instanceof  IMAPFolder) {
0170:                    newPath = ((IMAPFolder) getParent()).getImapPath();
0171:                }
0172:
0173:                newPath += (getServer().getDelimiter() + name);
0174:                LOG.info("new path=" + newPath);
0175:
0176:                getServer().renameFolder(oldPath, newPath);
0177:                super .setName(name);
0178:            }
0179:
0180:            /**
0181:             * Method getStore.
0182:             *
0183:             * @return IMAPStore
0184:             */
0185:            public IImapServer getServer() {
0186:                if (store == null) {
0187:                    store = ((IMAPRootFolder) getRootFolder()).getServer();
0188:                }
0189:
0190:                return store;
0191:            }
0192:
0193:            /**
0194:             * @see org.columba.mail.folder.Folder#getHeaderList(org.columba.api.command.IWorkerStatusController)
0195:             */
0196:            public synchronized IHeaderList getHeaderList() throws Exception {
0197:                if (headerList == null) {
0198:                    // header cache is stored in "headerlist" subfolder
0199:                    File headercacheDirectory = new File(getDirectoryFile(),
0200:                            "headerlist");
0201:                    headerList = new BerkeleyDBHeaderList(headercacheDirectory,
0202:                            getId());
0203:
0204:                    headerList
0205:                            .addHeaderListCorruptedListener(new IHeaderListCorruptedListener() {
0206:
0207:                                public void headerListCorrupted(
0208:                                        IHeaderList headerList) {
0209:                                    headerList.clear();
0210:                                    getMessageFolderInfo().reset();
0211:                                    fireFolderPropertyChanged();
0212:                                }
0213:                            });
0214:
0215:                }
0216:
0217:                if (mailboxSyncEnabled
0218:                        && ConnectionStateImpl.getInstance().isOnline()
0219:                        && !getServer().isSelected(this )) {
0220:                    // Trigger Synchronization
0221:                    CommandProcessor.getInstance().addOp(
0222:                            new CheckForNewMessagesCommand(
0223:                                    new MailFolderCommandReference(this )));
0224:                }
0225:
0226:                return headerList;
0227:            }
0228:
0229:            protected ImapItem getImapItem() {
0230:                return getServer().getItem();
0231:            }
0232:
0233:            protected void printStatusMessage(String message) {
0234:                if (getObservable() != null) {
0235:                    getObservable().setMessage(
0236:                            getImapItem().get("host") + ": " + message);
0237:                }
0238:            }
0239:
0240:            protected void setProgress(int progress) {
0241:                if (getObservable() != null) {
0242:                    getObservable().setCurrent(progress);
0243:                }
0244:            }
0245:
0246:            protected void setMaximum(int progress) {
0247:                if (getObservable() != null) {
0248:                    getObservable().setMax(progress);
0249:                }
0250:            }
0251:
0252:            /**
0253:             * @throws Exception
0254:             * @throws IOException
0255:             * @throws CommandCancelledException
0256:             * @throws IMAPException
0257:             */
0258:            Object[] synchronizeHeaderlist() throws Exception, IOException,
0259:                    CommandCancelledException, IMAPException {
0260:
0261:                Object[] result = new Object[0];
0262:
0263:                // Check if the mailbox has changed
0264:                MailboxStatus status = getServer().getStatus(this );
0265:
0266:                if (status.getMessages() == 0) {
0267:                    purgeHeaderList();
0268:
0269:                    syncMailboxInfo(status);
0270:
0271:                    return result;
0272:                }
0273:
0274:                if (!firstSync
0275:                        && status.getMessages() == this .getMessageFolderInfo()
0276:                                .getExists()) {
0277:                    return result;
0278:                }
0279:
0280:                List localUids = new LinkedList(Arrays.asList(getHeaderList()
0281:                        .getUids()));
0282:                // Sort the uid list
0283:                Collections.sort(localUids);
0284:
0285:                int largestLocalUid = localUids.size() > 0 ? ((Integer) localUids
0286:                        .get(localUids.size() - 1)).intValue()
0287:                        : -1;
0288:
0289:                int largestRemoteUid = getServer().getLargestRemoteUid(this );
0290:
0291:                if (localUids.size() == status.getMessages()
0292:                        && largestRemoteUid == largestLocalUid) {
0293:                    // Seems to be no change!
0294:                    if (firstSync) {
0295:                        firstSync = false;
0296:                        synchronizeFlags(status);
0297:                    } else {
0298:                        syncMailboxInfo(status);
0299:                    }
0300:
0301:                    return result;
0302:                }
0303:
0304:                printStatusMessage(MailResourceLoader.getString("statusbar",
0305:                        "message", "sync_messages"));
0306:
0307:                largestRemoteUid = getServer().fetchUid(
0308:                        new SequenceSet(SequenceEntry.STAR), this );
0309:
0310:                if (largestRemoteUid == -1) {
0311:                    largestRemoteUid = getServer().fetchUid(
0312:                            new SequenceSet(status.getMessages()), this );
0313:                }
0314:
0315:                int largestLocalUidIndex = findLargestLocalUidIndex(localUids);
0316:
0317:                int newMessages = status.getMessages() - largestLocalUidIndex;
0318:
0319:                /*
0320:                 * // Somehow there are new messages that // have a lower index -> out
0321:                 * of sync if (localUids.size() - status.getMessages() + newMessages <
0322:                 * 0) {
0323:                 *
0324:                 * LOG.severe("Folder " + getName() + " is out of sync -> recreating the
0325:                 * cache!"); purgeHeaderList(); // all messages are new newMessages =
0326:                 * status.getMessages(); // Set the index of the largest Uid to 0 // ->
0327:                 * ensure it works with the fetch of new // messages part below
0328:                 * largestLocalUidIndex = 0; largestLocalUid = -1;
0329:                 *
0330:                 * localUids.clear(); }
0331:                 */
0332:                LOG.fine("Found " + newMessages + " new Messages");
0333:
0334:                // If we have new messages add them to the headerlist
0335:                if (newMessages > 0) {
0336:                    printStatusMessage(MailResourceLoader.getString(
0337:                            "statusbar", "message", "fetch_new_headers"));
0338:
0339:                    // Ensure sizes are correct
0340:                    getMessageFolderInfo().setExists(localUids.size());
0341:                    getMessageFolderInfo().setUnseen(
0342:                            Math.min(getMessageFolderInfo().getUnseen(),
0343:                                    localUids.size()));
0344:                    getMessageFolderInfo().setRecent(0);
0345:
0346:                    List newUids = fetchNewMessages(largestLocalUidIndex);
0347:
0348:                    localUids.addAll(newUids);
0349:
0350:                    if (newUids.size() < newMessages) {
0351:                        // There are still more messages to update
0352:                        // -> issue another fetch messages command
0353:                        CommandProcessor.getInstance().addOp(
0354:                                new FetchMessagesCommand(
0355:                                        new MailFolderCommandReference(this ),
0356:                                        newMessages, largestLocalUidIndex,
0357:                                        newUids.size()));
0358:
0359:                    } else {
0360:                        fetchDone();
0361:                    }
0362:
0363:                    result = newUids.toArray(new Object[0]);
0364:                } else {
0365:
0366:                    // Number of deleted messages is computed from exists on imap and
0367:                    // local
0368:                    // newMessages
0369:                    findRemovedMessages(status, localUids);
0370:
0371:                    if (firstSync) {
0372:                        firstSync = false;
0373:                        synchronizeFlags(status);
0374:                    } else {
0375:                        syncMailboxInfo(status);
0376:                    }
0377:                }
0378:
0379:                return result;
0380:            }
0381:
0382:            private int findLargestLocalUidIndex(List localUids)
0383:                    throws IOException, IMAPException,
0384:                    CommandCancelledException {
0385:                int largestLocalUidIndex = -1;
0386:
0387:                printStatusMessage(MailResourceLoader.getString("statusbar",
0388:                        "message", "sync_messages"));
0389:
0390:                // Compute the number of new messages
0391:                if (localUids.size() > 0) {
0392:                    // Find the index of the largest local Uid
0393:                    int position = localUids.size() - 1;
0394:                    while (largestLocalUidIndex == -1
0395:                            && position >= localUids.size() - 10
0396:                            && position >= 0) {
0397:                        largestLocalUidIndex = getServer().getIndex(
0398:                                (Integer) localUids.get(position--), this );
0399:                    }
0400:
0401:                    // Still not found -> do a binary search
0402:                    if (largestLocalUidIndex == -1) {
0403:                        int a, b, c;
0404:                        int index;
0405:                        a = 0;
0406:                        b = position;
0407:                        while (b > a && b - a > 1) {
0408:                            c = Math.round((b - a) * 0.5f) + a;
0409:
0410:                            index = getServer().getIndex(
0411:                                    (Integer) localUids.get(c), this );
0412:                            if (index == -1) {
0413:                                b = c;
0414:                            } else {
0415:                                a = c;
0416:                                largestLocalUidIndex = index;
0417:                            }
0418:                        }
0419:
0420:                        // removedLocalUids = localUids.size() - 1 - position;
0421:                    } else {
0422:                        // -2 because of the decrement in line 317
0423:                        // removedLocalUids = localUids.size() - 2 - position;
0424:                    }
0425:
0426:                    // Check if all local uids have been deleted
0427:                    if (largestLocalUidIndex == -1) {
0428:                        // all messages are new
0429:                        largestLocalUidIndex = 0;
0430:                    }
0431:
0432:                } else {
0433:                    // all messages are new
0434:                    largestLocalUidIndex = 0;
0435:                }
0436:                return largestLocalUidIndex;
0437:            }
0438:
0439:            private void findRemovedMessages(MailboxStatus status,
0440:                    List localUids) throws Exception, IOException,
0441:                    IMAPException, CommandCancelledException {
0442:                int largestRemoteUid = getServer().getLargestRemoteUid(this );
0443:
0444:                int deletedMessages = localUids.size() - status.getMessages();
0445:
0446:                LOG.fine("Found " + deletedMessages + " deleted Messages");
0447:
0448:                // Find the messages that have been deleted
0449:                if (deletedMessages > 0) {
0450:                    int found = 0;
0451:                    // First deleted all local uids that
0452:                    // are larger than the largest remote uid
0453:                    while (localUids.size() > 0
0454:                            && found != deletedMessages
0455:                            && ((Integer) localUids.get(localUids.size() - 1))
0456:                                    .intValue() > largestRemoteUid) {
0457:                        Flags flags = getHeaderList().remove(
0458:                                localUids.get(localUids.size() - 1)).getFlags();
0459:                        fireMessageRemoved(localUids
0460:                                .remove(localUids.size() - 1), flags);
0461:
0462:                        found++;
0463:                    }
0464:
0465:                    // Search in packs beginning from newest to oldest
0466:                    // -> in most cases this should save us a lot of uid fetchings to
0467:                    // find the deleted messages
0468:
0469:                    // Pack size is min 10, max 200 else mailboxsize / 10
0470:                    int packSize = Math.min(Math.max(deletedMessages, status
0471:                            .getMessages() / 10), 200);
0472:
0473:                    int upper = status.getMessages();
0474:
0475:                    int localPointer = localUids.size() - 1;
0476:
0477:                    // Fetch Pack outer loop
0478:                    while (upper >= 1 && found != deletedMessages) {
0479:                        SequenceSet set = new SequenceSet();
0480:                        set.add(Math.max(upper - packSize + 1, 1), upper);
0481:
0482:                        // Fetch these uids and compare them to the
0483:                        // local list
0484:                        Integer[] actUids = getServer().fetchUids(set, this );
0485:
0486:                        // Compare inner loop
0487:                        for (int i = actUids.length - 1; i >= 0
0488:                                && found != deletedMessages; i--) {
0489:
0490:                            // Find missing uids loop
0491:                            while (found != deletedMessages
0492:                                    && localPointer >= 0
0493:                                    && !localUids.get(localPointer).equals(
0494:                                            actUids[i])) {
0495:                                // We found the uid of a deleted message
0496:                                // -> remove it from the headerlist
0497:                                getHeaderList().remove(
0498:                                        localUids.get(localPointer));
0499:
0500:                                found++;
0501:                                localPointer--;
0502:                            }
0503:
0504:                            // next position in the local uid list
0505:                            localPointer--;
0506:                        }
0507:
0508:                        upper = upper - packSize;
0509:                    }
0510:
0511:                    // All the other local mails are deleted
0512:                    while (found < deletedMessages && localPointer >= 0) {
0513:                        getHeaderList().remove(localUids.get(localPointer--));
0514:                        found++;
0515:                    }
0516:
0517:                    if (found != deletedMessages) {
0518:                        LOG.severe("Assertion failed : found only " + found
0519:                                + " of " + deletedMessages);
0520:                    }
0521:
0522:                }
0523:            }
0524:
0525:            private void purgeHeaderList() throws Exception {
0526:                ICloseableIterator it = getHeaderList().keyIterator();
0527:                while (it.hasNext()) {
0528:                    Object uid = it.next();
0529:                    fireMessageRemoved(uid, getHeaderList().get(uid).getFlags());
0530:                }
0531:                it.close();
0532:                getHeaderList().clear();
0533:
0534:                getMessageFolderInfo().reset();
0535:                fireFolderPropertyChanged();
0536:            }
0537:
0538:            List fetchNewMessages(int startIndex) throws IOException,
0539:                    IMAPException, CommandCancelledException, Exception {
0540:                IMAPFlags[] newFlags = getServer().fetchFlagsListStartFrom2(
0541:                        startIndex + 1, this );
0542:
0543:                List newUids = new ArrayList(newFlags.length);
0544:
0545:                // Build a list of the new uids
0546:                for (int i = 0; i < newFlags.length; i++) {
0547:                    // Update the list of new and local uids
0548:                    newUids.add(newFlags[i].getUid());
0549:                }
0550:
0551:                // Fetch the headers of the new messages ...
0552:                getServer().fetchHeaderList(getHeaderList(), newUids, this );
0553:
0554:                // .. and set the flags
0555:                setFlags(newFlags);
0556:
0557:                // fire message added updates
0558:                for (int i = 0; i < newFlags.length; i++) {
0559:                    fireMessageAdded(newFlags[i].getUid(), newFlags[i]);
0560:                }
0561:
0562:                return newUids;
0563:            }
0564:
0565:            private void syncMailboxInfo(MailboxStatus status) {
0566:                boolean updated = false;
0567:                if (status.getMessages() != -1
0568:                        && messageFolderInfo.getExists() != status
0569:                                .getMessages()) {
0570:                    messageFolderInfo.setExists(status.getMessages());
0571:                    updated = true;
0572:                }
0573:
0574:                if (status.getMessages() == 0) {
0575:                    messageFolderInfo.setRecent(0);
0576:                    messageFolderInfo.setUnseen(0);
0577:                    updated = true;
0578:                } else {
0579:
0580:                    if (status.getUnseen() != -1
0581:                            && messageFolderInfo.getUnseen() != status
0582:                                    .getUnseen()) {
0583:                        messageFolderInfo.setUnseen(status.getUnseen());
0584:                        updated = true;
0585:                    }
0586:                }
0587:
0588:                // Sanity tests
0589:                if (messageFolderInfo.getRecent() < 0) {
0590:                    messageFolderInfo.setRecent(0);
0591:                    updated = true;
0592:                }
0593:                if (messageFolderInfo.getRecent() > messageFolderInfo
0594:                        .getExists()) {
0595:                    messageFolderInfo.setRecent(messageFolderInfo.getExists());
0596:                    updated = true;
0597:                }
0598:
0599:                if (messageFolderInfo.getUnseen() < 0) {
0600:                    messageFolderInfo.setUnseen(0);
0601:                    updated = true;
0602:                }
0603:                if (messageFolderInfo.getUnseen() > messageFolderInfo
0604:                        .getExists()) {
0605:                    messageFolderInfo.setUnseen(messageFolderInfo.getExists());
0606:                    updated = true;
0607:                }
0608:
0609:                if (updated) {
0610:                    fireFolderPropertyChanged();
0611:                }
0612:
0613:            }
0614:
0615:            private void synchronizeFlags(MailboxStatus status)
0616:                    throws Exception, IOException, CommandCancelledException,
0617:                    IMAPException {
0618:                printStatusMessage(MailResourceLoader.getString("statusbar",
0619:                        "message", "sync_flags"));
0620:
0621:                MailboxStatus flagStatus = new MailboxStatus();
0622:                flagStatus.setMessages(status.getMessages());
0623:
0624:                // Build the remote lists of messages that are UNSEEN, FLAGGED, DELETED,
0625:                // JUNK
0626:                SearchKey unseenKey = new SearchKey(SearchKey.UNSEEN);
0627:                List remoteUnseenUids = Arrays.asList(getServer().search(
0628:                        unseenKey, this ));
0629:                flagStatus.setUnseen(remoteUnseenUids.size());
0630:
0631:                SearchKey flaggedKey = new SearchKey(SearchKey.FLAGGED);
0632:                List remoteFlaggedUids = Arrays.asList(getServer().search(
0633:                        flaggedKey, this ));
0634:
0635:                SearchKey deletedKey = new SearchKey(SearchKey.DELETED);
0636:                List remoteDeletedUids = Arrays.asList(getServer().search(
0637:                        deletedKey, this ));
0638:
0639:                SearchKey recentKey = new SearchKey(SearchKey.RECENT);
0640:                List remoteRecentUids = Arrays.asList(getServer().search(
0641:                        recentKey, this ));
0642:                flagStatus.setRecent(remoteRecentUids.size());
0643:
0644:                SearchKey junkKey = new SearchKey(SearchKey.KEYWORD, "JUNK");
0645:                List remoteJunkUids = Arrays.asList(getServer().search(junkKey,
0646:                        this ));
0647:
0648:                // update the local flags and ensure that the MailboxInfo is correct
0649:                ICloseableIterator headerIterator = getHeaderList()
0650:                        .headerIterator();
0651:
0652:                int unseen = 0;
0653:                int flagged = 0;
0654:                int recent = 0;
0655:                int deleted = 0;
0656:                int junk = 0;
0657:
0658:                while (headerIterator.hasNext()) {
0659:                    IColumbaHeader header = (IColumbaHeader) headerIterator
0660:                            .next();
0661:                    Object uid = header.get("columba.uid");
0662:
0663:                    Flags flag = header.getFlags();
0664:                    Flags oldFlag = (Flags) flag.clone();
0665:
0666:                    int index;
0667:
0668:                    index = Collections.binarySearch(remoteUnseenUids, uid);
0669:                    flag.setSeen(index < 0);
0670:                    if (!flag.getSeen()) {
0671:                        unseen++;
0672:                    }
0673:
0674:                    index = Collections.binarySearch(remoteDeletedUids, uid);
0675:                    flag.setDeleted(index >= 0);
0676:                    if (flag.getDeleted()) {
0677:                        deleted++;
0678:                    }
0679:
0680:                    index = Collections.binarySearch(remoteFlaggedUids, uid);
0681:                    flag.setFlagged(index >= 0);
0682:                    if (flag.getFlagged()) {
0683:                        flagged++;
0684:                    }
0685:
0686:                    index = Collections.binarySearch(remoteRecentUids, uid);
0687:                    flag.setRecent(index >= 0);
0688:                    if (flag.getRecent()) {
0689:                        recent++;
0690:                    }
0691:
0692:                    index = Collections.binarySearch(remoteJunkUids, uid);
0693:                    header.getAttributes().put("columba.spam",
0694:                            new Boolean(index >= 0));
0695:                    if (index >= 0) {
0696:                        junk++;
0697:                    }
0698:
0699:                    if (!flag.equals(oldFlag)) {
0700:                        getHeaderList().update(uid, header);
0701:
0702:                        fireMessageFlagChanged(uid, oldFlag, 0);
0703:                    }
0704:                }
0705:                headerIterator.close();
0706:
0707:                if (remoteJunkUids.size() != junk
0708:                        || remoteRecentUids.size() != recent
0709:                        || remoteFlaggedUids.size() != flagged
0710:                        || remoteDeletedUids.size() != deleted
0711:                        || remoteUnseenUids.size() != unseen) {
0712:                    // Something is wrong
0713:                    // Sync again
0714:
0715:                    synchronizeHeaderlist();
0716:                    return;
0717:                }
0718:
0719:                syncMailboxInfo(flagStatus);
0720:            }
0721:
0722:            /**
0723:             * Method updateFlags.
0724:             *
0725:             * @param flagsList
0726:             */
0727:            protected void setFlags(Flags[] flagsList) throws Exception {
0728:                for (int i = 0; i < flagsList.length; i++) {
0729:                    IMAPFlags flags = (IMAPFlags) flagsList[i];
0730:
0731:                    Integer uid = (Integer) flags.getUid();
0732:
0733:                    IColumbaHeader header = getHeaderList().get(uid);
0734:
0735:                    Flags localFlags = header.getFlags();
0736:
0737:                    localFlags.setFlags(flags.getFlags());
0738:
0739:                    // Junk flag
0740:                    header.getAttributes().put("columba.spam",
0741:                            Boolean.valueOf(flags.get(IMAPFlags.JUNK)));
0742:
0743:                    getHeaderList().update(uid, header);
0744:                }
0745:            }
0746:
0747:            /**
0748:             * @see org.columba.mail.folder.Folder#getMimeTree(java.lang.Object,
0749:             *      IMAPFolder)
0750:             */
0751:            public MimeTree getMimePartTree(Object uid) throws Exception {
0752:                MimeTree tree = IMAPCache.getInstance().getMimeTree(this , uid);
0753:                if (tree == null) {
0754:                    tree = getServer().getMimeTree(uid, this );
0755:                    IMAPCache.getInstance().addMimeTree(this , uid, tree);
0756:                }
0757:
0758:                return tree;
0759:            }
0760:
0761:            /**
0762:             * Copies a set of messages from this folder to a destination folder.
0763:             * <p>
0764:             * The IMAP copy command also keeps the flags intact. So, there's no need to
0765:             * change these manually.
0766:             *
0767:             * @see org.columba.mail.folder.Folder#innerCopy(org.columba.mail.folder.IMailbox,
0768:             *      java.lang.Object, org.columba.api.command.IWorkerStatusController)
0769:             */
0770:            public void innerCopy(IMailbox destiny, Object[] uids)
0771:                    throws Exception {
0772:                IMAPFolder destFolder = (IMAPFolder) destiny;
0773:                IHeaderList srcHeaderList = getHeaderList();
0774:                IPersistantHeaderList destHeaderList = (IPersistantHeaderList) destFolder
0775:                        .getHeaderList();
0776:
0777:                Object[] destUids = getServer().copy(destFolder, uids, this );
0778:
0779:                if (destUids.length < uids.length) {
0780:                    LOG
0781:                            .warning("Some messages could not be copied because they do not exist anymore!");
0782:                }
0783:
0784:                // Check if maybe no message at all got copied
0785:                // In this case we are finished here
0786:                if (destUids.length == 0)
0787:                    return;
0788:
0789:                // update headerlist of destination-folder
0790:                // -> this is necessary to reflect the changes visually
0791:                // but only do it if the target folder is still in sync!
0792:
0793:                Integer largestDestUid = new Integer(-1);
0794:                ICloseableIterator it = destHeaderList.keyIterator();
0795:                while (it.hasNext()) {
0796:                    Integer uid = (Integer) it.next();
0797:                    if (largestDestUid.compareTo(uid) < 0) {
0798:                        largestDestUid = uid;
0799:                    }
0800:                }
0801:                it.close();
0802:
0803:                if (((Integer) destUids[0]).intValue() == largestDestUid
0804:                        .intValue() + 1) {
0805:                    int j = 0;
0806:                    for (int i = 0; i < uids.length; i++) {
0807:                        IColumbaHeader destHeader = srcHeaderList.get(uids[i]);
0808:                        // Was this message actually copied?
0809:                        if (destHeader != null) {
0810:                            // Copy the header
0811:                            destHeader = (IColumbaHeader) destHeader.clone();
0812:
0813:                            destHeader.set("columba.uid", destUids[j]);
0814:                            destHeaderList.add(destHeader, destUids[j]);
0815:
0816:                            // We need IMAPFlags
0817:                            IMAPFlags flags = new IMAPFlags(destHeader
0818:                                    .getFlags().getFlags());
0819:                            flags.setUid(destUids[j]);
0820:
0821:                            destFolder.fireMessageAdded(flags.getUid(), flags);
0822:                            j++;
0823:                        }
0824:                    }
0825:                }
0826:
0827:            }
0828:
0829:            /**
0830:             * @see org.columba.mail.folder.Folder#markMessage(java.lang.Object, int,
0831:             *      IMAPFolder)
0832:             */
0833:            public void markMessage(Object[] uids, int variant)
0834:                    throws Exception {
0835:                getServer().markMessage(uids, variant, this );
0836:
0837:                super .markMessage(uids, variant);
0838:            }
0839:
0840:            /**
0841:             * @see org.columba.mail.folder.Folder#expungeFolder(java.lang.Object,
0842:             *      org.columba.api.command.IWorkerStatusController)
0843:             */
0844:            public void expungeFolder() throws Exception {
0845:                try {
0846:                    getServer().expunge(this );
0847:                    super .expungeFolder();
0848:                } catch (Exception e) {
0849:                    throw e;
0850:                }
0851:            }
0852:
0853:            /**
0854:             * @see org.columba.mail.folder.Folder#getMessageHeader(java.lang.Object,
0855:             *      org.columba.api.command.IWorkerStatusController)
0856:             * @TODO dont use deprecated method
0857:             */
0858:            public IColumbaHeader getMessageHeader(Object uid) throws Exception {
0859:                return getHeaderList().get(uid);
0860:            }
0861:
0862:            /**
0863:             * Method getImapPath.
0864:             *
0865:             * @return String
0866:             */
0867:            public String getImapPath() throws IOException, IMAPException,
0868:                    CommandCancelledException {
0869:                StringBuffer path = new StringBuffer();
0870:                path.append(getName());
0871:
0872:                IMailFolder child = this ;
0873:
0874:                while (true) {
0875:                    child = (IMailFolder) child.getParent();
0876:
0877:                    if (child instanceof  IMAPRootFolder) {
0878:                        break;
0879:                    }
0880:
0881:                    String n = ((IMAPFolder) child).getName();
0882:
0883:                    path.insert(0, n + getServer().getDelimiter());
0884:                }
0885:
0886:                return path.toString();
0887:            }
0888:
0889:            /**
0890:             * @see org.columba.mail.folder.FolderTreeNode#getDefaultProperties()
0891:             */
0892:            public static XmlElement getDefaultProperties() {
0893:                XmlElement props = new XmlElement("property");
0894:
0895:                props.addAttribute("accessrights", "user");
0896:                props.addAttribute("subfolder", "true");
0897:
0898:                return props;
0899:            }
0900:
0901:            /**
0902:             * @see org.columba.mail.folder.FolderTreeNode#tryToGetLock(java.lang.Object)
0903:             */
0904:            public boolean tryToGetLock(Object locker) {
0905:                // IMAP Folders have no own lock ,but share the lock from the Root
0906:                // to ensure that only one operation can be processed simultanous
0907:                IMailFolder root = getRootFolder();
0908:                if (root == null)
0909:                    throw new IllegalArgumentException("IMAPRoot is null");
0910:
0911:                return root.tryToGetLock(locker);
0912:            }
0913:
0914:            /**
0915:             * @see org.columba.mail.folder.FolderTreeNode#releaseLock()
0916:             */
0917:            public void releaseLock(Object locker) {
0918:                IMailFolder root = getRootFolder();
0919:                if (root == null)
0920:                    throw new IllegalArgumentException("IMAPRoot is null");
0921:
0922:                root.releaseLock(locker);
0923:            }
0924:
0925:            /*
0926:             * (non-Javadoc)
0927:             *
0928:             * @see org.columba.mail.folder.FolderTreeNode#addSubfolder(org.columba.mail.folder.FolderTreeNode)
0929:             */
0930:            public void addSubfolder(IMailFolder child) throws Exception {
0931:                if (child instanceof  IMAPFolder) {
0932:
0933:                    getServer().createMailbox(child.getName(), this );
0934:                }
0935:
0936:                super .addSubfolder(child);
0937:            }
0938:
0939:            /*
0940:             * (non-Javadoc)
0941:             *
0942:             * @see org.columba.mail.folder.Folder#getObservable()
0943:             */
0944:            public IStatusObservable getObservable() {
0945:                if (observable == null) {
0946:                    observable = ((IMAPRootFolder) getRootFolder())
0947:                            .getObservable();
0948:                }
0949:
0950:                return observable;
0951:            }
0952:
0953:            /*
0954:             * (non-Javadoc)
0955:             *
0956:             * @see org.columba.mail.folder.IMailbox#addMessage(java.io.InputStream)
0957:             */
0958:            public Object addMessage(InputStream in, Attributes attributes,
0959:                    Flags flags) throws Exception {
0960:                PassiveHeaderParserInputStream withHeaderInputStream = new PassiveHeaderParserInputStream(
0961:                        in);
0962:
0963:                IMAPFlags imapFlags = new IMAPFlags(flags.getFlags());
0964:
0965:                Integer uid = getServer().append(withHeaderInputStream,
0966:                        imapFlags, this );
0967:
0968:                // Since JUNK is a non-system Flag we have to set it with
0969:                // an addtitional STORE command
0970:                if (((Boolean) attributes.get("columba.spam")).booleanValue()) {
0971:                    imapFlags.set(IMAPFlags.JUNK, true);
0972:
0973:                    getServer().setFlags(new Object[] { uid }, imapFlags, this );
0974:                }
0975:
0976:                // Parser the header
0977:                Header header = withHeaderInputStream.getHeader();
0978:
0979:                // update the HeaderList
0980:                IColumbaHeader cHeader = new ColumbaHeader(header,
0981:                        (Attributes) attributes.clone(), imapFlags);
0982:
0983:                getHeaderList().add(cHeader, uid);
0984:
0985:                fireMessageAdded(uid, cHeader.getFlags());
0986:
0987:                return uid;
0988:            }
0989:
0990:            /*
0991:             * (non-Javadoc)
0992:             *
0993:             * @see org.columba.mail.folder.IMailbox#getHeaderFields(java.lang.Object,
0994:             *      java.lang.String[])
0995:             */
0996:            public Header getHeaderFields(Object uid, String[] keys)
0997:                    throws Exception {
0998:                // get header with UID
0999:                IColumbaHeader header = getHeaderList().get(uid);
1000:
1001:                if (header == null)
1002:                    return new Header();
1003:
1004:                // cached headerfield list
1005:                List cachedList = Arrays.asList(CachedHeaderfields
1006:                        .getDefaultHeaderfields());
1007:
1008:                List keyList = new ArrayList(Arrays.asList(keys));
1009:                ListTools.substract(keyList, cachedList);
1010:
1011:                if (keyList.size() > 0) {
1012:                    return getServer().getHeaders(uid, keys, this );
1013:                } else {
1014:                    return (Header) header.getHeader().clone();
1015:                }
1016:            }
1017:
1018:            /*
1019:             * (non-Javadoc)
1020:             *
1021:             * @see org.columba.mail.folder.IMailbox#getMessageSourceStream(java.lang.Object)
1022:             */
1023:            public InputStream getMessageSourceStream(Object uid)
1024:                    throws Exception {
1025:                return getServer().getMessageSourceStream(uid, this );
1026:            }
1027:
1028:            /*
1029:             * (non-Javadoc)
1030:             *
1031:             * @see org.columba.mail.folder.IMailbox#getMimePartSourceStream(java.lang.Object,
1032:             *      java.lang.Integer[])
1033:             */
1034:            public InputStream getMimePartSourceStream(Object uid,
1035:                    Integer[] address) throws Exception {
1036:                return getServer().getMimePartSourceStream(uid, address, this );
1037:            }
1038:
1039:            /**
1040:             *
1041:             *
1042:             * @see org.columba.mail.folder.IMailbox#getMimePartBodyStream(java.lang.Object,
1043:             *      java.lang.Integer[])
1044:             */
1045:            public InputStream getMimePartBodyStream(Object uid,
1046:                    Integer[] address) throws Exception {
1047:                InputStream result = IMAPCache.getInstance().getMimeBody(this ,
1048:                        uid, address);
1049:                if (result == null) {
1050:                    LOG.fine("Cache miss - fetching from server");
1051:                    result = IMAPCache.getInstance().addMimeBody(
1052:                            this ,
1053:                            uid,
1054:                            address,
1055:                            getServer().getMimePartBodyStream(uid, address,
1056:                                    this ));
1057:                }
1058:                return result;
1059:            }
1060:
1061:            /*
1062:             * (non-Javadoc)
1063:             *
1064:             * @see org.columba.mail.folder.Folder#isInboxFolder()
1065:             */
1066:            public boolean isInboxFolder() {
1067:                RootFolder root = (RootFolder) getRootFolder();
1068:
1069:                if (root != null) {
1070:                    return root.getInboxFolder() == this ;
1071:                } else {
1072:                    return false;
1073:                }
1074:            }
1075:
1076:            /*
1077:             * (non-Javadoc)
1078:             *
1079:             * @see org.columba.mail.folder.Folder#isTrashFolder()
1080:             */
1081:            public boolean isTrashFolder() {
1082:                RootFolder root = (RootFolder) getRootFolder();
1083:
1084:                if (root != null) {
1085:                    return root.getTrashFolder() == this ;
1086:                } else {
1087:                    return false;
1088:                }
1089:            }
1090:
1091:            /*
1092:             * (non-Javadoc)
1093:             *
1094:             * @see org.columba.mail.folder.IMailbox#addMessage(java.io.InputStream,
1095:             *      org.columba.ristretto.message.Attributes)
1096:             */
1097:            public Object addMessage(InputStream in) throws Exception {
1098:                PassiveHeaderParserInputStream withHeaderInputStream = new PassiveHeaderParserInputStream(
1099:                        in);
1100:
1101:                Integer uid = getServer().append(withHeaderInputStream, this );
1102:
1103:                if (getServer().isSelected(this )) {
1104:                    // update the HeaderList
1105:                    Header header = withHeaderInputStream.getHeader();
1106:                    ColumbaHeader h = new ColumbaHeader(header);
1107:                    getHeaderList().add(h, uid);
1108:
1109:                    fireMessageAdded(uid, h.getFlags());
1110:                } else {
1111:                    if (mailboxSyncEnabled) {
1112:                        // Trigger Synchronization
1113:                        CommandProcessor.getInstance().addOp(
1114:                                new CheckForNewMessagesCommand(
1115:                                        new MailFolderCommandReference(this )));
1116:                    }
1117:                }
1118:
1119:                return uid;
1120:            }
1121:
1122:            /**
1123:             * @see org.columba.mail.folder.Folder#getHeaderListStorage()
1124:             */
1125:            /*
1126:             * public IHeaderListStorage getHeaderListStorage() { if (attributeStorage ==
1127:             * null) attributeStorage = new RemoteHeaderListStorage(this);
1128:             *
1129:             * return attributeStorage; }
1130:             */
1131:
1132:            /**
1133:             * @see org.columba.mail.folder.Folder#getSearchEngineInstance()
1134:             */
1135:            public DefaultSearchEngine getSearchEngine() {
1136:                if (searchEngine == null) {
1137:                    searchEngine = new DefaultSearchEngine(this );
1138:                    searchEngine.setNonDefaultEngine(new IMAPQueryEngine(this ));
1139:                }
1140:
1141:                return searchEngine;
1142:            }
1143:
1144:            /**
1145:             * @see org.columba.mail.folder.IMailbox#getAllHeaderFields(java.lang.Object)
1146:             */
1147:            public Header getAllHeaderFields(Object uid) throws Exception {
1148:                return getServer().getAllHeaders(uid, this );
1149:
1150:            }
1151:
1152:            /**
1153:             * @see org.columba.mail.folder.AbstractFolder#supportsAddFolder()
1154:             */
1155:            public boolean supportsAddFolder(String folder) {
1156:                return true;
1157:            }
1158:
1159:            /**
1160:             * This is called from the UpdateFlagCommand which gets triggered from an
1161:             * unexpected flags updated.
1162:             *
1163:             * @param flag
1164:             * @throws IOException
1165:             * @throws CommandCancelledException
1166:             * @throws IMAPException
1167:             */
1168:            public void updateFlag(IMAPFlags flag) throws Exception,
1169:                    CommandCancelledException {
1170:                if (getServer().isSelected(this )) {
1171:                    Integer uid = new Integer(getServer().fetchUid(
1172:                            new SequenceSet(flag.getIndex()), this ));
1173:                    flag.setUid(uid);
1174:                    setFlags(new Flags[] { flag });
1175:                }
1176:            }
1177:
1178:            /**
1179:             * @param readOnly
1180:             *            The readOnly to set.
1181:             */
1182:            public void setReadOnly(boolean readOnly) {
1183:                this .readOnly = readOnly;
1184:            }
1185:
1186:            /*
1187:             * (non-Javadoc)
1188:             *
1189:             * @see org.columba.mail.folder.AbstractMessageFolder#save()
1190:             */
1191:            public void save() throws Exception {
1192:                super .save();
1193:
1194:                if (headerList != null)
1195:                    headerList.persist();
1196:            }
1197:
1198:            void fetchDone() throws IOException, CommandCancelledException,
1199:                    IMAPException, Exception {
1200:                MailboxStatus status = getServer().getStatus(this );
1201:
1202:                List localUids = new LinkedList(Arrays.asList(getHeaderList()
1203:                        .getUids()));
1204:                // Sort the uid list
1205:                Collections.sort(localUids);
1206:
1207:                // Number of deleted messages is computed from exists on imap and local
1208:                // newMessages
1209:                findRemovedMessages(status, localUids);
1210:
1211:                if (firstSync) {
1212:                    firstSync = false;
1213:                    synchronizeFlags(status);
1214:                } else {
1215:                    syncMailboxInfo(status);
1216:                }
1217:
1218:                // Apply filter if enabled
1219:                ImapItem item = getServer().getItem();
1220:
1221:                boolean applyFilter = item.getBooleanWithDefault(
1222:                        "automatically_apply_filter", false);
1223:
1224:                // if "automatically apply filter" is selected & there
1225:                // are
1226:                // new
1227:                // messages
1228:                if (applyFilter) {
1229:                    CommandProcessor.getInstance().addOp(
1230:                            new ApplyFilterCommand(
1231:                                    new MailFolderCommandReference(this )));
1232:                }
1233:
1234:                // Reenable Updating the mailbox
1235:                mailboxSyncEnabled = true;
1236:            }
1237:
1238:            /**
1239:             * @return Returns the mailboxSyncEnabled.
1240:             */
1241:            public boolean isMailboxSyncEnabled() {
1242:                return mailboxSyncEnabled;
1243:            }
1244:
1245:            /**
1246:             * @param mailboxSyncEnabled
1247:             *            The mailboxSyncEnabled to set.
1248:             */
1249:            public void setMailboxSyncEnabled(boolean mailboxSyncEnabled) {
1250:                this.mailboxSyncEnabled = mailboxSyncEnabled;
1251:            }
1252:
1253:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.