Source Code Cross Referenced for POP3Handler.java in  » Web-Mail » james-2.3.1 » org » apache » james » pop3server » 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 » Web Mail » james 2.3.1 » org.apache.james.pop3server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /****************************************************************
0002:         * Licensed to the Apache Software Foundation (ASF) under one   *
0003:         * or more contributor license agreements.  See the NOTICE file *
0004:         * distributed with this work for additional information        *
0005:         * regarding copyright ownership.  The ASF licenses this file   *
0006:         * to you under the Apache License, Version 2.0 (the            *
0007:         * "License"); you may not use this file except in compliance   *
0008:         * with the License.  You may obtain a copy of the License at   *
0009:         *                                                              *
0010:         *   http://www.apache.org/licenses/LICENSE-2.0                 *
0011:         *                                                              *
0012:         * Unless required by applicable law or agreed to in writing,   *
0013:         * software distributed under the License is distributed on an  *
0014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
0015:         * KIND, either express or implied.  See the License for the    *
0016:         * specific language governing permissions and limitations      *
0017:         * under the License.                                           *
0018:         ****************************************************************/package org.apache.james.pop3server;
0019:
0020:        import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
0021:        import org.apache.avalon.excalibur.pool.Poolable;
0022:        import org.apache.avalon.framework.container.ContainerUtil;
0023:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
0024:        import org.apache.commons.collections.ListUtils;
0025:        import org.apache.james.Constants;
0026:        import org.apache.james.core.MailImpl;
0027:        import org.apache.james.services.MailRepository;
0028:        import org.apache.james.util.CRLFTerminatedReader;
0029:        import org.apache.james.util.ExtraDotOutputStream;
0030:        import org.apache.james.util.InternetPrintWriter;
0031:        import org.apache.james.util.watchdog.BytesWrittenResetOutputStream;
0032:        import org.apache.james.util.watchdog.Watchdog;
0033:        import org.apache.james.util.watchdog.WatchdogTarget;
0034:        import org.apache.mailet.Mail;
0035:
0036:        import javax.mail.MessagingException;
0037:        import javax.mail.internet.MimeMessage;
0038:
0039:        import java.io.BufferedInputStream;
0040:        import java.io.BufferedOutputStream;
0041:        import java.io.BufferedReader;
0042:        import java.io.IOException;
0043:        import java.io.InputStreamReader;
0044:        import java.io.OutputStream;
0045:        import java.io.PrintWriter;
0046:        import java.net.Socket;
0047:        import java.util.ArrayList;
0048:        import java.util.Enumeration;
0049:        import java.util.Iterator;
0050:        import java.util.List;
0051:        import java.util.Locale;
0052:        import java.util.StringTokenizer;
0053:
0054:        /**
0055:         * The handler class for POP3 connections.
0056:         *
0057:         */
0058:        public class POP3Handler extends AbstractLogEnabled implements 
0059:                ConnectionHandler, Poolable {
0060:
0061:            // POP3 Server identification string used in POP3 headers
0062:            private static final String softwaretype = "JAMES POP3 Server "
0063:                    + Constants.SOFTWARE_VERSION;
0064:
0065:            // POP3 response prefixes
0066:            private final static String OK_RESPONSE = "+OK"; // OK response.  Requested content
0067:            // will follow
0068:
0069:            private final static String ERR_RESPONSE = "-ERR"; // Error response.  Requested content
0070:            // will not be provided.  This prefix
0071:            // is followed by a more detailed
0072:            // error message
0073:
0074:            // Authentication states for the POP3 interaction
0075:
0076:            private final static int AUTHENTICATION_READY = 0; // Waiting for user id
0077:
0078:            private final static int AUTHENTICATION_USERSET = 1; // User id provided, waiting for
0079:            // password
0080:
0081:            private final static int TRANSACTION = 2; // A valid user id/password combination
0082:            // has been provided.  In this state
0083:            // the client can access the mailbox
0084:            // of the specified user
0085:
0086:            private static final Mail DELETED = new MailImpl(); // A placeholder for emails deleted
0087:            // during the course of the POP3
0088:            // transaction.  This Mail instance
0089:            // is used to enable fast checks as
0090:            // to whether an email has been
0091:            // deleted from the inbox.
0092:
0093:            /**
0094:             * The per-service configuration data that applies to all handlers
0095:             */
0096:            private POP3HandlerConfigurationData theConfigData;
0097:
0098:            /**
0099:             * The mail server's copy of the user's inbox
0100:             */
0101:            private MailRepository userInbox;
0102:
0103:            /**
0104:             * The thread executing this handler
0105:             */
0106:            private Thread handlerThread;
0107:
0108:            /**
0109:             * The TCP/IP socket over which the POP3 interaction
0110:             * is occurring
0111:             */
0112:            private Socket socket;
0113:
0114:            /**
0115:             * The reader associated with incoming characters.
0116:             */
0117:            private CRLFTerminatedReader in;
0118:
0119:            /**
0120:             * The writer to which outgoing messages are written.
0121:             */
0122:            private PrintWriter out;
0123:
0124:            /**
0125:             * The socket's output stream
0126:             */
0127:            private OutputStream outs;
0128:
0129:            /**
0130:             * The current transaction state of the handler
0131:             */
0132:            private int state;
0133:
0134:            /**
0135:             * The user id associated with the POP3 dialogue
0136:             */
0137:            private String user;
0138:
0139:            /**
0140:             * A dynamic list representing the set of
0141:             * emails in the user's inbox at any given time
0142:             * during the POP3 transaction.
0143:             */
0144:            private ArrayList userMailbox = new ArrayList();
0145:
0146:            private ArrayList backupUserMailbox; // A snapshot list representing the set of
0147:            // emails in the user's inbox at the beginning
0148:            // of the transaction
0149:
0150:            /**
0151:             * The watchdog being used by this handler to deal with idle timeouts.
0152:             */
0153:            private Watchdog theWatchdog;
0154:
0155:            /**
0156:             * The watchdog target that idles out this handler.
0157:             */
0158:            private WatchdogTarget theWatchdogTarget = new POP3WatchdogTarget();
0159:
0160:            /**
0161:             * Set the configuration data for the handler.
0162:             *
0163:             * @param theData the configuration data
0164:             */
0165:            void setConfigurationData(POP3HandlerConfigurationData theData) {
0166:                theConfigData = theData;
0167:            }
0168:
0169:            /**
0170:             * Set the Watchdog for use by this handler.
0171:             *
0172:             * @param theWatchdog the watchdog
0173:             */
0174:            void setWatchdog(Watchdog theWatchdog) {
0175:                this .theWatchdog = theWatchdog;
0176:            }
0177:
0178:            /**
0179:             * Gets the Watchdog Target that should be used by Watchdogs managing
0180:             * this connection.
0181:             *
0182:             * @return the WatchdogTarget
0183:             */
0184:            WatchdogTarget getWatchdogTarget() {
0185:                return theWatchdogTarget;
0186:            }
0187:
0188:            /**
0189:             * Idle out this connection
0190:             */
0191:            void idleClose() {
0192:                if (getLogger() != null) {
0193:                    getLogger().error("POP3 Connection has idled out.");
0194:                }
0195:                try {
0196:                    if (socket != null) {
0197:                        socket.close();
0198:                    }
0199:                } catch (Exception e) {
0200:                    // ignored
0201:                } finally {
0202:                    socket = null;
0203:                }
0204:
0205:                synchronized (this ) {
0206:                    // Interrupt the thread to recover from internal hangs
0207:                    if (handlerThread != null) {
0208:                        handlerThread.interrupt();
0209:                        handlerThread = null;
0210:                    }
0211:                }
0212:
0213:            }
0214:
0215:            /**
0216:             * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
0217:             */
0218:            public void handleConnection(Socket connection) throws IOException {
0219:
0220:                String remoteHost = "";
0221:                String remoteIP = "";
0222:
0223:                try {
0224:                    this .socket = connection;
0225:                    synchronized (this ) {
0226:                        handlerThread = Thread.currentThread();
0227:                    }
0228:                    // in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ASCII"), 512);
0229:                    in = new CRLFTerminatedReader(new BufferedInputStream(
0230:                            socket.getInputStream(), 512), "ASCII");
0231:                    remoteIP = socket.getInetAddress().getHostAddress();
0232:                    remoteHost = socket.getInetAddress().getHostName();
0233:                } catch (Exception e) {
0234:                    if (getLogger().isErrorEnabled()) {
0235:                        StringBuffer exceptionBuffer = new StringBuffer(256)
0236:                                .append("Cannot open connection from ").append(
0237:                                        remoteHost).append(" (").append(
0238:                                        remoteIP).append("): ").append(
0239:                                        e.getMessage());
0240:                        getLogger().error(exceptionBuffer.toString(), e);
0241:                    }
0242:                }
0243:
0244:                if (getLogger().isInfoEnabled()) {
0245:                    StringBuffer logBuffer = new StringBuffer(128).append(
0246:                            "Connection from ").append(remoteHost).append(" (")
0247:                            .append(remoteIP).append(") ");
0248:                    getLogger().info(logBuffer.toString());
0249:                }
0250:
0251:                try {
0252:                    outs = new BufferedOutputStream(socket.getOutputStream(),
0253:                            1024);
0254:                    out = new InternetPrintWriter(outs, true);
0255:                    state = AUTHENTICATION_READY;
0256:                    user = "unknown";
0257:                    StringBuffer responseBuffer = new StringBuffer(256).append(
0258:                            OK_RESPONSE).append(" ").append(
0259:                            theConfigData.getHelloName()).append(
0260:                            " POP3 server (").append(POP3Handler.softwaretype)
0261:                            .append(") ready ");
0262:                    out.println(responseBuffer.toString());
0263:
0264:                    theWatchdog.start();
0265:                    while (parseCommand(readCommandLine())) {
0266:                        theWatchdog.reset();
0267:                    }
0268:                    theWatchdog.stop();
0269:                    if (getLogger().isInfoEnabled()) {
0270:                        StringBuffer logBuffer = new StringBuffer(128).append(
0271:                                "Connection for ").append(user)
0272:                                .append(" from ").append(remoteHost).append(
0273:                                        " (").append(remoteIP).append(
0274:                                        ") closed.");
0275:                        getLogger().info(logBuffer.toString());
0276:                    }
0277:                } catch (Exception e) {
0278:                    out.println(ERR_RESPONSE + " Error closing connection.");
0279:                    out.flush();
0280:                    StringBuffer exceptionBuffer = new StringBuffer(128)
0281:                            .append("Exception during connection from ")
0282:                            .append(remoteHost).append(" (").append(remoteIP)
0283:                            .append(") : ").append(e.getMessage());
0284:                    getLogger().error(exceptionBuffer.toString(), e);
0285:                } finally {
0286:                    resetHandler();
0287:                }
0288:            }
0289:
0290:            /**
0291:             * Resets the handler data to a basic state.
0292:             */
0293:            private void resetHandler() {
0294:
0295:                if (theWatchdog != null) {
0296:                    ContainerUtil.dispose(theWatchdog);
0297:                    theWatchdog = null;
0298:                }
0299:
0300:                // Close and clear streams, sockets
0301:
0302:                try {
0303:                    if (socket != null) {
0304:                        socket.close();
0305:                        socket = null;
0306:                    }
0307:                } catch (IOException ioe) {
0308:                    // Ignoring exception on close
0309:                } finally {
0310:                    socket = null;
0311:                }
0312:
0313:                try {
0314:                    if (in != null) {
0315:                        in.close();
0316:                    }
0317:                } catch (Exception e) {
0318:                    // Ignored
0319:                } finally {
0320:                    in = null;
0321:                }
0322:
0323:                try {
0324:                    if (out != null) {
0325:                        out.close();
0326:                    }
0327:                } catch (Exception e) {
0328:                    // Ignored
0329:                } finally {
0330:                    out = null;
0331:                }
0332:
0333:                try {
0334:                    if (outs != null) {
0335:                        outs.close();
0336:                    }
0337:                } catch (Exception e) {
0338:                    // Ignored
0339:                } finally {
0340:                    outs = null;
0341:                }
0342:
0343:                synchronized (this ) {
0344:                    handlerThread = null;
0345:                }
0346:
0347:                // Clear user data
0348:                user = null;
0349:                userInbox = null;
0350:                if (userMailbox != null) {
0351:                    userMailbox.clear();
0352:                    userMailbox = null;
0353:                }
0354:
0355:                if (backupUserMailbox != null) {
0356:                    backupUserMailbox.clear();
0357:                    backupUserMailbox = null;
0358:                }
0359:
0360:                // Clear config data
0361:                theConfigData = null;
0362:            }
0363:
0364:            /**
0365:             * Implements a "stat".  If the handler is currently in
0366:             * a transaction state, this amounts to a rollback of the
0367:             * mailbox contents to the beginning of the transaction.
0368:             * This method is also called when first entering the
0369:             * transaction state to initialize the handler copies of the
0370:             * user inbox.
0371:             *
0372:             */
0373:            private void stat() {
0374:                userMailbox = new ArrayList();
0375:                userMailbox.add(DELETED);
0376:                try {
0377:                    for (Iterator it = userInbox.list(); it.hasNext();) {
0378:                        String key = (String) it.next();
0379:                        Mail mc = userInbox.retrieve(key);
0380:                        // Retrieve can return null if the mail is no longer in the store.
0381:                        // In this case we simply continue to the next key
0382:                        if (mc == null) {
0383:                            continue;
0384:                        }
0385:                        userMailbox.add(mc);
0386:                    }
0387:                } catch (MessagingException e) {
0388:                    // In the event of an exception being thrown there may or may not be anything in userMailbox
0389:                    getLogger().error("Unable to STAT mail box ", e);
0390:                } finally {
0391:                    backupUserMailbox = (ArrayList) userMailbox.clone();
0392:                }
0393:            }
0394:
0395:            /**
0396:             * Reads a line of characters off the command line.
0397:             *
0398:             * @return the trimmed input line
0399:             * @throws IOException if an exception is generated reading in the input characters
0400:             */
0401:            final String readCommandLine() throws IOException {
0402:                for (;;)
0403:                    try {
0404:                        String commandLine = in.readLine();
0405:                        if (commandLine != null) {
0406:                            commandLine = commandLine.trim();
0407:                        }
0408:                        return commandLine;
0409:                    } catch (CRLFTerminatedReader.TerminationException te) {
0410:                        writeLoggedFlushedResponse("-ERR Syntax error at character position "
0411:                                + te.position()
0412:                                + ". CR and LF must be CRLF paired.  See RFC 1939 #3.");
0413:                    }
0414:            }
0415:
0416:            /**
0417:             * This method parses POP3 commands read off the wire in handleConnection.
0418:             * Actual processing of the command (possibly including additional back and
0419:             * forth communication with the client) is delegated to one of a number of
0420:             * command specific handler methods.  The primary purpose of this method is
0421:             * to parse the raw command string to determine exactly which handler should
0422:             * be called.  It returns true if expecting additional commands, false otherwise.
0423:             *
0424:             * @param rawCommand the raw command string passed in over the socket
0425:             *
0426:             * @return whether additional commands are expected.
0427:             */
0428:            private boolean parseCommand(String rawCommand) {
0429:                if (rawCommand == null) {
0430:                    return false;
0431:                }
0432:                boolean returnValue = true;
0433:                String command = rawCommand;
0434:                StringTokenizer commandLine = new StringTokenizer(command, " ");
0435:                int arguments = commandLine.countTokens();
0436:                if (arguments == 0) {
0437:                    return true;
0438:                } else if (arguments > 0) {
0439:                    command = commandLine.nextToken().toUpperCase(Locale.US);
0440:                }
0441:                if (getLogger().isDebugEnabled()) {
0442:                    // Don't display password in logger
0443:                    if (!command.equals("PASS")) {
0444:                        getLogger().debug("Command received: " + rawCommand);
0445:                    } else {
0446:                        getLogger().debug(
0447:                                "Command received: PASS <password omitted>");
0448:                    }
0449:                }
0450:                String argument = null;
0451:                if (arguments > 1) {
0452:                    argument = commandLine.nextToken();
0453:                }
0454:                String argument1 = null;
0455:                if (arguments > 2) {
0456:                    argument1 = commandLine.nextToken();
0457:                }
0458:
0459:                if (command.equals("USER")) {
0460:                    doUSER(command, argument, argument1);
0461:                } else if (command.equals("PASS")) {
0462:                    doPASS(command, argument, argument1);
0463:                } else if (command.equals("STAT")) {
0464:                    doSTAT(command, argument, argument1);
0465:                } else if (command.equals("LIST")) {
0466:                    doLIST(command, argument, argument1);
0467:                } else if (command.equals("UIDL")) {
0468:                    doUIDL(command, argument, argument1);
0469:                } else if (command.equals("RSET")) {
0470:                    doRSET(command, argument, argument1);
0471:                } else if (command.equals("DELE")) {
0472:                    doDELE(command, argument, argument1);
0473:                } else if (command.equals("NOOP")) {
0474:                    doNOOP(command, argument, argument1);
0475:                } else if (command.equals("RETR")) {
0476:                    doRETR(command, argument, argument1);
0477:                } else if (command.equals("TOP")) {
0478:                    doTOP(command, argument, argument1);
0479:                } else if (command.equals("QUIT")) {
0480:                    returnValue = false;
0481:                    doQUIT(command, argument, argument1);
0482:                } else {
0483:                    doUnknownCmd(command, argument, argument1);
0484:                }
0485:                return returnValue;
0486:            }
0487:
0488:            /**
0489:             * Handler method called upon receipt of a USER command.
0490:             * Reads in the user id.
0491:             *
0492:             * @param command the command parsed by the parseCommand method
0493:             * @param argument the first argument parsed by the parseCommand method
0494:             * @param argument1 the second argument parsed by the parseCommand method
0495:             */
0496:            private void doUSER(String command, String argument,
0497:                    String argument1) {
0498:                String responseString = null;
0499:                if (state == AUTHENTICATION_READY && argument != null) {
0500:                    user = argument;
0501:                    state = AUTHENTICATION_USERSET;
0502:                    responseString = OK_RESPONSE;
0503:                } else {
0504:                    responseString = ERR_RESPONSE;
0505:                }
0506:                writeLoggedFlushedResponse(responseString);
0507:            }
0508:
0509:            /**
0510:             * Handler method called upon receipt of a PASS command.
0511:             * Reads in and validates the password.
0512:             *
0513:             * @param command the command parsed by the parseCommand method
0514:             * @param argument the first argument parsed by the parseCommand method
0515:             * @param argument1 the second argument parsed by the parseCommand method
0516:             */
0517:            private void doPASS(String command, String argument,
0518:                    String argument1) {
0519:                String responseString = null;
0520:                if (state == AUTHENTICATION_USERSET && argument != null) {
0521:                    String passArg = argument;
0522:                    if (theConfigData.getUsersRepository().test(user, passArg)) {
0523:                        StringBuffer responseBuffer = new StringBuffer(64)
0524:                                .append(OK_RESPONSE).append(" Welcome ")
0525:                                .append(user);
0526:                        responseString = responseBuffer.toString();
0527:                        state = TRANSACTION;
0528:                        writeLoggedFlushedResponse(responseString);
0529:                        userInbox = theConfigData.getMailServer().getUserInbox(
0530:                                user);
0531:                        stat();
0532:                    } else {
0533:                        responseString = ERR_RESPONSE
0534:                                + " Authentication failed.";
0535:                        state = AUTHENTICATION_READY;
0536:                        writeLoggedFlushedResponse(responseString);
0537:                    }
0538:                } else {
0539:                    responseString = ERR_RESPONSE;
0540:                    writeLoggedFlushedResponse(responseString);
0541:                }
0542:            }
0543:
0544:            /**
0545:             * Handler method called upon receipt of a STAT command.
0546:             * Returns the number of messages in the mailbox and its
0547:             * aggregate size.
0548:             *
0549:             * @param command the command parsed by the parseCommand method
0550:             * @param argument the first argument parsed by the parseCommand method
0551:             * @param argument1 the second argument parsed by the parseCommand method
0552:             */
0553:            private void doSTAT(String command, String argument,
0554:                    String argument1) {
0555:                String responseString = null;
0556:                if (state == TRANSACTION) {
0557:                    long size = 0;
0558:                    int count = 0;
0559:                    try {
0560:                        for (Iterator i = userMailbox.iterator(); i.hasNext();) {
0561:                            Mail mc = (Mail) i.next();
0562:                            if (mc != DELETED) {
0563:                                size += mc.getMessageSize();
0564:                                count++;
0565:                            }
0566:                        }
0567:                        StringBuffer responseBuffer = new StringBuffer(32)
0568:                                .append(OK_RESPONSE).append(" ").append(count)
0569:                                .append(" ").append(size);
0570:                        responseString = responseBuffer.toString();
0571:                        writeLoggedFlushedResponse(responseString);
0572:                    } catch (MessagingException me) {
0573:                        responseString = ERR_RESPONSE;
0574:                        writeLoggedFlushedResponse(responseString);
0575:                    }
0576:                } else {
0577:                    responseString = ERR_RESPONSE;
0578:                    writeLoggedFlushedResponse(responseString);
0579:                }
0580:            }
0581:
0582:            /**
0583:             * Handler method called upon receipt of a LIST command.
0584:             * Returns the number of messages in the mailbox and its
0585:             * aggregate size, or optionally, the number and size of
0586:             * a single message.
0587:             *
0588:             * @param command the command parsed by the parseCommand method
0589:             * @param argument the first argument parsed by the parseCommand method
0590:             * @param argument1 the second argument parsed by the parseCommand method
0591:             */
0592:            private void doLIST(String command, String argument,
0593:                    String argument1) {
0594:                String responseString = null;
0595:                if (state == TRANSACTION) {
0596:                    if (argument == null) {
0597:                        long size = 0;
0598:                        int count = 0;
0599:                        try {
0600:                            for (Iterator i = userMailbox.iterator(); i
0601:                                    .hasNext();) {
0602:                                Mail mc = (Mail) i.next();
0603:                                if (mc != DELETED) {
0604:                                    size += mc.getMessageSize();
0605:                                    count++;
0606:                                }
0607:                            }
0608:                            StringBuffer responseBuffer = new StringBuffer(32)
0609:                                    .append(OK_RESPONSE).append(" ").append(
0610:                                            count).append(" ").append(size);
0611:                            responseString = responseBuffer.toString();
0612:                            writeLoggedFlushedResponse(responseString);
0613:                            count = 0;
0614:                            for (Iterator i = userMailbox.iterator(); i
0615:                                    .hasNext(); count++) {
0616:                                Mail mc = (Mail) i.next();
0617:
0618:                                if (mc != DELETED) {
0619:                                    responseBuffer = new StringBuffer(16)
0620:                                            .append(count).append(" ").append(
0621:                                                    mc.getMessageSize());
0622:                                    out.println(responseBuffer.toString());
0623:                                }
0624:                            }
0625:                            out.println(".");
0626:                            out.flush();
0627:                        } catch (MessagingException me) {
0628:                            responseString = ERR_RESPONSE;
0629:                            writeLoggedFlushedResponse(responseString);
0630:                        }
0631:                    } else {
0632:                        int num = 0;
0633:                        try {
0634:                            num = Integer.parseInt(argument);
0635:                            Mail mc = (Mail) userMailbox.get(num);
0636:                            if (mc != DELETED) {
0637:                                StringBuffer responseBuffer = new StringBuffer(
0638:                                        64).append(OK_RESPONSE).append(" ")
0639:                                        .append(num).append(" ").append(
0640:                                                mc.getMessageSize());
0641:                                responseString = responseBuffer.toString();
0642:                                writeLoggedFlushedResponse(responseString);
0643:                            } else {
0644:                                StringBuffer responseBuffer = new StringBuffer(
0645:                                        64).append(ERR_RESPONSE).append(
0646:                                        " Message (").append(num).append(
0647:                                        ") already deleted.");
0648:                                responseString = responseBuffer.toString();
0649:                                writeLoggedFlushedResponse(responseString);
0650:                            }
0651:                        } catch (IndexOutOfBoundsException npe) {
0652:                            StringBuffer responseBuffer = new StringBuffer(64)
0653:                                    .append(ERR_RESPONSE).append(" Message (")
0654:                                    .append(num).append(") does not exist.");
0655:                            responseString = responseBuffer.toString();
0656:                            writeLoggedFlushedResponse(responseString);
0657:                        } catch (NumberFormatException nfe) {
0658:                            StringBuffer responseBuffer = new StringBuffer(64)
0659:                                    .append(ERR_RESPONSE).append(" ").append(
0660:                                            argument).append(
0661:                                            " is not a valid number");
0662:                            responseString = responseBuffer.toString();
0663:                            writeLoggedFlushedResponse(responseString);
0664:                        } catch (MessagingException me) {
0665:                            responseString = ERR_RESPONSE;
0666:                            writeLoggedFlushedResponse(responseString);
0667:                        }
0668:                    }
0669:                } else {
0670:                    responseString = ERR_RESPONSE;
0671:                    writeLoggedFlushedResponse(responseString);
0672:                }
0673:            }
0674:
0675:            /**
0676:             * Handler method called upon receipt of a UIDL command.
0677:             * Returns a listing of message ids to the client.
0678:             *
0679:             * @param command the command parsed by the parseCommand method
0680:             * @param argument the first argument parsed by the parseCommand method
0681:             * @param argument1 the second argument parsed by the parseCommand method
0682:             */
0683:            private void doUIDL(String command, String argument,
0684:                    String argument1) {
0685:                String responseString = null;
0686:                if (state == TRANSACTION) {
0687:                    if (argument == null) {
0688:                        responseString = OK_RESPONSE
0689:                                + " unique-id listing follows";
0690:                        writeLoggedFlushedResponse(responseString);
0691:                        int count = 0;
0692:                        for (Iterator i = userMailbox.iterator(); i.hasNext(); count++) {
0693:                            Mail mc = (Mail) i.next();
0694:                            if (mc != DELETED) {
0695:                                StringBuffer responseBuffer = new StringBuffer(
0696:                                        64).append(count).append(" ").append(
0697:                                        mc.getName());
0698:                                out.println(responseBuffer.toString());
0699:                            }
0700:                        }
0701:                        out.println(".");
0702:                        out.flush();
0703:                    } else {
0704:                        int num = 0;
0705:                        try {
0706:                            num = Integer.parseInt(argument);
0707:                            Mail mc = (Mail) userMailbox.get(num);
0708:                            if (mc != DELETED) {
0709:                                StringBuffer responseBuffer = new StringBuffer(
0710:                                        64).append(OK_RESPONSE).append(" ")
0711:                                        .append(num).append(" ").append(
0712:                                                mc.getName());
0713:                                responseString = responseBuffer.toString();
0714:                                writeLoggedFlushedResponse(responseString);
0715:                            } else {
0716:                                StringBuffer responseBuffer = new StringBuffer(
0717:                                        64).append(ERR_RESPONSE).append(
0718:                                        " Message (").append(num).append(
0719:                                        ") already deleted.");
0720:                                responseString = responseBuffer.toString();
0721:                                writeLoggedFlushedResponse(responseString);
0722:                            }
0723:                        } catch (IndexOutOfBoundsException npe) {
0724:                            StringBuffer responseBuffer = new StringBuffer(64)
0725:                                    .append(ERR_RESPONSE).append(" Message (")
0726:                                    .append(num).append(") does not exist.");
0727:                            responseString = responseBuffer.toString();
0728:                            writeLoggedFlushedResponse(responseString);
0729:                        } catch (NumberFormatException nfe) {
0730:                            StringBuffer responseBuffer = new StringBuffer(64)
0731:                                    .append(ERR_RESPONSE).append(" ").append(
0732:                                            argument).append(
0733:                                            " is not a valid number");
0734:                            responseString = responseBuffer.toString();
0735:                            writeLoggedFlushedResponse(responseString);
0736:                        }
0737:                    }
0738:                } else {
0739:                    writeLoggedFlushedResponse(ERR_RESPONSE);
0740:                }
0741:            }
0742:
0743:            /**
0744:             * Handler method called upon receipt of a RSET command.
0745:             * Calls stat() to reset the mailbox.
0746:             *
0747:             * @param command the command parsed by the parseCommand method
0748:             * @param argument the first argument parsed by the parseCommand method
0749:             * @param argument1 the second argument parsed by the parseCommand method
0750:             */
0751:            private void doRSET(String command, String argument,
0752:                    String argument1) {
0753:                String responseString = null;
0754:                if (state == TRANSACTION) {
0755:                    stat();
0756:                    responseString = OK_RESPONSE;
0757:                } else {
0758:                    responseString = ERR_RESPONSE;
0759:                }
0760:                writeLoggedFlushedResponse(responseString);
0761:            }
0762:
0763:            /**
0764:             * Handler method called upon receipt of a DELE command.
0765:             * This command deletes a particular mail message from the
0766:             * mailbox.
0767:             *
0768:             * @param command the command parsed by the parseCommand method
0769:             * @param argument the first argument parsed by the parseCommand method
0770:             * @param argument1 the second argument parsed by the parseCommand method
0771:             */
0772:            private void doDELE(String command, String argument,
0773:                    String argument1) {
0774:                String responseString = null;
0775:                if (state == TRANSACTION) {
0776:                    int num = 0;
0777:                    try {
0778:                        num = Integer.parseInt(argument);
0779:                    } catch (Exception e) {
0780:                        responseString = ERR_RESPONSE
0781:                                + " Usage: DELE [mail number]";
0782:                        writeLoggedFlushedResponse(responseString);
0783:                        return;
0784:                    }
0785:                    try {
0786:                        Mail mc = (Mail) userMailbox.get(num);
0787:                        if (mc == DELETED) {
0788:                            StringBuffer responseBuffer = new StringBuffer(64)
0789:                                    .append(ERR_RESPONSE).append(" Message (")
0790:                                    .append(num).append(") already deleted.");
0791:                            responseString = responseBuffer.toString();
0792:                            writeLoggedFlushedResponse(responseString);
0793:                        } else {
0794:                            userMailbox.set(num, DELETED);
0795:                            writeLoggedFlushedResponse(OK_RESPONSE
0796:                                    + " Message deleted");
0797:                        }
0798:                    } catch (IndexOutOfBoundsException iob) {
0799:                        StringBuffer responseBuffer = new StringBuffer(64)
0800:                                .append(ERR_RESPONSE).append(" Message (")
0801:                                .append(num).append(") does not exist.");
0802:                        responseString = responseBuffer.toString();
0803:                        writeLoggedFlushedResponse(responseString);
0804:                    }
0805:                } else {
0806:                    responseString = ERR_RESPONSE;
0807:                    writeLoggedFlushedResponse(responseString);
0808:                }
0809:            }
0810:
0811:            /**
0812:             * Handler method called upon receipt of a NOOP command.
0813:             * Like all good NOOPs, does nothing much.
0814:             *
0815:             * @param command the command parsed by the parseCommand method
0816:             * @param argument the first argument parsed by the parseCommand method
0817:             * @param argument1 the second argument parsed by the parseCommand method
0818:             */
0819:            private void doNOOP(String command, String argument,
0820:                    String argument1) {
0821:                String responseString = null;
0822:                if (state == TRANSACTION) {
0823:                    responseString = OK_RESPONSE;
0824:                    writeLoggedFlushedResponse(responseString);
0825:                } else {
0826:                    responseString = ERR_RESPONSE;
0827:                    writeLoggedFlushedResponse(responseString);
0828:                }
0829:            }
0830:
0831:            /**
0832:             * Handler method called upon receipt of a RETR command.
0833:             * This command retrieves a particular mail message from the
0834:             * mailbox.
0835:             *
0836:             * @param command the command parsed by the parseCommand method
0837:             * @param argument the first argument parsed by the parseCommand method
0838:             * @param argument1 the second argument parsed by the parseCommand method
0839:             */
0840:            private void doRETR(String command, String argument,
0841:                    String argument1) {
0842:                String responseString = null;
0843:                if (state == TRANSACTION) {
0844:                    int num = 0;
0845:                    try {
0846:                        num = Integer.parseInt(argument.trim());
0847:                    } catch (Exception e) {
0848:                        responseString = ERR_RESPONSE
0849:                                + " Usage: RETR [mail number]";
0850:                        writeLoggedFlushedResponse(responseString);
0851:                        return;
0852:                    }
0853:                    try {
0854:                        Mail mc = (Mail) userMailbox.get(num);
0855:                        if (mc != DELETED) {
0856:                            responseString = OK_RESPONSE + " Message follows";
0857:                            writeLoggedFlushedResponse(responseString);
0858:                            try {
0859:                                ExtraDotOutputStream edouts = new ExtraDotOutputStream(
0860:                                        outs);
0861:                                OutputStream nouts = new BytesWrittenResetOutputStream(
0862:                                        edouts, theWatchdog, theConfigData
0863:                                                .getResetLength());
0864:                                mc.getMessage().writeTo(nouts);
0865:                                nouts.flush();
0866:                                edouts.checkCRLFTerminator();
0867:                                edouts.flush();
0868:                            } finally {
0869:                                out.println(".");
0870:                                out.flush();
0871:                            }
0872:                        } else {
0873:                            StringBuffer responseBuffer = new StringBuffer(64)
0874:                                    .append(ERR_RESPONSE).append(" Message (")
0875:                                    .append(num).append(") already deleted.");
0876:                            responseString = responseBuffer.toString();
0877:                            writeLoggedFlushedResponse(responseString);
0878:                        }
0879:                    } catch (IOException ioe) {
0880:                        responseString = ERR_RESPONSE
0881:                                + " Error while retrieving message.";
0882:                        writeLoggedFlushedResponse(responseString);
0883:                    } catch (MessagingException me) {
0884:                        responseString = ERR_RESPONSE
0885:                                + " Error while retrieving message.";
0886:                        writeLoggedFlushedResponse(responseString);
0887:                    } catch (IndexOutOfBoundsException iob) {
0888:                        StringBuffer responseBuffer = new StringBuffer(64)
0889:                                .append(ERR_RESPONSE).append(" Message (")
0890:                                .append(num).append(") does not exist.");
0891:                        responseString = responseBuffer.toString();
0892:                        writeLoggedFlushedResponse(responseString);
0893:                    }
0894:                } else {
0895:                    responseString = ERR_RESPONSE;
0896:                    writeLoggedFlushedResponse(responseString);
0897:                }
0898:            }
0899:
0900:            /**
0901:             * Handler method called upon receipt of a TOP command.
0902:             * This command retrieves the top N lines of a specified
0903:             * message in the mailbox.
0904:             *
0905:             * The expected command format is
0906:             *  TOP [mail message number] [number of lines to return]
0907:             *
0908:             * @param command the command parsed by the parseCommand method
0909:             * @param argument the first argument parsed by the parseCommand method
0910:             * @param argument1 the second argument parsed by the parseCommand method
0911:             */
0912:            private void doTOP(String command, String argument, String argument1) {
0913:                String responseString = null;
0914:                if (state == TRANSACTION) {
0915:                    int num = 0;
0916:                    int lines = 0;
0917:                    try {
0918:                        num = Integer.parseInt(argument);
0919:                        lines = Integer.parseInt(argument1);
0920:                    } catch (NumberFormatException nfe) {
0921:                        responseString = ERR_RESPONSE
0922:                                + " Usage: TOP [mail number] [Line number]";
0923:                        writeLoggedFlushedResponse(responseString);
0924:                        return;
0925:                    }
0926:                    try {
0927:                        Mail mc = (Mail) userMailbox.get(num);
0928:                        if (mc != DELETED) {
0929:                            responseString = OK_RESPONSE + " Message follows";
0930:                            writeLoggedFlushedResponse(responseString);
0931:                            try {
0932:                                for (Enumeration e = mc.getMessage()
0933:                                        .getAllHeaderLines(); e
0934:                                        .hasMoreElements();) {
0935:                                    out.println(e.nextElement());
0936:                                }
0937:                                out.println();
0938:                                ExtraDotOutputStream edouts = new ExtraDotOutputStream(
0939:                                        outs);
0940:                                OutputStream nouts = new BytesWrittenResetOutputStream(
0941:                                        edouts, theWatchdog, theConfigData
0942:                                                .getResetLength());
0943:                                writeMessageContentTo(mc.getMessage(), nouts,
0944:                                        lines);
0945:                                nouts.flush();
0946:                                edouts.checkCRLFTerminator();
0947:                                edouts.flush();
0948:                            } finally {
0949:                                out.println(".");
0950:                                out.flush();
0951:                            }
0952:                        } else {
0953:                            StringBuffer responseBuffer = new StringBuffer(64)
0954:                                    .append(ERR_RESPONSE).append(" Message (")
0955:                                    .append(num).append(") already deleted.");
0956:                            responseString = responseBuffer.toString();
0957:                            writeLoggedFlushedResponse(responseString);
0958:                        }
0959:                    } catch (IOException ioe) {
0960:                        responseString = ERR_RESPONSE
0961:                                + " Error while retrieving message.";
0962:                        writeLoggedFlushedResponse(responseString);
0963:                    } catch (MessagingException me) {
0964:                        responseString = ERR_RESPONSE
0965:                                + " Error while retrieving message.";
0966:                        writeLoggedFlushedResponse(responseString);
0967:                    } catch (IndexOutOfBoundsException iob) {
0968:                        StringBuffer exceptionBuffer = new StringBuffer(64)
0969:                                .append(ERR_RESPONSE).append(" Message (")
0970:                                .append(num).append(") does not exist.");
0971:                        responseString = exceptionBuffer.toString();
0972:                        writeLoggedFlushedResponse(responseString);
0973:                    }
0974:                } else {
0975:                    responseString = ERR_RESPONSE;
0976:                    writeLoggedFlushedResponse(responseString);
0977:                }
0978:            }
0979:
0980:            /**
0981:             * Writes the content of the message, up to a total number of lines, out to 
0982:             * an OutputStream.
0983:             *
0984:             * @param out the OutputStream to which to write the content
0985:             * @param lines the number of lines to write to the stream
0986:             *
0987:             * @throws MessagingException if the MimeMessage is not set for this MailImpl
0988:             * @throws IOException if an error occurs while reading or writing from the stream
0989:             */
0990:            public void writeMessageContentTo(MimeMessage message,
0991:                    OutputStream out, int lines) throws IOException,
0992:                    MessagingException {
0993:                String line;
0994:                BufferedReader br;
0995:                if (message != null) {
0996:                    br = new BufferedReader(new InputStreamReader(message
0997:                            .getRawInputStream()));
0998:                    try {
0999:                        while (lines-- > 0) {
1000:                            if ((line = br.readLine()) == null) {
1001:                                break;
1002:                            }
1003:                            line += "\r\n";
1004:                            out.write(line.getBytes());
1005:                        }
1006:                    } finally {
1007:                        br.close();
1008:                    }
1009:                } else {
1010:                    throw new MessagingException(
1011:                            "No message set for this MailImpl.");
1012:                }
1013:            }
1014:
1015:            /**
1016:             * Handler method called upon receipt of a QUIT command.
1017:             * This method handles cleanup of the POP3Handler state.
1018:             *
1019:             * @param command the command parsed by the parseCommand method
1020:             * @param argument the first argument parsed by the parseCommand method
1021:             * @param argument1 the second argument parsed by the parseCommand method
1022:             */
1023:            private void doQUIT(String command, String argument,
1024:                    String argument1) {
1025:                String responseString = null;
1026:                if (state == AUTHENTICATION_READY
1027:                        || state == AUTHENTICATION_USERSET) {
1028:                    responseString = OK_RESPONSE
1029:                            + " Apache James POP3 Server signing off.";
1030:                    writeLoggedFlushedResponse(responseString);
1031:                    return;
1032:                }
1033:                List toBeRemoved = ListUtils.subtract(backupUserMailbox,
1034:                        userMailbox);
1035:                try {
1036:                    userInbox.remove(toBeRemoved);
1037:                    // for (Iterator it = toBeRemoved.iterator(); it.hasNext(); ) {
1038:                    //    Mail mc = (Mail) it.next();
1039:                    //    userInbox.remove(mc.getName());
1040:                    //}
1041:                    responseString = OK_RESPONSE
1042:                            + " Apache James POP3 Server signing off.";
1043:                    writeLoggedFlushedResponse(responseString);
1044:                } catch (Exception ex) {
1045:                    responseString = ERR_RESPONSE
1046:                            + " Some deleted messages were not removed";
1047:                    writeLoggedFlushedResponse(responseString);
1048:                    getLogger().error(
1049:                            "Some deleted messages were not removed: "
1050:                                    + ex.getMessage());
1051:                }
1052:            }
1053:
1054:            /**
1055:             * Handler method called upon receipt of an unrecognized command.
1056:             * Returns an error response and logs the command.
1057:             *
1058:             * @param command the command parsed by the parseCommand method
1059:             * @param argument the first argument parsed by the parseCommand method
1060:             * @param argument1 the second argument parsed by the parseCommand method
1061:             */
1062:            private void doUnknownCmd(String command, String argument,
1063:                    String argument1) {
1064:                writeLoggedFlushedResponse(ERR_RESPONSE);
1065:            }
1066:
1067:            /**
1068:             * This method logs at a "DEBUG" level the response string that
1069:             * was sent to the POP3 client.  The method is provided largely
1070:             * as syntactic sugar to neaten up the code base.  It is declared
1071:             * private and final to encourage compiler inlining.
1072:             *
1073:             * @param responseString the response string sent to the client
1074:             */
1075:            private final void logResponseString(String responseString) {
1076:                if (getLogger().isDebugEnabled()) {
1077:                    getLogger().debug("Sent: " + responseString);
1078:                }
1079:            }
1080:
1081:            /**
1082:             * Write and flush a response string.  The response is also logged.
1083:             * Should be used for the last line of a multi-line response or
1084:             * for a single line response.
1085:             *
1086:             * @param responseString the response string sent to the client
1087:             */
1088:            final void writeLoggedFlushedResponse(String responseString) {
1089:                out.println(responseString);
1090:                out.flush();
1091:                logResponseString(responseString);
1092:            }
1093:
1094:            /**
1095:             * Write a response string.  The response is also logged.
1096:             * Used for multi-line responses.
1097:             *
1098:             * @param responseString the response string sent to the client
1099:             */
1100:            final void writeLoggedResponse(String responseString) {
1101:                out.println(responseString);
1102:                logResponseString(responseString);
1103:            }
1104:
1105:            /**
1106:             * A private inner class which serves as an adaptor
1107:             * between the WatchdogTarget interface and this
1108:             * handler class.
1109:             */
1110:            private class POP3WatchdogTarget implements  WatchdogTarget {
1111:
1112:                /**
1113:                 * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
1114:                 */
1115:                public void execute() {
1116:                    POP3Handler.this.idleClose();
1117:                }
1118:
1119:            }
1120:
1121:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.