Source Code Cross Referenced for ImapMailbox.java in  » IDE » J » org » armedbear » j » mail » 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 » IDE » J » org.armedbear.j.mail 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ImapMailbox.java
0003:         *
0004:         * Copyright (C) 2000-2003 Peter Graves
0005:         * $Id: ImapMailbox.java,v 1.5 2003/08/09 17:41:41 piso Exp $
0006:         *
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License
0009:         * as published by the Free Software Foundation; either version 2
0010:         * of the License, or (at your option) any later version.
0011:         *
0012:         * This program is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015:         * GNU General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU General Public License
0018:         * along with this program; if not, write to the Free Software
0019:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0020:         */
0021:
0022:        package org.armedbear.j.mail;
0023:
0024:        import java.io.UnsupportedEncodingException;
0025:        import java.net.MalformedURLException;
0026:        import java.util.ArrayList;
0027:        import java.util.Collections;
0028:        import java.util.HashMap;
0029:        import java.util.Iterator;
0030:        import java.util.List;
0031:        import javax.swing.SwingUtilities;
0032:        import org.armedbear.j.BackgroundProcess;
0033:        import org.armedbear.j.Buffer;
0034:        import org.armedbear.j.BufferIterator;
0035:        import org.armedbear.j.Debug;
0036:        import org.armedbear.j.Editor;
0037:        import org.armedbear.j.EditorIterator;
0038:        import org.armedbear.j.File;
0039:        import org.armedbear.j.FastStringBuffer;
0040:        import org.armedbear.j.Frame;
0041:        import org.armedbear.j.Headers;
0042:        import org.armedbear.j.InputDialog;
0043:        import org.armedbear.j.Line;
0044:        import org.armedbear.j.Log;
0045:        import org.armedbear.j.MessageDialog;
0046:        import org.armedbear.j.ProgressNotifier;
0047:        import org.armedbear.j.Property;
0048:        import org.armedbear.j.Sidebar;
0049:        import org.armedbear.j.StatusBar;
0050:        import org.armedbear.j.StatusBarProgressNotifier;
0051:        import org.armedbear.j.Utilities;
0052:        import org.armedbear.j.View;
0053:
0054:        public final class ImapMailbox extends Mailbox {
0055:            private static final int DEFAULT_PORT = 143;
0056:
0057:            private final ImapSession session;
0058:            private final String folderName;
0059:
0060:            private int messageCount = -1;
0061:            private int uidValidity;
0062:            private int uidLast;
0063:            private ImapMailboxCache mailboxCache;
0064:            private boolean cancelled;
0065:            private Thread backgroundThread;
0066:
0067:            public ImapMailbox(ImapURL url, ImapSession session) {
0068:                super (url);
0069:                this .session = session;
0070:                session.setMailbox(this );
0071:                String tunnel = getStringProperty(Property.TUNNEL);
0072:                if (tunnel != null) {
0073:                    Log.debug("tunnel = |" + tunnel + "|");
0074:                    session.setTunnel(tunnel);
0075:                }
0076:                folderName = session.getFolderName();
0077:                Debug.assertTrue(folderName.equals(url.getFolderName()));
0078:                supportsUndo = false;
0079:                type = TYPE_MAILBOX;
0080:                mode = MailboxMode.getMode();
0081:                formatter = mode.getFormatter(this );
0082:                readOnly = true;
0083:                setInitialized(true);
0084:                Log.debug("ImapMailbox constructor ".concat(url
0085:                        .getCanonicalName()));
0086:            }
0087:
0088:            public String getFileNameForDisplay() {
0089:                FastStringBuffer sb = new FastStringBuffer(64);
0090:                sb.append(url.toString());
0091:                String limitPattern = getLimitPattern();
0092:                if (limitPattern != null) {
0093:                    sb.append(' ');
0094:                    sb.append(limitPattern);
0095:                }
0096:                return sb.toString();
0097:            }
0098:
0099:            public String getName() {
0100:                FastStringBuffer sb = new FastStringBuffer();
0101:                sb.append('{');
0102:                sb.append(session.getUser());
0103:                sb.append('@');
0104:                sb.append(session.getHost());
0105:                sb.append(':');
0106:                sb.append(session.getPort());
0107:                sb.append('}');
0108:                sb.append(folderName);
0109:                return sb.toString();
0110:            }
0111:
0112:            public final ImapSession getSession() {
0113:                return session;
0114:            }
0115:
0116:            public final String getFolderName() {
0117:                return folderName;
0118:            }
0119:
0120:            public final int getUidValidity() {
0121:                return uidValidity;
0122:            }
0123:
0124:            public final int getMessageCount() {
0125:                return messageCount;
0126:            }
0127:
0128:            public synchronized long getLastErrorMillis() {
0129:                return session.getLastErrorMillis();
0130:            }
0131:
0132:            public void setAlertText(final String s) {
0133:                Log.debug("alert = " + s);
0134:                Runnable r = new Runnable() {
0135:                    public void run() {
0136:                        Editor.currentEditor().status(s);
0137:                    }
0138:                };
0139:                SwingUtilities.invokeLater(r);
0140:            }
0141:
0142:            public void setStatusText(final String s) {
0143:                Log.debug("status = " + s);
0144:                Runnable r = new Runnable() {
0145:                    public void run() {
0146:                        Editor.currentEditor().status(s);
0147:                    }
0148:                };
0149:                SwingUtilities.invokeLater(r);
0150:            }
0151:
0152:            public void messageExpunged(int messageNumber) {
0153:                // Invalidate message count.
0154:                messageCount = -1;
0155:            }
0156:
0157:            public void expunge() {
0158:                Runnable expungeRunnable = new Runnable() {
0159:                    public void run() {
0160:                        try {
0161:                            if (session.verifyConnected()
0162:                                    && session.verifySelected(folderName)) {
0163:                                if (session.isReadOnly()) {
0164:                                    Log
0165:                                            .debug("expunge - read-only - reselecting...");
0166:                                    session.reselect(folderName);
0167:                                    if (session.isReadOnly()) {
0168:                                        Log
0169:                                                .error("expunge - mailbox is read-only");
0170:                                        readOnlyError();
0171:                                        return;
0172:                                    }
0173:                                }
0174:                                if (messageCache != null)
0175:                                    messageCache
0176:                                            .removeDeletedEntries(Collections
0177:                                                    .unmodifiableList(entries));
0178:                                if (session.close()) {
0179:                                    Log
0180:                                            .debug("expunge back from close(), calling reselect()");
0181:                                    if (session.reselect(folderName)) {
0182:                                        Log
0183:                                                .debug("expunge back from reselect()");
0184:                                        getAllMessageHeaders();
0185:                                        refreshBuffer();
0186:                                        setBusy(false);
0187:                                        for (int i = 0; i < Editor
0188:                                                .getFrameCount(); i++) {
0189:                                            Frame frame = Editor.getFrame(i);
0190:                                            if (frame != null) {
0191:                                                StatusBar statusBar = frame
0192:                                                        .getStatusBar();
0193:                                                if (statusBar != null)
0194:                                                    statusBar.setText(null);
0195:                                            }
0196:                                        }
0197:                                        updateDisplay();
0198:                                        return;
0199:                                    }
0200:                                }
0201:                                // Error!
0202:                                error("Operation failed", "Expunge");
0203:                            }
0204:                        } finally {
0205:                            setBusy(false);
0206:                            unlock();
0207:                        }
0208:                    }
0209:                };
0210:                if (lock()) {
0211:                    setBusy(true);
0212:                    saveDisplayState();
0213:                    new Thread(expungeRunnable).start();
0214:                }
0215:            }
0216:
0217:            public synchronized int load() {
0218:                if (isLoaded()) {
0219:                    return LOAD_COMPLETED;
0220:                } else if (lock()) {
0221:                    Debug.assertTrue(backgroundThread == null);
0222:                    backgroundThread = new Thread(loadProcess);
0223:                    backgroundThread.start();
0224:                    setLoaded(true);
0225:                    return LOAD_PENDING;
0226:                } else {
0227:                    // Not loaded, lock() failed. Shouldn't happen.
0228:                    Debug.bug("ImapMailbox.load can't lock mailbox");
0229:                    return LOAD_FAILED;
0230:                }
0231:            }
0232:
0233:            private BackgroundProcess loadProcess = new BackgroundProcess() {
0234:                public void run() {
0235:                    Runnable completionRunnable = null;
0236:                    try {
0237:                        cancelled = false;
0238:                        setBusy(true);
0239:                        setBackgroundProcess(this );
0240:                        if (getAllMessageHeaders()) {
0241:                            refreshBuffer();
0242:                            completionRunnable = new Runnable() {
0243:                                public void run() {
0244:                                    setBusy(false);
0245:                                    for (EditorIterator it = new EditorIterator(); it
0246:                                            .hasNext();) {
0247:                                        Editor ed = it.nextEditor();
0248:                                        View view = new View();
0249:                                        view.setDotEntry(getInitialEntry());
0250:                                        ed.setView(ImapMailbox.this , view);
0251:                                        if (ed.getBuffer() == ImapMailbox.this ) {
0252:                                            ed.bufferActivated(true);
0253:                                            ed.updateDisplay();
0254:                                        }
0255:                                    }
0256:                                }
0257:                            };
0258:                        } else {
0259:                            // Error or user cancelled.
0260:                            completionRunnable = new Runnable() {
0261:                                public void run() {
0262:                                    if (Editor.getBufferList().contains(
0263:                                            ImapMailbox.this ))
0264:                                        kill();
0265:                                    for (EditorIterator it = new EditorIterator(); it
0266:                                            .hasNext();)
0267:                                        it.nextEditor().updateDisplay();
0268:                                }
0269:                            };
0270:                        }
0271:                    } finally {
0272:                        setBackgroundProcess(null);
0273:                        backgroundThread = null;
0274:                        unlock();
0275:                        if (completionRunnable != null)
0276:                            SwingUtilities.invokeLater(completionRunnable);
0277:                    }
0278:                }
0279:
0280:                public void cancel() {
0281:                    abort();
0282:                }
0283:            };
0284:
0285:            private void abort() {
0286:                Log.debug("ImapMailbox.abort");
0287:                cancelled = true;
0288:                if (backgroundThread != null && backgroundThread.isAlive())
0289:                    backgroundThread.interrupt();
0290:                session.disconnect();
0291:            }
0292:
0293:            public final void getNewMessages() {
0294:                if (lock())
0295:                    getNewMessages(true);
0296:                else
0297:                    Editor.currentEditor().status("Mailbox is locked");
0298:            }
0299:
0300:            public void getNewMessages(boolean interactive) {
0301:                Debug.assertTrue(isLocked());
0302:                setBusy(true);
0303:                if (interactive)
0304:                    saveDisplayState();
0305:                Debug.assertTrue(backgroundThread == null);
0306:                backgroundThread = new Thread(new GetNewMessagesProcess(
0307:                        interactive));
0308:                backgroundThread.start();
0309:            }
0310:
0311:            private class GetNewMessagesProcess implements  BackgroundProcess {
0312:                private final boolean interactive;
0313:
0314:                public GetNewMessagesProcess(boolean interactive) {
0315:                    this .interactive = interactive;
0316:                }
0317:
0318:                public void run() {
0319:                    cancelled = false;
0320:                    setBackgroundProcess(this );
0321:                    boolean changed = false;
0322:                    if (interactive)
0323:                        changed = clearRecent();
0324:                    try {
0325:                        // verifyConnected() sends a NOOP command to the server, which
0326:                        // gives the server a chance to report changes to the mailbox.
0327:                        if (!session.verifyConnected()) {
0328:                            Log
0329:                                    .error("GetNewMessagesProcess.run can't connect");
0330:                            return;
0331:                        }
0332:                        if (cancelled) {
0333:                            Log.debug("cancelled, disconnecting...");
0334:                            session.disconnect();
0335:                            return;
0336:                        }
0337:                        if (!session.verifySelected(folderName)) {
0338:                            Log.error("GetNewMessagesProcess.run can't select "
0339:                                    + folderName);
0340:                            return;
0341:                        }
0342:                        if (cancelled) {
0343:                            Log.debug("cancelled, disconnecting...");
0344:                            session.disconnect();
0345:                            return;
0346:                        }
0347:                        if (session.isReadOnly()) {
0348:                            Log.warn("GetNewMessagesProcess.run " + folderName
0349:                                    + " is read-only, returning...");
0350:                            return;
0351:                        }
0352:                        if (uidValidity != session.getUidValidity()) {
0353:                            getAllMessageHeaders();
0354:                            changed = true;
0355:                        } else if (interactive) {
0356:                            changed = getNewMessageHeaders() || changed;
0357:                        } else {
0358:                            // Not interactive.
0359:                            if (session.getMessageCount() != messageCount) {
0360:                                Log.debug("session.getMessageCount() = "
0361:                                        + session.getMessageCount()
0362:                                        + " mailbox message count = "
0363:                                        + messageCount);
0364:                                changed = getNewMessageHeaders();
0365:                            }
0366:                        }
0367:                        if (cancelled) {
0368:                            Log.debug("cancelled, disconnecting...");
0369:                            session.disconnect();
0370:                        }
0371:                    } finally {
0372:                        setBackgroundProcess(null);
0373:                        backgroundThread = null;
0374:                        if (changed) {
0375:                            refreshBuffer();
0376:                            setBusy(false);
0377:                            updateDisplay();
0378:                            newMessagesStatus();
0379:                        } else {
0380:                            setBusy(false);
0381:                            for (EditorIterator it = new EditorIterator(); it
0382:                                    .hasNext();) {
0383:                                Editor ed = it.nextEditor();
0384:                                if (ed != null
0385:                                        && ed.getBuffer() == ImapMailbox.this )
0386:                                    ed.setDefaultCursor();
0387:                            }
0388:                        }
0389:                        setLastCheckMillis(System.currentTimeMillis());
0390:                        unlock();
0391:                    }
0392:                }
0393:
0394:                public void cancel() {
0395:                    abort();
0396:                }
0397:            }
0398:
0399:            public void createFolder() {
0400:                final Editor editor = Editor.currentEditor();
0401:                final String input = InputDialog.showInputDialog(editor,
0402:                        "Folder:", "Create Folder");
0403:                if (input == null || input.length() == 0)
0404:                    return;
0405:                final String name = extractFolderName(input);
0406:                if (name == null)
0407:                    return;
0408:                Runnable createRunnable = new Runnable() {
0409:                    public void run() {
0410:                        boolean succeeded = false;
0411:                        try {
0412:                            if (session.verifyConnected()
0413:                                    && session.verifySelected(folderName)) {
0414:                                session.setEcho(true);
0415:                                session.writeTagged("create " + name);
0416:                                succeeded = session.getResponse() == ImapSession.OK;
0417:                                session.setEcho(false);
0418:                            }
0419:                        } finally {
0420:                            unlock();
0421:                            setBusy(false);
0422:                            Editor.updateDisplayLater(ImapMailbox.this );
0423:                            if (succeeded)
0424:                                success("Folder created");
0425:                            else
0426:                                error("Unable to create folder", "Error");
0427:                        }
0428:                    }
0429:                };
0430:                // Even though we're not changing this mailbox per se, we need to lock
0431:                // it here so we have exclusive use of the session.
0432:                if (lock()) {
0433:                    setBusy(true);
0434:                    new Thread(createRunnable).start();
0435:                }
0436:            }
0437:
0438:            public void deleteFolder() {
0439:                final Editor editor = Editor.currentEditor();
0440:                final String input = InputDialog.showInputDialog(editor,
0441:                        "Folder:", "Delete Folder");
0442:                if (input == null || input.length() == 0)
0443:                    return;
0444:                final String name = extractFolderName(input);
0445:                if (name == null)
0446:                    return;
0447:                String message = "Delete folder \"" + name + "\" on "
0448:                        + session.getHost() + "?";
0449:                if (!editor.confirm("Delete Folder", message))
0450:                    return;
0451:                Runnable deleteFolderRunnable = new Runnable() {
0452:                    public void run() {
0453:                        boolean succeeded = false;
0454:                        try {
0455:                            if (session.verifyConnected()
0456:                                    && session.verifySelected(folderName)) {
0457:                                session.setEcho(true);
0458:                                session.writeTagged("delete " + name);
0459:                                succeeded = session.getResponse() == ImapSession.OK;
0460:                                session.setEcho(false);
0461:                            }
0462:                        } finally {
0463:                            unlock();
0464:                            setBusy(false);
0465:                            Editor.updateDisplayLater(ImapMailbox.this );
0466:                            if (succeeded)
0467:                                success("Folder deleted");
0468:                            else
0469:                                error("Unable to delete folder", "Error");
0470:                        }
0471:                    }
0472:                };
0473:                // Even though we're not changing this mailbox per se, we need to lock
0474:                // it here so we have exclusive use of the session.
0475:                if (lock()) {
0476:                    setBusy(true);
0477:                    new Thread(deleteFolderRunnable).start();
0478:                }
0479:            }
0480:
0481:            public void saveToFolder() {
0482:                final Editor editor = Editor.currentEditor();
0483:                boolean advanceDot = false;
0484:                List list = getTaggedEntries();
0485:                if (list == null) {
0486:                    Line line = editor.getDotLine();
0487:                    if (!(line instanceof  MailboxLine))
0488:                        return;
0489:                    advanceDot = true;
0490:                    list = new ArrayList();
0491:                    list.add(((MailboxLine) line).getMailboxEntry());
0492:                }
0493:                final List toBeCopied = list;
0494:                final int count = toBeCopied.size();
0495:                String title;
0496:                if (count > 1)
0497:                    title = "Save Tagged Messages to Folder";
0498:                else
0499:                    title = "Save Message to Folder";
0500:                FastStringBuffer sb = new FastStringBuffer("Save ");
0501:                sb.append(count);
0502:                sb.append(" message");
0503:                if (count > 1)
0504:                    sb.append('s');
0505:                sb.append(" to:");
0506:                final String destination = ChooseFolderDialog.chooseFolder(
0507:                        editor, sb.toString(), title);
0508:                if (destination == null)
0509:                    return;
0510:                final Line dotLine = advanceDot ? editor.getDotLine() : null;
0511:                Runnable saveRunnable = new Runnable() {
0512:                    public void run() {
0513:                        boolean succeeded = false;
0514:                        try {
0515:                            if (session.verifyConnected()
0516:                                    && session.verifySelected(folderName)) {
0517:                                if (destination.startsWith("mailbox:")) {
0518:                                    // Destination is local.
0519:                                    succeeded = saveLocal(toBeCopied,
0520:                                            destination, false);
0521:                                } else {
0522:                                    session.setEcho(true);
0523:                                    final String messageSet = getMessageSet(toBeCopied);
0524:                                    FastStringBuffer sbuf = new FastStringBuffer(
0525:                                            "uid copy ");
0526:                                    sbuf.append(messageSet);
0527:                                    sbuf.append(' ');
0528:                                    sbuf.append(destination);
0529:                                    if (session.writeTagged(sbuf.toString()))
0530:                                        if (session.getResponse() == ImapSession.OK)
0531:                                            succeeded = true;
0532:                                    session.setEcho(false);
0533:                                }
0534:                            }
0535:                        } finally {
0536:                            if (succeeded && dotLine != null)
0537:                                advanceDot(dotLine);
0538:                            setBusy(false);
0539:                            unlock();
0540:                            editor.updateDisplayLater();
0541:                            if (succeeded) {
0542:                                FastStringBuffer sbuf = new FastStringBuffer(
0543:                                        "Saved ");
0544:                                sbuf.append(toBeCopied.size());
0545:                                sbuf.append(" message");
0546:                                if (toBeCopied.size() != 1)
0547:                                    sbuf.append('s');
0548:                                success(sbuf.toString());
0549:                            } else
0550:                                error("Save failed", "Error");
0551:                        }
0552:                    }
0553:                };
0554:                if (lock()) {
0555:                    setBusy(true);
0556:                    new Thread(saveRunnable).start();
0557:                }
0558:            }
0559:
0560:            public void moveToFolder() {
0561:                final Editor editor = Editor.currentEditor();
0562:                boolean advanceDot = false;
0563:                List list = getTaggedEntries();
0564:                if (list == null) {
0565:                    Line line = editor.getDotLine();
0566:                    if (!(line instanceof  MailboxLine))
0567:                        return;
0568:                    advanceDot = true;
0569:                    list = new ArrayList();
0570:                    list.add(((MailboxLine) line).getMailboxEntry());
0571:                }
0572:                final List toBeMoved = list;
0573:                final int count = toBeMoved.size();
0574:                String title;
0575:                if (count > 1)
0576:                    title = "Move Tagged Messages to Folder";
0577:                else
0578:                    title = "Move Message to Folder";
0579:                FastStringBuffer sb = new FastStringBuffer("Move ");
0580:                sb.append(count);
0581:                sb.append(" message");
0582:                if (count > 1)
0583:                    sb.append('s');
0584:                sb.append(" to:");
0585:                final String destination = ChooseFolderDialog.chooseFolder(
0586:                        editor, sb.toString(), title);
0587:                if (destination == null)
0588:                    return;
0589:                final Line dotLine = advanceDot ? editor.getDotLine() : null;
0590:                Runnable moveRunnable = new Runnable() {
0591:                    public void run() {
0592:                        boolean succeeded = false;
0593:                        String errorText = "Move failed";
0594:                        try {
0595:                            succeeded = moveToFolder(toBeMoved, destination);
0596:                        } catch (MailException e) {
0597:                            errorText = e.getMessage();
0598:                        } finally {
0599:                            // Update message count in sidebar buffer list. We should
0600:                            // do this even if there was an error, since some messages
0601:                            // may have been moved successfully.
0602:                            countMessages();
0603:                            Sidebar.repaintBufferListInAllFrames();
0604:                            if (succeeded && dotLine != null)
0605:                                advanceDot(dotLine);
0606:                            setBusy(false);
0607:                            unlock();
0608:                            editor.updateDisplayLater();
0609:                            if (succeeded) {
0610:                                FastStringBuffer sbuf = new FastStringBuffer(
0611:                                        "Moved ");
0612:                                sbuf.append(toBeMoved.size());
0613:                                sbuf.append(" message");
0614:                                if (toBeMoved.size() != 1)
0615:                                    sbuf.append('s');
0616:                                success(sbuf.toString());
0617:                            } else
0618:                                error(errorText, "Error");
0619:                        }
0620:                    }
0621:                };
0622:                if (lock()) {
0623:                    setBusy(true);
0624:                    new Thread(moveRunnable).start();
0625:                }
0626:            }
0627:
0628:            private boolean moveToFolder(List toBeMoved, String destination)
0629:                    throws MailException {
0630:                if (destination == null)
0631:                    return false;
0632:                if (!destination.startsWith("mailbox:")) {
0633:                    // Not local. Extract folder name from URL.
0634:                    destination = extractFolderName(destination);
0635:                    if (destination == null)
0636:                        return false;
0637:                }
0638:                boolean succeeded = false;
0639:                if (session.verifyConnected()
0640:                        && session.verifySelected(folderName)) {
0641:                    if (session.isReadOnly()) {
0642:                        Log.debug("moveToFolder " + folderName
0643:                                + " is read-only - reselecting...");
0644:                        session.reselect(folderName);
0645:                        if (session.isReadOnly())
0646:                            throw new MailException("Mailbox " + folderName
0647:                                    + " is read-only");
0648:                    }
0649:                    if (destination.startsWith("mailbox:")) {
0650:                        // Destination is local.
0651:                        succeeded = saveLocal(toBeMoved, destination, true);
0652:                    } else {
0653:                        // Destination is an IMAP folder.
0654:                        session.setEcho(true);
0655:                        final String messageSet = getMessageSet(toBeMoved);
0656:                        FastStringBuffer sb = new FastStringBuffer("uid copy ");
0657:                        sb.append(messageSet);
0658:                        sb.append(' ');
0659:                        sb.append(destination);
0660:                        session.writeTagged(sb.toString());
0661:                        if (session.getResponse() == ImapSession.OK) {
0662:                            sb.setLength(0);
0663:                            sb.append("uid store ");
0664:                            sb.append(messageSet);
0665:                            sb.append(" +flags.silent (\\deleted)");
0666:                            session.writeTagged(sb.toString());
0667:                            if (session.getResponse() == ImapSession.OK) {
0668:                                succeeded = true;
0669:                                for (int i = 0; i < toBeMoved.size(); i++) {
0670:                                    ImapMailboxEntry entry = (ImapMailboxEntry) toBeMoved
0671:                                            .get(i);
0672:                                    entry.setFlags(entry.getFlags()
0673:                                            | MailboxEntry.DELETED);
0674:                                    updateEntry(entry);
0675:                                }
0676:                            }
0677:                        }
0678:                        session.setEcho(false);
0679:                    }
0680:                }
0681:                return succeeded;
0682:            }
0683:
0684:            private boolean saveLocal(List toBeSaved, String destination,
0685:                    boolean delete) {
0686:                File file = File.getInstance(destination.substring(8));
0687:                if (file == null)
0688:                    return false;
0689:                if (!file.isLocal())
0690:                    return false;
0691:                Mbox mbox = Mbox.getInstance(file);
0692:                if (!mbox.lock())
0693:                    return false;
0694:                boolean error = false;
0695:                for (int i = 0; i < toBeSaved.size(); i++) {
0696:                    ImapMailboxEntry entry = (ImapMailboxEntry) toBeSaved
0697:                            .get(i);
0698:                    Message message = getMessage(entry, null);
0699:                    if (message != null
0700:                            && mbox.appendMessage(message, entry.getFlags()
0701:                                    & ~MailboxEntry.TAGGED)) {
0702:                        if (delete) {
0703:                            session.writeTagged("uid store " + entry.getUid()
0704:                                    + " +flags.silent (\\deleted)");
0705:                            if (session.getResponse() == ImapSession.OK) {
0706:                                entry.setFlags(entry.getFlags()
0707:                                        | MailboxEntry.DELETED);
0708:                                updateEntry(entry);
0709:                            } else {
0710:                                error = true;
0711:                                break;
0712:                            }
0713:                        }
0714:                    } else {
0715:                        error = true;
0716:                        break;
0717:                    }
0718:                }
0719:                mbox.unlock();
0720:                mbox.updateViews();
0721:                return !error;
0722:            }
0723:
0724:            public String extractFolderName(String input) {
0725:                if (input.startsWith("{")) {
0726:                    try {
0727:                        ImapURL targetUrl = new ImapURL(input);
0728:                        if (!url.getHost().equals(targetUrl.getHost())) {
0729:                            // We don't support operations involving folders on other
0730:                            // servers.
0731:                            return null;
0732:                        }
0733:                        String name = targetUrl.getFolderName();
0734:                        Log.debug("folder name = |" + name + "|");
0735:                        return name;
0736:                    } catch (MalformedURLException e) {
0737:                        Log.error(e);
0738:                        return null;
0739:                    }
0740:                } else {
0741:                    // Assume input is already a relative path.
0742:                    return input;
0743:                }
0744:            }
0745:
0746:            public void delete() {
0747:                final Editor editor = Editor.currentEditor();
0748:                boolean advanceDot = false;
0749:                List list = getTaggedEntries();
0750:                if (list == null) {
0751:                    Line line = editor.getDotLine();
0752:                    if (!(line instanceof  MailboxLine))
0753:                        return;
0754:                    advanceDot = true;
0755:                    list = new ArrayList();
0756:                    list.add(((MailboxLine) line).getMailboxEntry());
0757:                }
0758:                final List toBeDeleted = list;
0759:                final Line dotLine = advanceDot ? editor.getDotLine() : null;
0760:                Runnable deleteRunnable = new Runnable() {
0761:                    public void run() {
0762:                        boolean succeeded = false;
0763:                        String errorText = "Delete failed";
0764:                        try {
0765:                            succeeded = delete(toBeDeleted);
0766:                        } catch (MailException e) {
0767:                            errorText = e.getMessage();
0768:                        } finally {
0769:                            if (succeeded) {
0770:                                // Update message count in sidebar buffer list.
0771:                                countMessages();
0772:                                Sidebar.repaintBufferListInAllFrames();
0773:                                if (dotLine != null)
0774:                                    advanceDot(dotLine);
0775:                            }
0776:                            setBusy(false);
0777:                            unlock();
0778:                            editor.updateDisplayLater();
0779:                            if (!succeeded)
0780:                                error(errorText, "Error");
0781:                        }
0782:                    }
0783:                };
0784:                if (lock()) {
0785:                    setBusy(true);
0786:                    new Thread(deleteRunnable).start();
0787:                }
0788:            }
0789:
0790:            private boolean delete(List toBeDeleted) throws MailException {
0791:                boolean succeeded = false;
0792:                if (session.verifyConnected()
0793:                        && session.verifySelected(folderName)) {
0794:                    if (session.isReadOnly()) {
0795:                        Log.debug("delete " + folderName
0796:                                + " is read-only - reselecting...");
0797:                        session.reselect(folderName);
0798:                        if (session.isReadOnly())
0799:                            throw new MailException("Mailbox " + folderName
0800:                                    + " is read-only");
0801:                    }
0802:                    session.setEcho(true);
0803:                    session.uidStore(getMessageSet(toBeDeleted),
0804:                            "+flags.silent (\\deleted)");
0805:                    if (session.getResponse() == ImapSession.OK) {
0806:                        succeeded = true;
0807:                        for (int i = 0; i < toBeDeleted.size(); i++) {
0808:                            ImapMailboxEntry entry = (ImapMailboxEntry) toBeDeleted
0809:                                    .get(i);
0810:                            entry.setFlags(entry.getFlags()
0811:                                    | MailboxEntry.DELETED);
0812:                            updateEntry(entry);
0813:                        }
0814:                    }
0815:                    session.setEcho(false);
0816:                }
0817:                return succeeded;
0818:            }
0819:
0820:            public void undelete() {
0821:                storeFlagsInternal(ACTION_UNDELETE);
0822:            }
0823:
0824:            public void markRead() {
0825:                storeFlagsInternal(ACTION_MARK_READ);
0826:            }
0827:
0828:            public void markUnread() {
0829:                storeFlagsInternal(ACTION_MARK_UNREAD);
0830:            }
0831:
0832:            private static final int ACTION_UNDELETE = 0;
0833:            private static final int ACTION_MARK_UNREAD = 1;
0834:            private static final int ACTION_MARK_READ = 2;
0835:
0836:            private void storeFlagsInternal(final int action) {
0837:                final Editor editor = Editor.currentEditor();
0838:                boolean advanceDot = false;
0839:                List list = getTaggedEntries();
0840:                if (list == null) {
0841:                    Line line = editor.getDotLine();
0842:                    if (!(line instanceof  MailboxLine))
0843:                        return;
0844:                    if (action == ACTION_UNDELETE)
0845:                        advanceDot = getBooleanProperty(Property.UNDELETE_ADVANCE_DOT);
0846:                    else
0847:                        advanceDot = true;
0848:                    list = new ArrayList();
0849:                    list.add(((MailboxLine) line).getMailboxEntry());
0850:                }
0851:                final List entriesToBeProcessed = list;
0852:                final Line dotLine = advanceDot ? editor.getDotLine() : null;
0853:                Runnable storeFlagsRunnable = new Runnable() {
0854:                    public void run() {
0855:                        try {
0856:                            if (session.verifyConnected()
0857:                                    && session.verifySelected(folderName)) {
0858:                                if (session.isReadOnly()) {
0859:                                    Log
0860:                                            .debug("storeFlagsInternal - read-only - reselecting...");
0861:                                    session.reselect(folderName);
0862:                                    if (session.isReadOnly()) {
0863:                                        readOnlyError();
0864:                                        return;
0865:                                    }
0866:                                }
0867:                                session.setEcho(true);
0868:                                final String messageSet = getMessageSet(entriesToBeProcessed);
0869:                                switch (action) {
0870:                                case ACTION_UNDELETE:
0871:                                    session.uidStore(messageSet,
0872:                                            "-flags.silent (\\deleted)");
0873:                                    break;
0874:                                case ACTION_MARK_READ:
0875:                                    session.uidStore(messageSet,
0876:                                            "+flags.silent (\\seen)");
0877:                                    break;
0878:                                case ACTION_MARK_UNREAD:
0879:                                    session.uidStore(messageSet,
0880:                                            "-flags.silent (\\seen)");
0881:                                    break;
0882:                                default:
0883:                                    Debug.assertTrue(false);
0884:                                    break;
0885:                                }
0886:                                if (session.getResponse() == ImapSession.OK) {
0887:                                    for (int i = 0; i < entriesToBeProcessed
0888:                                            .size(); i++) {
0889:                                        ImapMailboxEntry entry = (ImapMailboxEntry) entriesToBeProcessed
0890:                                                .get(i);
0891:                                        switch (action) {
0892:                                        case ACTION_UNDELETE:
0893:                                            entry.setFlags(entry.getFlags()
0894:                                                    & ~MailboxEntry.DELETED);
0895:                                            break;
0896:                                        case ACTION_MARK_READ:
0897:                                            entry.setFlags(entry.getFlags()
0898:                                                    | MailboxEntry.SEEN);
0899:                                            break;
0900:                                        case ACTION_MARK_UNREAD:
0901:                                            entry.setFlags(entry.getFlags()
0902:                                                    & ~MailboxEntry.SEEN);
0903:                                            break;
0904:                                        default:
0905:                                            Debug.assertTrue(false);
0906:                                            break;
0907:                                        }
0908:                                        updateEntry(entry);
0909:                                    }
0910:                                    if (dotLine != null)
0911:                                        advanceDot(dotLine);
0912:                                }
0913:                                session.setEcho(false);
0914:                            }
0915:                            countMessages();
0916:                        } finally {
0917:                            setBusy(false);
0918:                            unlock();
0919:                            editor.updateDisplayLater();
0920:                            // Update message count in sidebar buffer list.
0921:                            Sidebar.repaintBufferListInAllFrames();
0922:                        }
0923:                    }
0924:                };
0925:                if (lock()) {
0926:                    setBusy(true);
0927:                    new Thread(storeFlagsRunnable).start();
0928:                }
0929:            }
0930:
0931:            public void flag() {
0932:                final Editor editor = Editor.currentEditor();
0933:                boolean advanceDot = false;
0934:                List list = getTaggedEntries();
0935:                if (list == null) {
0936:                    Line line = editor.getDotLine();
0937:                    if (!(line instanceof  MailboxLine))
0938:                        return;
0939:                    advanceDot = true;
0940:                    list = new ArrayList();
0941:                    list.add(((MailboxLine) line).getMailboxEntry());
0942:                }
0943:                final List entriesToBeSet = new ArrayList();
0944:                final List entriesToBeCleared = new ArrayList();
0945:                for (int i = 0; i < list.size(); i++) {
0946:                    MailboxEntry entry = (MailboxEntry) list.get(i);
0947:                    if (entry.isFlagged())
0948:                        entriesToBeCleared.add(entry);
0949:                    else
0950:                        entriesToBeSet.add(entry);
0951:                }
0952:                final Line dotLine = advanceDot ? editor.getDotLine() : null;
0953:                Runnable flagRunnable = new Runnable() {
0954:                    public void run() {
0955:                        try {
0956:                            if (session.verifyConnected()
0957:                                    && session.verifySelected(folderName)) {
0958:                                if (session.isReadOnly()) {
0959:                                    Log
0960:                                            .debug("storeFlagsInternal - read-only - reselecting...");
0961:                                    session.reselect(folderName);
0962:                                    if (session.isReadOnly()) {
0963:                                        readOnlyError();
0964:                                        return;
0965:                                    }
0966:                                }
0967:                                boolean error = false;
0968:                                session.setEcho(true);
0969:                                if (entriesToBeSet.size() > 0) {
0970:                                    session.uidStore(
0971:                                            getMessageSet(entriesToBeSet),
0972:                                            "+flags.silent (\\flagged)");
0973:                                    if (session.getResponse() == ImapSession.OK) {
0974:                                        for (int i = 0; i < entriesToBeSet
0975:                                                .size(); i++) {
0976:                                            MailboxEntry entry = (MailboxEntry) entriesToBeSet
0977:                                                    .get(i);
0978:                                            entry.flag();
0979:                                            updateEntry(entry);
0980:                                        }
0981:                                    } else
0982:                                        error = true;
0983:                                }
0984:                                if (!error && entriesToBeCleared.size() > 0) {
0985:                                    session.uidStore(
0986:                                            getMessageSet(entriesToBeCleared),
0987:                                            "-flags.silent (\\flagged)");
0988:                                    if (session.getResponse() == ImapSession.OK) {
0989:                                        for (int i = 0; i < entriesToBeCleared
0990:                                                .size(); i++) {
0991:                                            MailboxEntry entry = (MailboxEntry) entriesToBeCleared
0992:                                                    .get(i);
0993:                                            entry.unflag();
0994:                                            updateEntry(entry);
0995:                                        }
0996:                                    } else
0997:                                        error = true;
0998:                                }
0999:                                session.setEcho(false);
1000:                                if (!error && dotLine != null)
1001:                                    advanceDot(dotLine);
1002:                            }
1003:                        } finally {
1004:                            setBusy(false);
1005:                            unlock();
1006:                            editor.updateDisplayLater();
1007:                            // Update message count in sidebar buffer list.
1008:                            Sidebar.repaintBufferListInAllFrames();
1009:                        }
1010:                    }
1011:                };
1012:                if (lock()) {
1013:                    setBusy(true);
1014:                    new Thread(flagRunnable).start();
1015:                }
1016:            }
1017:
1018:            public void setAnsweredFlag(final MailboxEntry entry) {
1019:                Runnable setAnsweredFlagRunnable = new Runnable() {
1020:                    public void run() {
1021:                        try {
1022:                            if (session.verifyConnected()
1023:                                    && session.verifySelected(folderName)) {
1024:                                session.setEcho(true);
1025:                                session.uidStore(((ImapMailboxEntry) entry)
1026:                                        .getUid(), "+flags (\\answered)");
1027:                                if (session.getResponse() == ImapSession.OK) {
1028:                                    entry.setFlags(entry.getFlags()
1029:                                            | MailboxEntry.ANSWERED);
1030:                                    updateEntry(entry);
1031:                                }
1032:                                session.setEcho(false);
1033:                            }
1034:                        } finally {
1035:                            setBusy(false);
1036:                            unlock();
1037:                            Editor.updateDisplayLater(ImapMailbox.this );
1038:                        }
1039:                    }
1040:                };
1041:                if (lock()) {
1042:                    setBusy(true);
1043:                    new Thread(setAnsweredFlagRunnable).start();
1044:                }
1045:            }
1046:
1047:            private List retrieveMessageHeaders(int uidBegin, int uidEnd,
1048:                    boolean recent) {
1049:                Log.debug("retrieveMessageHeaders " + folderName + " "
1050:                        + uidBegin + " " + uidEnd);
1051:                long start = System.currentTimeMillis();
1052:                uidValidity = session.getUidValidity();
1053:                messageCount = session.getMessageCount();
1054:                ArrayList list = new ArrayList();
1055:                FastStringBuffer sbCommand = new FastStringBuffer("uid fetch ");
1056:                sbCommand.append(uidBegin);
1057:                sbCommand.append(':');
1058:                if (uidEnd < 0)
1059:                    sbCommand.append('*');
1060:                else
1061:                    sbCommand.append(uidEnd);
1062:                sbCommand
1063:                        .append(" (uid flags internaldate rfc822.size envelope");
1064:                sbCommand.append(" body.peek[header.fields (references)]");
1065:                sbCommand.append(')');
1066:                Log.debug("command = |" + sbCommand.toString() + "|");
1067:                session.writeTagged(sbCommand.toString());
1068:                StatusBarProgressNotifier progressNotifier = new StatusBarProgressNotifier(
1069:                        this );
1070:                progressNotifier.progressStart();
1071:                try {
1072:                    FastStringBuffer sb = new FastStringBuffer();
1073:                    final String endPrefix = session.lastTag() + " ";
1074:                    while (true) {
1075:                        String s = session.readLine();
1076:                        if (s == null) {
1077:                            Log.debug("retrieveMessageHeaders s == null");
1078:                            break;
1079:                        }
1080:                        if (s.startsWith(endPrefix))
1081:                            break;
1082:                        if (s.indexOf("ENVELOPE (") >= 0) {
1083:                            // New entry starting.
1084:                            if (sb.length() > 0) {
1085:                                // Add previous entry to list.
1086:                                addEntry(list, sb.toString(), uidBegin, recent);
1087:                                progressNotifier.progress(getProgressText(list
1088:                                        .size()));
1089:                                if (cancelled) {
1090:                                    Log
1091:                                            .debug("retrieveMessageHeaders cancelled, disconnecting...");
1092:                                    session.disconnect();
1093:                                    return list;
1094:                                }
1095:                                sb.setLength(0);
1096:                            }
1097:                            sb.append(s);
1098:                        } else {
1099:                            // Continuation of previous entry.
1100:                            sb.append("\r\n");
1101:                            sb.append(s);
1102:                        }
1103:                    }
1104:                    if (sb.length() > 0) {
1105:                        // Add final entry to list.
1106:                        addEntry(list, sb.toString(), uidBegin, recent);
1107:                        progressNotifier.progress(getProgressText(list.size()));
1108:                    }
1109:                } catch (Exception e) {
1110:                    Log.error(e);
1111:                } finally {
1112:                    progressNotifier.progressStop();
1113:                    long elapsed = System.currentTimeMillis() - start;
1114:                    Log.debug("retrieveMessageHeaders " + list.size()
1115:                            + " messages in " + elapsed + " ms");
1116:                }
1117:                return list;
1118:            }
1119:
1120:            private void addEntry(List list, String s, int uidBegin,
1121:                    boolean recent) {
1122:                ImapMailboxEntry entry = ImapMailboxEntry.parseEntry(this , s);
1123:                if (entry != null) {
1124:                    if (entry.getUid() >= uidBegin) {
1125:                        if (recent)
1126:                            entry.setFlags(entry.getFlags()
1127:                                    | MailboxEntry.RECENT);
1128:                        list.add(entry);
1129:                    } else {
1130:                        Log.debug("not adding message "
1131:                                + entry.getMessageNumber() + " uid "
1132:                                + entry.getUid() + " uidBegin = " + uidBegin);
1133:                        if (messageCount < 0) {
1134:                            // Mailbox message count is invalid.
1135:                            messageCount = entry.getMessageNumber();
1136:                        } else if (entry.getMessageNumber() != messageCount)
1137:                            Debug.bug();
1138:                    }
1139:                } else
1140:                    Log.error("can't parse envelope |" + s + "|");
1141:            }
1142:
1143:            // This method does not make any assumptions about the order of the entries.
1144:            private void updateLastUid() {
1145:                uidLast = 0;
1146:                if (entries != null) {
1147:                    for (int i = entries.size() - 1; i >= 0; i--) {
1148:                        ImapMailboxEntry entry = (ImapMailboxEntry) entries
1149:                                .get(i);
1150:                        if (entry.getUid() > uidLast)
1151:                            uidLast = entry.getUid();
1152:                    }
1153:                }
1154:            }
1155:
1156:            public void readOnlyError() {
1157:                Runnable r = new Runnable() {
1158:                    public void run() {
1159:                        MessageDialog.showMessageDialog("Mailbox is read-only",
1160:                                "Error");
1161:                    }
1162:                };
1163:                SwingUtilities.invokeLater(r);
1164:            }
1165:
1166:            private void fatal(final String text, final String title) {
1167:                Runnable r = new Runnable() {
1168:                    public void run() {
1169:                        MessageDialog.showMessageDialog(Editor.currentEditor(),
1170:                                text, title);
1171:                        if (Editor.getBufferList().contains(ImapMailbox.this ))
1172:                            kill();
1173:                    }
1174:                };
1175:                SwingUtilities.invokeLater(r);
1176:            }
1177:
1178:            private boolean getAllMessageHeaders() {
1179:                Thread t = new Thread() {
1180:                    public void run() {
1181:                        mailboxCache = ImapMailboxCache
1182:                                .readCache(ImapMailbox.this );
1183:                    }
1184:                };
1185:                t.start();
1186:                if (!session.verifyConnected()) {
1187:                    Log.error("getAllMessageHeaders can't connect to "
1188:                            + session.getHost() + " on port "
1189:                            + session.getPort());
1190:                    setBusy(false);
1191:                    if (!cancelled)
1192:                        fatal(session.getErrorText(), "Error");
1193:                    return false;
1194:                }
1195:                if (!session.verifySelected(folderName)) {
1196:                    Log.error("getAllMessageHeaders can't SELECT " + folderName
1197:                            + " on " + session.getHost());
1198:                    setBusy(false);
1199:                    if (!cancelled)
1200:                        fatal(session.getErrorText(), "Error");
1201:                    return false;
1202:                }
1203:                if (t != null) {
1204:                    try {
1205:                        t.join();
1206:                    } catch (InterruptedException e) {
1207:                        Log.error(e);
1208:                    }
1209:                }
1210:                entries = null;
1211:                uidLast = 0;
1212:                if (mailboxCache != null && mailboxCache.isValid()) {
1213:                    Log.debug("mailboxCache is valid");
1214:                    List cachedEntries = mailboxCache.getEntries();
1215:                    Log.debug("cachedEntries.size() = " + cachedEntries.size());
1216:                    updateCachedEntries(cachedEntries);
1217:                    int size = cachedEntries.size();
1218:                    entries = new ArrayList(size);
1219:                    // Add entries from cache, skipping any that have been nulled out.
1220:                    for (int i = 0; i < size; i++) {
1221:                        Object o = cachedEntries.get(i);
1222:                        if (o != null)
1223:                            entries.add(o);
1224:                    }
1225:                    Log.debug("entries.size() = " + entries.size());
1226:                    // We don't need the cache any more.
1227:                    mailboxCache = null;
1228:                    updateLastUid();
1229:                }
1230:                if (cancelled) {
1231:                    session.disconnect();
1232:                    return false;
1233:                }
1234:                // Get any new entries from the server. Set the recent flag on these
1235:                // entries unless we're retrieving the whole mailbox (uidLast == 0).
1236:                boolean recent = uidLast > 0;
1237:                final List newEntries = retrieveMessageHeaders(uidLast + 1, -1,
1238:                        recent);
1239:                if (newEntries != null && newEntries.size() > 0) {
1240:                    addEntriesToAddressBook(newEntries);
1241:                    processIncomingFilters(newEntries);
1242:                    if (entries != null)
1243:                        entries.addAll(newEntries);
1244:                    else
1245:                        entries = new ArrayList(newEntries);
1246:                }
1247:                uidValidity = session.getUidValidity();
1248:                if (entries == null)
1249:                    entries = new ArrayList();
1250:                else if (entries instanceof  ArrayList)
1251:                    ((ArrayList) entries).trimToSize();
1252:                new ImapMailboxCache(this ).writeCache();
1253:                updateLastUid();
1254:                return true;
1255:            }
1256:
1257:            private boolean getNewMessageHeaders() {
1258:                List newEntries = retrieveMessageHeaders(uidLast + 1, -1, true);
1259:                if (newEntries == null || newEntries.size() == 0)
1260:                    return false;
1261:                addEntriesToAddressBook(newEntries);
1262:                processIncomingFilters(newEntries);
1263:                entries.addAll(newEntries);
1264:                if (entries instanceof  ArrayList)
1265:                    ((ArrayList) entries).trimToSize();
1266:                new ImapMailboxCache(this ).writeCache();
1267:                updateLastUid();
1268:                return true;
1269:            }
1270:
1271:            private void processIncomingFilters(List entryList) {
1272:                Log.debug("processIncomingFilters");
1273:                final List filterList = IncomingFilter.getFilterList();
1274:                if (filterList == null || filterList.size() == 0)
1275:                    return;
1276:                // For now, we just process incoming filters for the user's inbox.
1277:                String inbox = Editor.preferences().getStringProperty(
1278:                        Property.INBOX);
1279:                if (inbox == null)
1280:                    return;
1281:                MailboxURL inboxUrl = MailboxURL.parse(inbox);
1282:                if (!(inboxUrl instanceof  ImapURL)) {
1283:                    Log.debug("processIncomingFilters not inbox "
1284:                            + url.toString());
1285:                    return;
1286:                }
1287:                if (!url.getHost().equals(inboxUrl.getHost())) {
1288:                    Log.debug("processIncomingFilters not inbox "
1289:                            + url.toString());
1290:                    return;
1291:                }
1292:                if (!folderName.equals(((ImapURL) inboxUrl).getFolderName())) {
1293:                    Log.debug("processIncomingFilters not inbox "
1294:                            + url.toString());
1295:                    return;
1296:                }
1297:                SmtpSession smtp = null;
1298:                for (int i = 0; i < entryList.size(); i++) {
1299:                    ImapMailboxEntry entry = (ImapMailboxEntry) entryList
1300:                            .get(i);
1301:                    // Don't process deleted entries.
1302:                    if (entry.isDeleted())
1303:                        continue;
1304:                    for (int j = 0; j < filterList.size(); j++) {
1305:                        IncomingFilter incomingFilter = (IncomingFilter) filterList
1306:                                .get(j);
1307:                        if (incomingFilter != null) {
1308:                            MailboxFilter mf = incomingFilter.getFilter();
1309:                            if (mf != null && mf.accept(entry)) {
1310:                                switch (incomingFilter.getAction()) {
1311:                                case IncomingFilter.MOVE: {
1312:                                    processMove(entry, incomingFilter
1313:                                            .getParameter());
1314:                                    break;
1315:                                }
1316:                                case IncomingFilter.BOUNCE: {
1317:                                    boolean succeeded = false;
1318:                                    if (smtp == null)
1319:                                        smtp = SmtpSession.getDefaultSession();
1320:                                    if (smtp != null)
1321:                                        succeeded = processBounce(entry,
1322:                                                incomingFilter.getParameter(),
1323:                                                smtp);
1324:                                    if (!succeeded)
1325:                                        Log.error("processBounce failed");
1326:                                    break;
1327:                                }
1328:                                case IncomingFilter.BOUNCE_AND_DELETE: {
1329:                                    boolean succeeded = false;
1330:                                    if (smtp == null)
1331:                                        smtp = SmtpSession.getDefaultSession();
1332:                                    if (smtp != null)
1333:                                        succeeded = processBounce(entry,
1334:                                                incomingFilter.getParameter(),
1335:                                                smtp);
1336:                                    if (succeeded)
1337:                                        processDelete(entry);
1338:                                    else
1339:                                        Log.error("processBounce failed");
1340:                                    break;
1341:                                }
1342:                                default:
1343:                                    break;
1344:                                }
1345:                                break;
1346:                            }
1347:                        }
1348:                    }
1349:                }
1350:                // Processing completed.
1351:                if (smtp != null)
1352:                    smtp.quit();
1353:            }
1354:
1355:            private void processMove(ImapMailboxEntry entry, String destination) {
1356:                if (destination != null) {
1357:                    Log.debug("destination = |" + destination + "|");
1358:                    ArrayList list = new ArrayList(1);
1359:                    list.add(entry);
1360:                    try {
1361:                        Log.debug("processMove calling moveToFolder");
1362:                        moveToFolder(list, destination);
1363:                        Log.debug("processMove back from moveToFolder");
1364:                    } catch (Exception e) {
1365:                        Log.error(e);
1366:                    }
1367:                }
1368:            }
1369:
1370:            private boolean processBounce(ImapMailboxEntry entry,
1371:                    String bounceTo, SmtpSession smtp) {
1372:                if (bounceTo == null)
1373:                    return false;
1374:                Log.debug("bounceTo = |" + bounceTo + "|");
1375:                MailAddress[] to = MailAddress.parseAddresses(bounceTo);
1376:                if (to == null)
1377:                    return false;
1378:                if (to.length == 0)
1379:                    return false;
1380:                Message message = getMessage(entry, null);
1381:                if (message == null) {
1382:                    Log.error("processBounce getMessage() failed");
1383:                    return false;
1384:                }
1385:                return Mail.bounceMessage(message, to, smtp);
1386:            }
1387:
1388:            private void processDelete(ImapMailboxEntry entry) {
1389:                ArrayList list = new ArrayList(1);
1390:                list.add(entry);
1391:                try {
1392:                    delete(list);
1393:                } catch (Exception e) {
1394:                    Log.error(e);
1395:                }
1396:            }
1397:
1398:            private void updateCachedEntries(List cachedEntries) {
1399:                if (cachedEntries == null)
1400:                    return;
1401:                final int size = cachedEntries.size();
1402:                if (size == 0)
1403:                    return;
1404:                long start = System.currentTimeMillis();
1405:                session.writeTagged("uid fetch 1:* (uid flags)");
1406:                HashMap map = new HashMap(size);
1407:                Iterator iter = cachedEntries.iterator();
1408:                while (iter.hasNext()) {
1409:                    ImapMailboxEntry entry = (ImapMailboxEntry) iter.next();
1410:                    map.put(new Integer(entry.getUid()), entry);
1411:                }
1412:                Log.debug("built map " + (System.currentTimeMillis() - start)
1413:                        + " ms");
1414:                iter = null;
1415:                final String endPrefix = session.lastTag() + " ";
1416:                // Set mailbox field and update flags for all messages on server.
1417:                while (true) {
1418:                    final String s = session.readLine();
1419:                    if (s == null) {
1420:                        Log.debug("updateCachedEntries s is null");
1421:                        break;
1422:                    }
1423:                    if (s.startsWith(endPrefix))
1424:                        break;
1425:                    int uid = ImapMailboxEntry.parseUid(s);
1426:                    if (uid == 0) {
1427:                        Log.debug("uid = 0 s = |" + s + "|");
1428:                        continue;
1429:                    }
1430:                    ImapMailboxEntry entry = (ImapMailboxEntry) map
1431:                            .get(new Integer(uid));
1432:                    if (entry != null) {
1433:                        Debug.assertTrue(entry.getMailbox() == null);
1434:                        entry.setMailbox(this );
1435:                        entry.setFlags(ImapMailboxEntry.parseFlags(s));
1436:                    }
1437:                }
1438:                map.clear();
1439:                // Null out entries whose mailbox field is not set (i.e. entries
1440:                // deleted from server).
1441:                for (int i = 0; i < size; i++) {
1442:                    ImapMailboxEntry entry = (ImapMailboxEntry) cachedEntries
1443:                            .get(i);
1444:                    if (entry.getMailbox() == null)
1445:                        cachedEntries.set(i, null);
1446:                }
1447:                long elapsed = System.currentTimeMillis() - start;
1448:                Log.debug("updateCachedEntries " + elapsed + " ms "
1449:                        + (float) elapsed / cachedEntries.size()
1450:                        + " ms per entry");
1451:            }
1452:
1453:            public void readMessage(Line line) {
1454:                readMessage(line, false);
1455:            }
1456:
1457:            public void readMessageOtherWindow(Line line) {
1458:                readMessage(line, true);
1459:            }
1460:
1461:            private void readMessage(Line line, boolean useOtherWindow) {
1462:                Editor editor = Editor.currentEditor();
1463:                ImapMailboxEntry entry = (ImapMailboxEntry) ((MailboxLine) line)
1464:                        .getMailboxEntry();
1465:                Buffer buf = null;
1466:                for (BufferIterator it = new BufferIterator(); it.hasNext();) {
1467:                    Buffer b = it.nextBuffer();
1468:                    if (b instanceof  ImapMessageBuffer) {
1469:                        ImapMessageBuffer mb = (ImapMessageBuffer) b;
1470:                        if (mb.getMailboxEntry() == entry) {
1471:                            buf = b;
1472:                            break;
1473:                        }
1474:                    }
1475:                }
1476:                if (buf != null) {
1477:                    // Found existing buffer.
1478:                    activateMessageBuffer(editor, (ImapMessageBuffer) buf,
1479:                            useOtherWindow);
1480:                    return;
1481:                }
1482:                if (getBooleanProperty(Property.IMAP_USE_LOCAL_CACHE)) {
1483:                    String rawText = getMessageTextFromCache(entry.getUid());
1484:                    if (rawText != null) {
1485:                        ImapMessageBuffer mb = new ImapMessageBuffer(this ,
1486:                                entry, rawText);
1487:                        activateMessageBuffer(editor, mb, useOtherWindow);
1488:                        if ((entry.getFlags() & MailboxEntry.SEEN) == 0) {
1489:                            if (session.isReadOnly())
1490:                                markReadLocal(entry);
1491:                            else
1492:                                markRead(entry);
1493:                        }
1494:                        return;
1495:                    }
1496:                }
1497:                // Lock the mailbox before creating the message buffer. It will be
1498:                // unlocked at the end of the message buffer's loadProcess.run().
1499:                if (lock()) {
1500:                    setBusy(true);
1501:                    ImapMessageBuffer mb = new ImapMessageBuffer(this , entry);
1502:                    activateMessageBuffer(editor, mb, useOtherWindow);
1503:                } else
1504:                    editor.status("Mailbox is locked");
1505:            }
1506:
1507:            private void markRead(final ImapMailboxEntry entry) {
1508:                Runnable markReadRunnable = new Runnable() {
1509:                    public void run() {
1510:                        try {
1511:                            if (session.verifyConnected()
1512:                                    && session.verifySelected(folderName)) {
1513:                                session.uidStore(entry.getUid(),
1514:                                        "+flags.silent (\\seen)");
1515:                                if (session.getResponse() == ImapSession.OK)
1516:                                    markReadLocal(entry);
1517:                            }
1518:                        } finally {
1519:                            setBusy(false);
1520:                            unlock();
1521:                            Editor.updateDisplayLater(ImapMailbox.this );
1522:                        }
1523:                    }
1524:                };
1525:                if (lock()) {
1526:                    setBusy(true);
1527:                    new Thread(markReadRunnable).start();
1528:                }
1529:            }
1530:
1531:            private void markReadLocal(ImapMailboxEntry entry) {
1532:                entry.setFlags(entry.getFlags() | MailboxEntry.SEEN);
1533:                updateEntry(entry);
1534:                countMessages();
1535:            }
1536:
1537:            public ImapMailboxEntry getMailboxEntry(String messageId) {
1538:                for (int i = entries.size() - 1; i >= 0; i--) {
1539:                    ImapMailboxEntry entry = (ImapMailboxEntry) entries.get(i);
1540:                    if (messageId.equals(entry.getMessageId()))
1541:                        return entry;
1542:                }
1543:                return null;
1544:            }
1545:
1546:            public Message getMessage(MailboxEntry entry,
1547:                    ProgressNotifier progressNotifier) {
1548:                if (!(entry instanceof  ImapMailboxEntry))
1549:                    return null;
1550:                final int uid = ((ImapMailboxEntry) entry).getUid();
1551:                if (getBooleanProperty(Property.IMAP_USE_LOCAL_CACHE)) {
1552:                    String rawText = getMessageTextFromCache(uid);
1553:                    if (rawText != null)
1554:                        return new Message(rawText);
1555:                }
1556:                if (!isLocked())
1557:                    Debug.bug("ImapMailbox.getMessage mailbox is not locked!");
1558:                if (!session.verifyConnected())
1559:                    return null;
1560:                if (progressNotifier != null && progressNotifier.cancelled())
1561:                    return null;
1562:                if (!session.verifySelected(folderName))
1563:                    return null;
1564:                if (progressNotifier != null && progressNotifier.cancelled())
1565:                    return null;
1566:                String header = fetchPart(uid, "header", null, progressNotifier);
1567:                if (header == null)
1568:                    return null;
1569:                Headers headers = Headers.parse(header);
1570:                String charset = null;
1571:                String contentType = headers.getValue(Headers.CONTENT_TYPE);
1572:                if (contentType != null)
1573:                    charset = Utilities.getCharsetFromContentType(contentType);
1574:                Log.debug("charset = " + charset);
1575:                String encoding = Utilities.getEncodingFromCharset(charset);
1576:                if (encoding.equalsIgnoreCase("us-ascii"))
1577:                    encoding = null;
1578:                else if (encoding.equalsIgnoreCase("iso-8859-1"))
1579:                    encoding = null;
1580:                String body = fetchPart(uid, "text", encoding, progressNotifier);
1581:                if (body == null)
1582:                    return null;
1583:                if (getBooleanProperty(Property.IMAP_USE_LOCAL_CACHE))
1584:                    cacheMessage(uid, header + body, encoding);
1585:                return new Message(header.concat(body), headers);
1586:            }
1587:
1588:            private String fetchPart(int uid, String part, String encoding,
1589:                    ProgressNotifier progressNotifier) {
1590:                FastStringBuffer sb = new FastStringBuffer("uid fetch ");
1591:                sb.append(uid);
1592:                sb.append(" body[");
1593:                sb.append(part);
1594:                sb.append(']');
1595:                session.writeTagged(sb.toString());
1596:                sb = null;
1597:                int length = -1;
1598:                try {
1599:                    if (progressNotifier != null
1600:                            && progressNotifier.cancelled()) {
1601:                        session.disconnect();
1602:                        return null;
1603:                    }
1604:                    String s = session.readLine();
1605:                    if (s == null)
1606:                        return null;
1607:                    if (s.startsWith("* ")) {
1608:                        int index = s.indexOf('(');
1609:                        if (index < 0) {
1610:                            Log.error("can't parse response s = |" + s + "|");
1611:                            return null;
1612:                        }
1613:                        String before = s.substring(0, index).trim();
1614:                        if (!before.endsWith(" FETCH")) {
1615:                            Log.error("no FETCH");
1616:                            return null;
1617:                        }
1618:                        String after = s.substring(index);
1619:                        int begin = after.indexOf('{');
1620:                        if (begin < 0) {
1621:                            Log.error("no '{'");
1622:                            Log.error("s = |" + s + "|");
1623:                            begin = after.indexOf('"');
1624:                            if (begin < 0)
1625:                                return null;
1626:                            else
1627:                                return parseQuotedString(after.substring(begin));
1628:                        }
1629:                        int end = after.indexOf('}', begin + 1);
1630:                        if (end < 0) {
1631:                            Log.error("no '}'");
1632:                            return null;
1633:                        }
1634:                        try {
1635:                            length = Integer.parseInt(after.substring(
1636:                                    begin + 1, end));
1637:                        } catch (NumberFormatException e) {
1638:                            Log.error(e);
1639:                        }
1640:                    }
1641:                    if (length < 0) {
1642:                        Log.error("can't determine length");
1643:                        Log.error("s = |" + s + "|");
1644:                        return null;
1645:                    }
1646:                    sb = new FastStringBuffer(length + 64);
1647:                    while (true) {
1648:                        if (progressNotifier != null
1649:                                && progressNotifier.cancelled()) {
1650:                            session.disconnect();
1651:                            return null;
1652:                        }
1653:                        s = session.readLine();
1654:                        if (s == null)
1655:                            break;
1656:                        if (s.startsWith(session.lastTag() + " OK"))
1657:                            break;
1658:                        // Otherwise we need to append the string...
1659:                        if (encoding != null) {
1660:                            // Must do conversion.
1661:                            int len = s.length();
1662:                            byte[] bytes = new byte[len];
1663:                            for (int i = 0; i < len; i++)
1664:                                bytes[i] = (byte) s.charAt(i);
1665:                            try {
1666:                                s = new String(bytes, encoding);
1667:                            } catch (UnsupportedEncodingException e) {
1668:                                Log.debug(e);
1669:                                // Conversion isn't going to work, so give up on it.
1670:                                encoding = null;
1671:                            }
1672:                        }
1673:                        sb.append(s);
1674:                        sb.append("\r\n");
1675:                        if (progressNotifier != null)
1676:                            progressNotifier.progress("Received ", sb.length(),
1677:                                    length);
1678:                    }
1679:                } catch (Exception e) {
1680:                    Log.error(e);
1681:                }
1682:                if (sb != null) {
1683:                    Log.debug("advertised length = " + length);
1684:                    Log.debug("actual length = " + sb.length());
1685:                    sb.setLength(length);
1686:                    return sb.toString();
1687:                } else
1688:                    return null;
1689:            }
1690:
1691:            private String parseQuotedString(final String s) {
1692:                Debug.assertTrue(s.length() > 0);
1693:                Debug.assertTrue(s.charAt(0) == '"');
1694:                FastStringBuffer sb = new FastStringBuffer();
1695:                final int length = s.length();
1696:                for (int i = 1; i < length; i++) {
1697:                    char c = s.charAt(i);
1698:                    if (c == '\\' && i + 1 < length)
1699:                        sb.append(s.charAt(++i));
1700:                    else if (c == '"')
1701:                        break;
1702:                    else
1703:                        sb.append(c);
1704:                }
1705:                return sb.toString();
1706:            }
1707:
1708:            public void dispose() {
1709:                Log.debug("ImapMailbox.dispose " + folderName + " on "
1710:                        + session.getHost());
1711:                Runnable r = new Runnable() {
1712:                    public void run() {
1713:                        session.logout();
1714:                    }
1715:                };
1716:                new Thread(r).start();
1717:                MailboxProperties.saveProperties(this );
1718:            }
1719:
1720:            protected void finalize() throws Throwable {
1721:                Log.debug("ImapMailbox.finalize " + folderName + " on "
1722:                        + session.getHost());
1723:                super .finalize();
1724:            }
1725:
1726:            private String getProgressText(int n) {
1727:                FastStringBuffer sb = new FastStringBuffer(32);
1728:                sb.append("Retrieved ");
1729:                sb.append(n);
1730:                sb.append(" message header");
1731:                if (n > 1)
1732:                    sb.append('s');
1733:                return sb.toString();
1734:            }
1735:
1736:            // Package scope for testing.
1737:            /*package*/static String getMessageSet(List list) {
1738:                FastStringBuffer sb = new FastStringBuffer();
1739:                int limit = list.size();
1740:                int begin = -1;
1741:                int end = -1;
1742:                for (int i = 0; i < limit; i++) {
1743:                    ImapMailboxEntry entry = (ImapMailboxEntry) list.get(i);
1744:                    if (begin < 0) {
1745:                        begin = entry.getUid();
1746:                        end = entry.getUid();
1747:                    } else if (entry.getUid() == end + 1) {
1748:                        end = entry.getUid();
1749:                    } else {
1750:                        if (sb.length() > 0)
1751:                            sb.append(',');
1752:                        if (begin != end) {
1753:                            Debug.assertTrue(end > begin);
1754:                            sb.append(begin);
1755:                            sb.append(':');
1756:                            sb.append(end);
1757:                            begin = end = entry.getUid();
1758:                        } else {
1759:                            sb.append(begin);
1760:                            begin = end = entry.getUid();
1761:                        }
1762:                    }
1763:                }
1764:                if (sb.length() > 0)
1765:                    sb.append(',');
1766:                if (begin != end) {
1767:                    Debug.assertTrue(end > begin);
1768:                    sb.append(begin);
1769:                    sb.append(':');
1770:                    sb.append(end);
1771:                } else
1772:                    sb.append(begin);
1773:                return sb.toString();
1774:            }
1775:
1776:            public String toString() {
1777:                int newMessageCount = getNewMessageCount();
1778:                if (newMessageCount > 0) {
1779:                    FastStringBuffer sb = new FastStringBuffer(url.toString());
1780:                    sb.append(" (");
1781:                    sb.append(newMessageCount);
1782:                    sb.append(" new)");
1783:                    return sb.toString();
1784:                } else
1785:                    return url.toString();
1786:            }
1787:
1788:            public String getTitle() {
1789:                return toString();
1790:            }
1791:
1792:            private ImapMessageCache messageCache;
1793:
1794:            private void cacheMessage(int uid, String message, String encoding) {
1795:                if (messageCache != null) {
1796:                    if (messageCache.getUidValidity() != session
1797:                            .getUidValidity())
1798:                        messageCache = null;
1799:                }
1800:                if (messageCache == null) {
1801:                    messageCache = ImapMessageCache.getMessageCache(this );
1802:                    if (messageCache == null)
1803:                        return;
1804:                }
1805:                messageCache.store(uid, message, encoding);
1806:            }
1807:
1808:            private String getMessageTextFromCache(int uid) {
1809:                if (messageCache != null) {
1810:                    if (messageCache.getUidValidity() != session
1811:                            .getUidValidity())
1812:                        messageCache = null;
1813:                }
1814:                if (messageCache == null) {
1815:                    messageCache = ImapMessageCache.getMessageCache(this);
1816:                    if (messageCache == null)
1817:                        return null;
1818:                }
1819:                return messageCache.getMessageText(uid);
1820:            }
1821:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.