Source Code Cross Referenced for PopMailbox.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) 


001:        /*
002:         * PopMailbox.java
003:         *
004:         * Copyright (C) 2000-2003 Peter Graves
005:         * $Id: PopMailbox.java,v 1.3 2003/06/29 00:19:34 piso Exp $
006:         *
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License
009:         * as published by the Free Software Foundation; either version 2
010:         * of the License, or (at your option) any later version.
011:         *
012:         * This program is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015:         * GNU General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU General Public License
018:         * along with this program; if not, write to the Free Software
019:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
020:         */
021:
022:        package org.armedbear.j.mail;
023:
024:        import java.io.BufferedReader;
025:        import java.io.BufferedWriter;
026:        import java.io.FileNotFoundException;
027:        import java.io.FileReader;
028:        import java.io.FileWriter;
029:        import java.io.IOException;
030:        import java.io.InputStream;
031:        import java.io.OutputStream;
032:        import java.io.RandomAccessFile;
033:        import java.text.SimpleDateFormat;
034:        import java.util.ArrayList;
035:        import java.util.Calendar;
036:        import java.util.HashSet;
037:        import java.util.Iterator;
038:        import java.util.List;
039:        import java.util.Locale;
040:        import java.util.Properties;
041:        import javax.swing.SwingUtilities;
042:        import org.armedbear.j.BackgroundProcess;
043:        import org.armedbear.j.Debug;
044:        import org.armedbear.j.Editor;
045:        import org.armedbear.j.Directories;
046:        import org.armedbear.j.EditorIterator;
047:        import org.armedbear.j.File;
048:        import org.armedbear.j.FastStringBuffer;
049:        import org.armedbear.j.Log;
050:        import org.armedbear.j.PasswordDialog;
051:        import org.armedbear.j.Property;
052:        import org.armedbear.j.StatusBarProgressNotifier;
053:        import org.armedbear.j.Utilities;
054:        import org.armedbear.j.View;
055:
056:        public final class PopMailbox extends LocalMailbox {
057:            private final PopSession session;
058:
059:            private File localStore;
060:            private StatusBarProgressNotifier progressNotifier;
061:            private boolean cancelled;
062:            private Thread backgroundThread;
063:
064:            public PopMailbox(PopURL url, PopSession session) {
065:                super (url);
066:                this .session = session;
067:                if (url.getUser() == null)
068:                    url.setUser(session.getUser());
069:                setMailboxFile(getLocalStore());
070:                setInitialized(true);
071:            }
072:
073:            public String getFileNameForDisplay() {
074:                FastStringBuffer sb = new FastStringBuffer(64);
075:                sb.append(url.toString());
076:                String limitPattern = getLimitPattern();
077:                if (limitPattern != null) {
078:                    sb.append(' ');
079:                    sb.append(limitPattern);
080:                }
081:                return sb.toString();
082:            }
083:
084:            public final String getName() {
085:                return url.toString();
086:            }
087:
088:            public synchronized int load() {
089:                if (isLoaded())
090:                    return LOAD_COMPLETED;
091:                if (lock()) {
092:                    Debug.assertTrue(backgroundThread == null);
093:                    backgroundThread = new Thread(loadProcess);
094:                    backgroundThread.start();
095:                    setLoaded(true);
096:                    return LOAD_PENDING;
097:                }
098:                // Not loaded, lock() failed. Shouldn't happen.
099:                Debug.bug("PopMailbox.load can't lock mailbox");
100:                return LOAD_FAILED;
101:            }
102:
103:            private BackgroundProcess loadProcess = new BackgroundProcess() {
104:                public void run() {
105:                    // Mailbox is already locked at this point.
106:                    boolean abort = false;
107:                    try {
108:                        setBusy(true);
109:                        cancelled = false;
110:                        progressNotifier = new StatusBarProgressNotifier(
111:                                PopMailbox.this );
112:                        progressNotifier.progressStart();
113:                        setBackgroundProcess(this );
114:                        readMailboxFile(progressNotifier); // Error handling?
115:                        if (cancelled) {
116:                            abort = true;
117:                            return;
118:                        }
119:                        readExpungedUidlsList();
120:                        clearRecent();
121:                        if (cancelled || getBooleanProperty(Property.OFFLINE))
122:                            return;
123:                        if (retrieveNewMessages()) {
124:                            addEntriesToAddressBook(entries);
125:                            setLastCheckMillis(System.currentTimeMillis());
126:                        } else if (!cancelled) {
127:                            // Error!
128:                            error(session.getErrorText(), url.toString());
129:                        }
130:                    } finally {
131:                        if (abort) {
132:                            Runnable r = new Runnable() {
133:                                public void run() {
134:                                    kill();
135:                                    for (EditorIterator it = new EditorIterator(); it
136:                                            .hasNext();)
137:                                        it.nextEditor().updateDisplay();
138:                                }
139:                            };
140:                            SwingUtilities.invokeLater(r);
141:                        } else {
142:                            refreshBuffer();
143:                            Runnable r = new Runnable() {
144:                                public void run() {
145:                                    setBusy(false);
146:                                    for (EditorIterator it = new EditorIterator(); it
147:                                            .hasNext();) {
148:                                        Editor ed = it.nextEditor();
149:                                        View view = new View();
150:                                        view.setDotEntry(getInitialEntry());
151:                                        ed.setView(PopMailbox.this , view);
152:                                        if (ed.getBuffer() == PopMailbox.this ) {
153:                                            ed.bufferActivated(true);
154:                                            ed.updateDisplay();
155:                                        }
156:                                    }
157:                                }
158:                            };
159:                            SwingUtilities.invokeLater(r);
160:                        }
161:                        setBackgroundProcess(null);
162:                        backgroundThread = null;
163:                        if (progressNotifier != null) {
164:                            progressNotifier.setText(cancelled ? "Cancelled"
165:                                    : "");
166:                            progressNotifier.progressStop();
167:                            progressNotifier = null;
168:                        }
169:                        unlock();
170:                    }
171:                }
172:
173:                public void cancel() {
174:                    Log.debug("loadProcess.cancel");
175:                    cancelled = true;
176:                    progressNotifier.cancel();
177:                    progressNotifier.setText("Cancelled, cleaning up...");
178:                    if (backgroundThread != null && backgroundThread.isAlive())
179:                        backgroundThread.interrupt();
180:                    session.disconnect();
181:                }
182:            };
183:
184:            public void getNewMessages() {
185:                if (session.getPassword() == null) {
186:                    String password = PasswordDialog.showPasswordDialog(Editor
187:                            .currentEditor(), "Password:", "Password");
188:                    if (password == null || password.length() == 0)
189:                        return;
190:                    session.setPassword(password);
191:                }
192:                if (lock())
193:                    getNewMessages(true);
194:                else
195:                    Editor.currentEditor().status("Mailbox is locked");
196:            }
197:
198:            public void getNewMessages(boolean userInitiated) {
199:                Debug.assertTrue(isLocked());
200:                // This method can get called in the background so we can't put up a
201:                // dialog.
202:                if (session.getPassword() == null)
203:                    return;
204:                Log.debug("PopMailbox.getNewMessages " + userInitiated);
205:                setBusy(true);
206:                Log.debug("PopMailbox.getNewMessages back from setBusy(true)");
207:                if (userInitiated)
208:                    saveDisplayState();
209:                Debug.assertTrue(backgroundThread == null);
210:                backgroundThread = new Thread(new GetNewMessagesProcess(
211:                        userInitiated));
212:                backgroundThread.start();
213:            }
214:
215:            private class GetNewMessagesProcess implements  BackgroundProcess {
216:                private boolean userInitiated;
217:
218:                // If this constructor is private, we run into jikes 1.15 bug #2256.
219:                /*private*/GetNewMessagesProcess(boolean userInitiated) {
220:                    this .userInitiated = userInitiated;
221:                }
222:
223:                public void run() {
224:                    try {
225:                        boolean changed = false;
226:                        if (userInitiated)
227:                            changed = clearRecent();
228:                        cancelled = false;
229:                        progressNotifier = new StatusBarProgressNotifier(
230:                                PopMailbox.this );
231:                        progressNotifier.progressStart();
232:                        setBackgroundProcess(this );
233:                        int oldSize = entries.size();
234:                        boolean ok = retrieveNewMessages();
235:                        if (changed || entries.size() != oldSize) {
236:                            refreshBuffer();
237:                            addEntriesToAddressBook(entries);
238:                            updateDisplay();
239:                        }
240:                        newMessagesStatus();
241:                        if (!ok) {
242:                            if (userInitiated && !cancelled)
243:                                error(session.getErrorText(), url.toString());
244:                        }
245:                    } finally {
246:                        setBusy(false);
247:                        if (progressNotifier != null) {
248:                            progressNotifier.setText(cancelled ? "Cancelled"
249:                                    : "");
250:                            progressNotifier.progressStop();
251:                            progressNotifier = null;
252:                        }
253:                        setBackgroundProcess(null);
254:                        backgroundThread = null;
255:                        setLastCheckMillis(System.currentTimeMillis());
256:                        unlock();
257:                        Editor.updateDisplayLater(PopMailbox.this );
258:                    }
259:                }
260:
261:                public void cancel() {
262:                    Log.debug("GetNewMessagesProcess.cancel");
263:                    cancelled = true;
264:                    progressNotifier.cancel();
265:                    progressNotifier.setText("Cancelled, cleaning up...");
266:                    if (backgroundThread != null && backgroundThread.isAlive()) {
267:                        Log.debug("interrupting background thread...");
268:                        backgroundThread.interrupt();
269:                    }
270:                    session.disconnect();
271:                }
272:            }
273:
274:            private boolean retrieveNewMessages() {
275:                Log.debug("PopMailbox.retrieveNewMessages");
276:                if (!connect())
277:                    return false;
278:                File outputFile = null;
279:                long start = System.currentTimeMillis();
280:                try {
281:                    if (Thread.currentThread().isInterrupted() || cancelled)
282:                        return true;
283:                    int count = stat();
284:                    if (count < 0)
285:                        return false; // Error.
286:                    if (count == 0)
287:                        return true; // No messages on the server.
288:                    if (Thread.currentThread().isInterrupted() || cancelled)
289:                        return true;
290:                    List serverMessageList = getServerMessageList(count);
291:                    if (serverMessageList == null)
292:                        return false; // Error.
293:                    if (Thread.currentThread().isInterrupted() || cancelled)
294:                        return true;
295:                    // Removed uidls from the expunged uidls list if the corresponding
296:                    // message no longer exists on the server.
297:                    pruneExpungedUidlsList(serverMessageList);
298:                    if (Thread.currentThread().isInterrupted() || cancelled)
299:                        return true;
300:                    // Remove messages from the server message list if we already have
301:                    // them or if they've been expunged locally.
302:                    List messagesToBeRetrieved = getMessagesToBeRetrieved(serverMessageList);
303:                    if (Thread.currentThread().isInterrupted() || cancelled)
304:                        return true;
305:                    // Is there anything left?
306:                    if (messagesToBeRetrieved.size() == 0) {
307:                        // If we're not keeping messages on the server, delete the old
308:                        // messages.
309:                        if (!getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER))
310:                            deleteMessagesOnServer(serverMessageList);
311:                        Log.debug("no new messages");
312:                        return true;
313:                    }
314:                    if (getLocalStore() == null)
315:                        return false; // Error.
316:                    if (localStore.isFile() && localStore.length() > 0) {
317:                        outputFile = Utilities.getTempFile(localStore
318:                                .getParentFile());
319:                        Log.debug("calling copyFile");
320:                        long copyStart = System.currentTimeMillis();
321:                        if (!Utilities.copyFile(localStore, outputFile))
322:                            return false;
323:                        Log.debug("back from copyFile "
324:                                + (System.currentTimeMillis() - copyStart)
325:                                + " ms");
326:                    } else
327:                        outputFile = localStore;
328:                    MailboxFileWriter writer = MailboxFileWriter.getInstance(
329:                            outputFile, true); // Append.
330:                    if (writer == null)
331:                        return false; // Error.
332:                    boolean ok = retrieveMessages(messagesToBeRetrieved, writer);
333:                    try {
334:                        writer.flush();
335:                        writer.close();
336:                    } catch (IOException e) {
337:                        Log.error(e);
338:                        return false;
339:                    }
340:                    if (!ok) {
341:                        Log.debug("not ok...");
342:                        // retrieveMessages() was interrupted. Truncate output file to
343:                        // proper length.
344:                        if (entries.size() == 0)
345:                            return false;
346:                        LocalMailboxEntry entry = (LocalMailboxEntry) entries
347:                                .get(entries.size() - 1);
348:                        long offset = entry.getNextMessageStart(); // Truncate to here.
349:                        try {
350:                            RandomAccessFile raf = outputFile
351:                                    .getRandomAccessFile("rw");
352:                            Log.debug("before raf.length() = " + raf.length());
353:                            Log.debug("truncating to " + offset);
354:                            raf.setLength(offset);
355:                            Log.debug("after raf.length() = " + raf.length());
356:                            raf.close();
357:                        } catch (IOException e) {
358:                            Log.error(e);
359:                            return false;
360:                        }
361:                    }
362:                    if (outputFile != localStore)
363:                        if (!Utilities.deleteRename(outputFile, localStore))
364:                            return false;
365:                    if (getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER) == false)
366:                        deleteMessagesOnServer(serverMessageList);
367:                    outputFile = null;
368:                } finally {
369:                    Log.debug("retrieveNewMessages calling logout() ...");
370:                    session.logout();
371:                    if (outputFile != null && outputFile.isFile())
372:                        outputFile.delete();
373:                }
374:                Log.debug("retrieveNewMessages "
375:                        + (System.currentTimeMillis() - start) + " ms");
376:                return true; // Success!
377:            }
378:
379:            private boolean connect() {
380:                if (progressNotifier != null)
381:                    progressNotifier.setText("Connecting to "
382:                            + session.getHost());
383:                if (session.connect()) {
384:                    if (progressNotifier != null)
385:                        progressNotifier.setText("Connected to "
386:                                + session.getHost());
387:                    return true;
388:                }
389:                return false;
390:            }
391:
392:            // Returns number of messages on server or -1 if there is an error.
393:            private int stat() {
394:                int count = -1;
395:                session.write("stat");
396:                String response = session.readLine();
397:                if (response.startsWith("+OK")) {
398:                    try {
399:                        count = Utilities
400:                                .parseInt(response.substring(3).trim());
401:                    } catch (NumberFormatException e) {
402:                        Log.error(e);
403:                    }
404:                } else {
405:                    Log.error("stat failed");
406:                    Log.error(response);
407:                }
408:                return count;
409:            }
410:
411:            private List getServerMessageList(int count) {
412:                long start = System.currentTimeMillis();
413:                session.write("uidl");
414:                String response = session.readLine();
415:                if (!response.startsWith("+OK")) {
416:                    Log.error("getServerMessageList uidl failed");
417:                    Log.error(response);
418:                    return null;
419:                }
420:                List list = new ArrayList(count);
421:                while (true) {
422:                    String s = session.readLine();
423:                    if (s == null)
424:                        return null; // Shouldn't happen.
425:                    if (s.equals("."))
426:                        break;
427:                    int index = s.indexOf(' ');
428:                    if (index >= 0) {
429:                        int messageNumber = Integer.parseInt(s.substring(0,
430:                                index)); // BUG! Error handling!
431:                        String uidl = s.substring(index + 1);
432:                        if (messageNumber >= 1)
433:                            list.add(new MessageListEntry(messageNumber, uidl));
434:                    }
435:                }
436:                Log.debug("getServerMessageList "
437:                        + (System.currentTimeMillis() - start) + " ms");
438:                Log.debug("getServerMessageList count = " + count
439:                        + " list size = " + list.size());
440:                return list;
441:            }
442:
443:            private List getMessagesToBeRetrieved(List serverMessageList) {
444:                long start = System.currentTimeMillis();
445:                HashSet hashSet = null;
446:                if (entries != null) {
447:                    int size = entries.size();
448:                    hashSet = new HashSet(size);
449:                    for (int i = 0; i < size; i++) {
450:                        LocalMailboxEntry mailboxEntry = (LocalMailboxEntry) entries
451:                                .get(i);
452:                        hashSet.add(mailboxEntry.getUidl());
453:                    }
454:                }
455:                List toBeReturned = new ArrayList();
456:                int size = serverMessageList.size();
457:                for (int i = 0; i < size; i++) {
458:                    MessageListEntry messageListEntry = (MessageListEntry) serverMessageList
459:                            .get(i);
460:                    String uidl = messageListEntry.uidl;
461:                    if (isExpunged(uidl))
462:                        continue;
463:                    if (hashSet != null && hashSet.contains(uidl))
464:                        continue;
465:                    toBeReturned.add(messageListEntry);
466:                }
467:                Log.debug("getMessagesToBeRetrieved "
468:                        + (System.currentTimeMillis() - start) + " ms");
469:                return toBeReturned;
470:            }
471:
472:            private boolean retrieveMessages(List messageList,
473:                    MailboxFileWriter writer) {
474:                Log.debug("entering retrieveMessages");
475:                long start = System.currentTimeMillis();
476:                for (int i = 0; i < messageList.size(); i++) {
477:                    String text = "Retrieving message " + (i + 1) + " of "
478:                            + messageList.size();
479:                    if (i == 0)
480:                        progressNotifier.setText(text); // Make sure the user sees this.
481:                    else
482:                        progressNotifier.progress(text);
483:                    MessageListEntry entry = (MessageListEntry) messageList
484:                            .get(i);
485:                    if (!retrieveMessage(entry.messageNumber, entry.uidl,
486:                            writer)) {
487:                        Log.error("retrieveMessages error retrieving message "
488:                                + entry.messageNumber);
489:                        return false;
490:                    }
491:                }
492:                progressNotifier.setText(cancelled ? "Cancelled, cleaning up"
493:                        : "");
494:                Log.debug("leaving retrieveMessages "
495:                        + (System.currentTimeMillis() - start) + " ms");
496:                return true;
497:            }
498:
499:            // Returns true if no error.
500:            private boolean retrieveMessage(int i, String uidl,
501:                    MailboxFileWriter writer) {
502:                String command = "list " + i;
503:                session.write(command);
504:                int size = 0;
505:                String response = session.readLine();
506:                String expected = "+OK " + i + " ";
507:                if (response != null && response.startsWith(expected)) {
508:                    try {
509:                        size = Integer.parseInt(response.substring(expected
510:                                .length()));
511:                    } catch (NumberFormatException e) {
512:                        Log.error(e);
513:                        return false; // Error!
514:                    }
515:                } else {
516:                    Log.error("retrieveMessage command failed: " + command);
517:                    Log.error("response = " + response);
518:                }
519:                command = "retr " + i;
520:                session.write(command);
521:                response = session.readLine();
522:                if (response == null || !response.startsWith("+OK")) {
523:                    Log.error("retrieveMessage command failed: " + command);
524:                    Log.error(response);
525:                    return false; // Error!
526:                }
527:                try {
528:                    final long messageStart = writer.getOffset();
529:                    writer.write("From - ");
530:                    writer.write(getDateTimeStamp());
531:                    writer.write('\n');
532:                    // Headers.
533:                    FastStringBuffer sb = new FastStringBuffer(2048);
534:                    while (true) {
535:                        String s = session.readLine();
536:                        if (s == null)
537:                            return false; // Error! (Reached end of stream before reaching end of headers.)
538:                        if (s.length() == 0) {
539:                            // Reached end of headers.
540:                            // Add X-J-Status.
541:                            String status = "X-J-Status: 0\n";
542:                            writer.write(status);
543:                            sb.append(status);
544:                            // Add X-UIDL.
545:                            if (uidl != null) {
546:                                writer.write("X-UIDL: ");
547:                                writer.write(uidl);
548:                                writer.write('\n');
549:                                sb.append("X-UIDL: ");
550:                                sb.append(uidl);
551:                                sb.append('\n');
552:                            }
553:                            writer.write('\n');
554:                            break;
555:                        }
556:                        if (s.toUpperCase().startsWith("X-UIDL"))
557:                            continue;
558:                        writer.write(s);
559:                        writer.write('\n');
560:                        sb.append(s);
561:                        sb.append('\n');
562:                    }
563:                    // Body.
564:                    boolean echo = session.getEcho();
565:                    session.setEcho(false);
566:                    while (true) {
567:                        String s = session.readLine();
568:                        if (s == null)
569:                            return false; // Error! (Reached end of stream before reaching end of message.)
570:                        if (s.equals("."))
571:                            break; // End of message.
572:                        if (s.length() > 1 && s.charAt(0) == '.'
573:                                && s.charAt(1) == '.') {
574:                            // Remove dot-stuffing.
575:                            s = s.substring(1);
576:                        } else if (s.startsWith("From ")) {
577:                            // Mangle lines starting with "From " in body of message.
578:                            writer.write('>');
579:                        }
580:                        writer.write(s);
581:                        writer.write('\n');
582:                    }
583:                    session.setEcho(echo);
584:                    // Add a newline after the end of the message.
585:                    writer.write('\n');
586:                    LocalMailboxEntry entry = new LocalMailboxEntry(entries
587:                            .size() + 1, messageStart, sb.toString());
588:                    entry.setNextMessageStart(writer.getOffset());
589:                    entry.setSize(size);
590:                    entry.setFlags(MailboxEntry.RECENT);
591:                    entries.add(entry);
592:                    setDirty(true);
593:                    return true; // No error.
594:                } catch (IOException e) {
595:                    Log.error(e);
596:                    return false; // Error!
597:                }
598:            }
599:
600:            private boolean deleteMessagesOnServer(List serverMessageList) {
601:                Log.debug("deleteMessagesOnServer need to delete "
602:                        + serverMessageList.size() + " messages");
603:                for (int i = 0; i < serverMessageList.size(); i++) {
604:                    MessageListEntry messageListEntry = (MessageListEntry) serverMessageList
605:                            .get(i);
606:                    session.write("dele " + messageListEntry.messageNumber);
607:                    String response = session.readLine();
608:                    if (response == null || !response.startsWith("+OK")) {
609:                        Log
610:                                .error("deleteMessagesOnServer dele failed response = "
611:                                        + response);
612:                        session.write("rset");
613:                        session.readLine();
614:                        return false; // Error!
615:                    }
616:                }
617:                Log.debug("deleteMessagesOnServer success!");
618:                return true;
619:            }
620:
621:            public void expunge() {
622:                if (lock()) {
623:                    setBusy(true);
624:                    saveDisplayState();
625:                    Debug.assertTrue(backgroundThread == null);
626:                    backgroundThread = new Thread(expungeProcess);
627:                    backgroundThread.start();
628:                }
629:            }
630:
631:            private Runnable expungeProcess = new BackgroundProcess() {
632:                public void run() {
633:                    try {
634:                        setBackgroundProcess(this );
635:                        progressNotifier = new StatusBarProgressNotifier(
636:                                PopMailbox.this );
637:                        progressNotifier.progressStart();
638:                        cancelled = false;
639:                        expungeInternal();
640:                    } finally {
641:                        setBackgroundProcess(null);
642:                        backgroundThread = null;
643:                        setBusy(false);
644:                        if (progressNotifier != null) {
645:                            if (cancelled)
646:                                progressNotifier.setText("Cancelled");
647:                            progressNotifier.progressStop();
648:                            progressNotifier = null;
649:                        }
650:                        unlock();
651:                        updateDisplay();
652:                    }
653:                }
654:
655:                public void cancel() {
656:                    Log.debug("expungeProcess.cancel");
657:                    cancelled = true;
658:                    if (backgroundThread != null && backgroundThread.isAlive())
659:                        backgroundThread.interrupt();
660:                    session.disconnect();
661:                }
662:            };
663:
664:            private void expungeInternal() {
665:                if (entries == null)
666:                    return; // No error.
667:                if (getBooleanProperty(Property.POP_EXPUNGE_DELETED_MESSAGES_ON_SERVER) == false
668:                        || getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER) == false) {
669:                    // This is the "local expunge only" case.
670:                    Log.debug("expungeInternal \"local expunge only\" case");
671:                    // First add all deleted entries to expunged list.
672:                    for (int i = entries.size() - 1; i >= 0; i--) {
673:                        MailboxEntry entry = (MailboxEntry) entries.get(i);
674:                        if (entry.isDeleted())
675:                            addToExpungedUidlsList(entry.getUidl());
676:                    }
677:                    writeExpungedUidlsList(); // BUG! Error handling?
678:                    rewriteMailbox(true); // BUG! Error handling!
679:                    refreshBuffer();
680:                    return;
681:                }
682:                // Reaching here, we want to expunge the deleted messages on the server too.
683:                Log.debug("expungeInternal \"expunge through\" case");
684:                if (!connect()) {
685:                    Log.error("expungeInternal can't connect");
686:                    return;
687:                }
688:                try {
689:                    int count = stat();
690:                    if (count < 0)
691:                        return; // Error.
692:                    if (count > 0) {
693:                        List serverMessageList = getServerMessageList(count);
694:                        for (int i = 0; i < entries.size(); i++) {
695:                            MailboxEntry entry = (MailboxEntry) entries.get(i);
696:                            if (entry.isDeleted()) {
697:                                String uidl = entry.getUidl();
698:                                if (!expungeUidl(uidl, serverMessageList))
699:                                    return; // Error!
700:                                if (cancelled) {
701:                                    progressNotifier.setText("Cancelled");
702:                                    return;
703:                                }
704:                            }
705:                        }
706:                        if (expungedUidlsList != null) {
707:                            // Expunge on the server messages that were previously expunged locally.
708:                            Iterator it = expungedUidlsList.iterator();
709:                            while (it.hasNext()) {
710:                                String uidl = (String) it.next();
711:                                if (!expungeUidl(uidl, serverMessageList))
712:                                    return; // Error!
713:                                if (cancelled) {
714:                                    progressNotifier.setText("Cancelled");
715:                                    return;
716:                                }
717:                            }
718:                        }
719:                    }
720:                    progressNotifier.progress("Logging out...");
721:                    if (!session.logout())
722:                        return; // Error!
723:                    // All deletions have been completed on the server.
724:                    progressNotifier.progress("Saving mailbox...");
725:                    rewriteMailbox(true); // BUG! Error handling!
726:                    progressNotifier.setText("Saving mailbox...done");
727:                    refreshBuffer();
728:                } finally {
729:                    session.disconnect();
730:                }
731:            }
732:
733:            private boolean expungeUidl(String uidl, List serverMessageList) {
734:                if (uidl != null) {
735:                    for (int j = serverMessageList.size() - 1; j >= 0; j--) {
736:                        MessageListEntry messageListEntry = (MessageListEntry) serverMessageList
737:                                .get(j);
738:                        if (uidl.equals(messageListEntry.uidl)) {
739:                            if (progressNotifier != null) {
740:                                FastStringBuffer sb = new FastStringBuffer(
741:                                        "Deleting message ");
742:                                sb.append(messageListEntry.messageNumber);
743:                                sb.append(" on server");
744:                                progressNotifier.progress(sb.toString());
745:                            }
746:                            session.write("dele "
747:                                    + messageListEntry.messageNumber);
748:                            String response = session.readLine();
749:                            if (response != null && response.startsWith("+OK"))
750:                                return true;
751:                            // Error!
752:                            Log.error("expungeUidl dele failed response = "
753:                                    + response);
754:                            session.write("rset");
755:                            session.readLine();
756:                            return false;
757:                        }
758:                    }
759:                }
760:                // Didn't find uidl.
761:                return true;
762:            }
763:
764:            private HashSet expungedUidlsList;
765:
766:            private final boolean isExpunged(String uidl) {
767:                if (expungedUidlsList == null)
768:                    return false;
769:                return expungedUidlsList.contains(uidl);
770:            }
771:
772:            private final void addToExpungedUidlsList(String uidl) {
773:                if (expungedUidlsList == null)
774:                    expungedUidlsList = new HashSet();
775:                expungedUidlsList.add(uidl);
776:            }
777:
778:            // Prune our list of expunged uidls, removing entries that no longer exist
779:            // on the server.
780:            private void pruneExpungedUidlsList(List serverMessageList) {
781:                Log.debug("pruneExpungedUidlsList");
782:                if (expungedUidlsList == null)
783:                    return; // Nothing to do.
784:                boolean changed = false;
785:                long start = System.currentTimeMillis();
786:                int size = serverMessageList.size();
787:                HashSet serverUidls = new HashSet(size);
788:                for (int i = 0; i < size; i++) {
789:                    MessageListEntry entry = (MessageListEntry) serverMessageList
790:                            .get(i);
791:                    serverUidls.add(entry.uidl);
792:                }
793:                Iterator it = expungedUidlsList.iterator();
794:                while (it.hasNext()) {
795:                    String uidl = (String) it.next();
796:                    if (!serverUidls.contains(uidl)) {
797:                        Log.warn("removing uidl " + uidl
798:                                + " (no longer exists on server)");
799:                        it.remove();
800:                        changed = true;
801:                    }
802:                }
803:                if (changed)
804:                    writeExpungedUidlsList();
805:                Log.debug("pruneExpungedUidlsList "
806:                        + (System.currentTimeMillis() - start) + " ms");
807:            }
808:
809:            private void readExpungedUidlsList() {
810:                File mailboxFile = getMailboxFile();
811:                if (mailboxFile == null) {
812:                    Debug.bug("readExpungedUidlsList mailboxFile is null");
813:                    return;
814:                }
815:                String filename = mailboxFile.canonicalPath() + ".expunged";
816:                try {
817:                    BufferedReader reader = new BufferedReader(new FileReader(
818:                            filename));
819:                    String s;
820:                    while ((s = reader.readLine()) != null) {
821:                        if (expungedUidlsList == null)
822:                            expungedUidlsList = new HashSet();
823:                        expungedUidlsList.add(s);
824:                    }
825:                    reader.close();
826:                } catch (FileNotFoundException e) {
827:                    // Might happen.
828:                } catch (IOException e) {
829:                    Log.error(e);
830:                }
831:            }
832:
833:            private void writeExpungedUidlsList() {
834:                File mailboxFile = getMailboxFile();
835:                if (mailboxFile == null) {
836:                    Debug.bug("writeExpungedUidls mailboxFile is null");
837:                    return;
838:                }
839:                String filename = mailboxFile.canonicalPath() + ".expunged";
840:                if (expungedUidlsList == null || expungedUidlsList.size() == 0) {
841:                    File file = File.getInstance(filename);
842:                    if (file.isFile())
843:                        file.delete();
844:                    return;
845:                }
846:                try {
847:                    BufferedWriter writer = new BufferedWriter(new FileWriter(
848:                            filename));
849:                    Iterator it = expungedUidlsList.iterator();
850:                    while (it.hasNext()) {
851:                        writer.write((String) it.next());
852:                        writer.newLine();
853:                    }
854:                    writer.flush();
855:                    writer.close();
856:                } catch (IOException e) {
857:                    Log.error(e);
858:                }
859:            }
860:
861:            private static final SimpleDateFormat df = new SimpleDateFormat(
862:                    "EEE MMM dd HH:mm:ss yyyy", Locale.US);
863:
864:            private final String getDateTimeStamp() {
865:                return df.format(Calendar.getInstance().getTime());
866:            }
867:
868:            private File getLocalStore() {
869:                if (localStore != null)
870:                    return localStore;
871:                File popDir = File.getInstance(Directories.getMailDirectory(),
872:                        "pop");
873:                if (!popDir.isDirectory()) {
874:                    popDir.mkdirs();
875:                    if (!popDir.isDirectory()) {
876:                        Log.error("can't make directory "
877:                                + popDir.canonicalPath());
878:                        return null;
879:                    }
880:                }
881:                File catalogFile = File.getInstance(popDir, "catalog");
882:                Properties catalog = new Properties();
883:                // Load the catalog.
884:                try {
885:                    if (catalogFile.isFile()) {
886:                        InputStream in = catalogFile.getInputStream();
887:                        catalog.load(in);
888:                        in.close();
889:                    }
890:                } catch (IOException e) {
891:                    Log.error(e);
892:                }
893:                String mailboxName = getUrl().toString();
894:                if (mailboxName.startsWith("pop://"))
895:                    mailboxName = mailboxName.substring(6);
896:                String filename = catalog.getProperty(mailboxName);
897:                if (filename != null) // Found existing store.
898:                    return localStore = File.getInstance(popDir, filename);
899:                File file = Utilities.getTempFile(popDir);
900:                catalog.put(mailboxName, file.getName());
901:                try {
902:                    OutputStream out = catalogFile.getOutputStream();
903:                    catalog.save(out, null);
904:                    out.flush();
905:                    out.close();
906:                    return localStore = file;
907:                } catch (IOException e) {
908:                    Log.error(e);
909:                    return null;
910:                }
911:            }
912:
913:            public void dispose() {
914:                Log.debug("PopMailbox.dispose");
915:                Runnable disposeRunnable = new Runnable() {
916:                    public void run() {
917:                        try {
918:                            Log
919:                                    .debug("disposeRunnable.run() calling acquire()...");
920:                            acquire(); // Blocks, may throw InterruptedException.
921:                            Log
922:                                    .debug("disposeRunnable.run() back from acquire()");
923:                            if (dirty) {
924:                                final Object pending = new Object();
925:                                Editor.getPendingOperations().add(pending);
926:                                Log
927:                                        .debug("disposeRunnable.run() calling rewriteMailbox()...");
928:                                rewriteMailbox(false);
929:                                Log
930:                                        .debug("disposeRunnable.run() back from rewriteMailbox()");
931:                                Editor.getPendingOperations().remove(pending);
932:                            }
933:                            Debug.assertTrue(session != null);
934:                            Log
935:                                    .debug("disposeRunnable.run() calling session.logout()...");
936:                            session.logout();
937:                            release();
938:                            Log
939:                                    .debug("disposeRunnable.run() back from release()");
940:                        } catch (InterruptedException e) {
941:                            Log.error(e);
942:                        }
943:                    }
944:                };
945:                new Thread(disposeRunnable).start();
946:                MailboxProperties.saveProperties(this );
947:            }
948:
949:            protected void finalize() throws Throwable {
950:                Log.debug("PopMailbox.finalize");
951:                super .finalize();
952:            }
953:
954:            public String toString() {
955:                int newMessageCount = getNewMessageCount();
956:                if (newMessageCount > 0) {
957:                    FastStringBuffer sb = new FastStringBuffer(url.toString());
958:                    sb.append(" (");
959:                    sb.append(newMessageCount);
960:                    sb.append(" new)");
961:                    return sb.toString();
962:                } else
963:                    return url.toString();
964:            }
965:
966:            public String getTitle() {
967:                return toString();
968:            }
969:        }
970:
971:        class MessageListEntry {
972:            int messageNumber;
973:            String uidl;
974:
975:            MessageListEntry(int messageNumber, String uidl) {
976:                this.messageNumber = messageNumber;
977:                this.uidl = uidl;
978:            }
979:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.