geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickmcgu...@apache.org
Subject svn commit: r597135 [2/2] - in /geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main: java/org/apache/geronimo/javamail/store/imap/ java/org/apache/geronimo/javamail/store/imap/connection/ java/org/apache/geronimo/javam...
Date Wed, 21 Nov 2007 16:26:59 GMT
Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,655 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.pop3.connection;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.InternetHeaders;
+
+import org.apache.geronimo.javamail.authentication.AuthenticatorFactory; 
+import org.apache.geronimo.javamail.authentication.ClientAuthenticator;
+import org.apache.geronimo.javamail.store.pop3.POP3Constants;         
+import org.apache.geronimo.javamail.util.CommandFailedException;      
+import org.apache.geronimo.javamail.util.InvalidCommandException;      
+import org.apache.geronimo.javamail.util.MIMEInputReader;
+import org.apache.geronimo.javamail.util.MailConnection; 
+import org.apache.geronimo.javamail.util.ProtocolProperties; 
+import org.apache.geronimo.mail.util.Base64;
+import org.apache.geronimo.mail.util.Hex;
+
+/**
+ * Simple implementation of POP3 transport.  
+ *
+ * @version $Rev$ $Date$
+ */
+public class POP3Connection extends MailConnection implements POP3Constants {
+    
+    static final protected String MAIL_APOP_ENABLED = "apop.enable"; 
+    static final protected String MAIL_AUTH_ENABLED = "auth.enable"; 
+    static final protected String MAIL_RESET_QUIT = "rsetbeforequit"; 
+    static final protected String MAIL_DISABLE_TOP = "disabletop";
+    static final protected String MAIL_FORGET_TOP = "forgettopheaders"; 
+    
+    // the initial greeting string, which might be required for APOP authentication. 
+    protected String greeting; 
+    // is use of the AUTH command enabled 
+    protected boolean authEnabled; 
+    // is use of APOP command enabled 
+    protected boolean apopEnabled; 
+    // input reader wrapped around the socket input stream 
+    protected BufferedReader reader; 
+    // output writer wrapped around the socket output stream. 
+    protected PrintWriter writer; 
+    // this connection was closed unexpectedly
+    protected boolean closed;
+    // indicates whether this conneciton is currently logged in.  Once 
+    // we send a QUIT, we're finished. 
+    protected boolean loggedIn; 
+    // indicates whether we need to avoid using the TOP command 
+    // when retrieving headers
+    protected boolean topDisabled = false; 
+
+    /**
+     * Normal constructor for an POP3Connection() object.
+     *
+     * @param store    The store we're associated with (source of parameter values).
+     * @param host     The target host name of the IMAP server.
+     * @param port     The target listening port of the server.  Defaults to 119 if
+     *                 the port is specified as -1.
+     * @param username The login user name (can be null unless authentication is
+     *                 required).
+     * @param password Password associated with the userid account.  Can be null if
+     *                 authentication is not required.
+     * @param sslConnection
+     *                 True if this is targetted as an SSLConnection.
+     * @param debug    The session debug flag.
+     */
+    public POP3Connection(ProtocolProperties props) {
+        super(props);
+        
+        // get our login properties flags 
+        authEnabled = props.getBooleanProperty(MAIL_AUTH_ENABLED, false); 
+        apopEnabled = props.getBooleanProperty(MAIL_APOP_ENABLED, false); 
+        topDisabled = props.getBooleanProperty(MAIL_DISABLE_TOP, false); 
+    }
+
+                          
+    /**
+     * Connect to the server and do the initial handshaking.
+     *
+     * @exception MessagingException
+     */
+    public boolean protocolConnect(String host, int port, String authid, String realm, String username, String password) throws MessagingException {
+        this.serverHost = host; 
+        this.serverPort = port; 
+        this.realm = realm; 
+        this.authid = authid; 
+        this.username = username; 
+        this.password = password; 
+        
+        try {
+            // create socket and connect to server.
+            getConnection();
+            // consume the welcome line 
+            getWelcome(); 
+
+            // go login with the server 
+            if (login())  
+            {
+                loggedIn = true; 
+                return true;
+            }
+            return false; 
+        } catch (IOException e) {
+            if (debug) {
+                debugOut("I/O exception establishing connection", e);
+            }
+            throw new MessagingException("Connection error", e);
+        }
+    }
+
+
+    /**
+     * Create a transport connection object and connect it to the
+     * target server.
+     *
+     * @exception MessagingException
+     */
+    protected void getConnection() throws MessagingException
+    {
+        try {
+            // do all of the non-protocol specific set up.  This will get our socket established 
+            // and ready use. 
+            super.getConnection(); 
+        } catch (IOException e) {
+            throw new MessagingException("Unable to obtain a connection to the POP3 server", e); 
+        }
+        
+        // The POp3 protocol is inherently a string-based protocol, so we get 
+        // string readers/writers for the connection streams 
+        reader = new BufferedReader(new InputStreamReader(inputStream));
+        writer = new PrintWriter(new BufferedOutputStream(outputStream));
+    }
+    
+    protected void getWelcome() throws IOException {
+        // just read the line and consume it.  If debug is 
+        // enabled, there I/O stream will be traced
+        greeting = reader.readLine(); 
+    }
+
+    public String toString() {
+        return "POP3Connection host: " + serverHost + " port: " + serverPort;
+    }
+
+
+    /**
+     * Close the connection.  On completion, we'll be disconnected from
+     * the server and unable to send more data.
+     *
+     * @exception MessagingException
+     */
+    public void close() throws MessagingException {
+        // if we're already closed, get outta here.
+        if (socket == null) {
+            return;
+        }
+        try {
+            // say goodbye
+            logout();   
+        } finally {
+            // and close up the connection.  We do this in a finally block to make sure the connection
+            // is shut down even if quit gets an error.
+            closeServerConnection();
+            // get rid of our response processor too. 
+            reader = null; 
+            writer = null; 
+        }
+    }
+
+    
+    /**
+     * Tag this connection as having been closed by the 
+     * server.  This will not be returned to the 
+     * connection pool. 
+     */
+    public void setClosed() {
+        closed = true;
+    }
+    
+    /**
+     * Test if the connnection has been forcibly closed.
+     * 
+     * @return True if the server disconnected the connection.
+     */
+    public boolean isClosed() {
+        return closed; 
+    }
+    
+    protected POP3Response sendCommand(String cmd) throws MessagingException {
+        return sendCommand(cmd, false); 
+    }
+    
+    protected POP3Response sendMultiLineCommand(String cmd) throws MessagingException {
+        return sendCommand(cmd, true); 
+    }
+
+    protected synchronized POP3Response sendCommand(String cmd, boolean multiLine) throws MessagingException {
+        if (socket.isConnected()) {
+            {
+                // NOTE:  We don't use println() because it uses the platform concept of a newline rather 
+                // than using CRLF, which is required by the POP3 protocol.  
+                writer.write(cmd);
+                writer.write("\r\n"); 
+                writer.flush();
+                
+                POP3Response response = buildResponse(multiLine); 
+                if (response.isError()) {
+                    throw new CommandFailedException("Error issuing POP3 command: " + cmd); 
+                }
+                return response; 
+            }
+        }
+        throw new MessagingException("Connection to Mail Server is lost, connection " + this.toString());
+    }
+    
+    /**
+     * Build a POP3Response item from the response stream.
+     * 
+     * @param isMultiLineResponse
+     *               If true, this command is expecting multiple lines back from the server.
+     * 
+     * @return A POP3Response item with all of the command response data. 
+     * @exception MessagingException
+     */
+    protected POP3Response buildResponse(boolean isMultiLineResponse) throws MessagingException {
+        int status = ERR;
+        byte[] data = null;
+
+        String line;
+        MIMEInputReader source = new MIMEInputReader(reader); 
+        
+        try {
+            line = reader.readLine();
+        } catch (IOException e) {
+            throw new MessagingException("Error in receving response");
+        }
+        
+        if (line == null || line.trim().equals("")) {
+            throw new MessagingException("Empty Response");
+        }
+        
+        if (line.startsWith("+OK")) {
+            status = OK;
+            line = removeStatusField(line);
+            if (isMultiLineResponse) {
+                data = getMultiLineResponse();
+            }
+        } else if (line.startsWith("-ERR")) {
+            status = ERR;
+            line = removeStatusField(line);
+        }else if (line.startsWith("+")) {
+        	status = CHALLENGE;
+        	line = removeStatusField(line);
+        	if (isMultiLineResponse) {
+        		data = getMultiLineResponse();
+        	}
+        } else {
+            throw new MessagingException("Unexpected response: " + line);
+        }
+        return new POP3Response(status, line, data);
+    }
+
+    private static String removeStatusField(String line) {
+        return line.substring(line.indexOf(SPACE) + 1);
+    }
+
+    /**
+     * This could be a multiline response
+     */
+    private byte[] getMultiLineResponse() throws MessagingException {
+
+        MIMEInputReader source = new MIMEInputReader(reader); 
+        
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        
+        // it's more efficient to do this a buffer at a time. 
+        // the MIMEInputReader takes care of the byte-stuffing and 
+        // ".\r\n" input terminator for us. 
+        OutputStreamWriter outWriter = new OutputStreamWriter(out); 
+        char buffer[] = new char[500]; 
+        try {
+            int charsRead = -1;
+            while ((charsRead = source.read(buffer)) >= 0) {
+                outWriter.write(buffer, 0, charsRead);
+            }
+            outWriter.flush(); 
+        } catch (IOException e) {
+            throw new MessagingException("Error processing a multi-line response", e);
+        }
+        
+        return out.toByteArray();
+    }
+    
+    
+    /**
+     * Retrieve the raw message content from the POP3 
+     * server.  This is all of the message data, including 
+     * the header. 
+     * 
+     * @param sequenceNumber
+     *               The message sequence number.
+     * 
+     * @return A byte array containing all of the message data. 
+     * @exception MessagingException
+     */
+    public byte[] retrieveMessageData(int sequenceNumber) throws MessagingException {
+        POP3Response msgResponse = sendMultiLineCommand("RETR " + sequenceNumber); 
+        // we want the data directly in this case. 
+        return msgResponse.getData();          
+    }
+    
+    /**
+     * Retrieve the message header information for a given 
+     * message, returned as an input stream suitable 
+     * for loading the message data.
+     * 
+     * @param sequenceNumber
+     *               The server sequence number for the message.
+     * 
+     * @return An inputstream that can be used to read the message 
+     *         data.
+     * @exception MessagingException
+     */
+    public ByteArrayInputStream retrieveMessageHeaders(int sequenceNumber) throws MessagingException {
+        POP3Response msgResponse; 
+        
+        // some POP3 servers don't correctly implement TOP, so this can be disabled.  If 
+        // we can't use TOP, then use RETR and retrieve everything.  We can just hand back 
+        // the stream, as the header loading routine will stop at the first 
+        // null line. 
+        if (topDisabled) {
+            msgResponse = sendMultiLineCommand("RETR " + sequenceNumber); 
+        }
+        else {
+            msgResponse = sendMultiLineCommand("TOP " + sequenceNumber + " 0"); 
+        }
+        
+        // just load the returned message data as a set of headers 
+        return msgResponse.getContentStream();
+    }
+    
+    /**
+     * Retrieve the total message size from the mail 
+     * server.  This is the size of the headers plus 
+     * the size of the message content. 
+     * 
+     * @param sequenceNumber
+     *               The message sequence number.
+     * 
+     * @return The full size of the message.
+     * @exception MessagingException
+     */
+    public int retrieveMessageSize(int sequenceNumber) throws MessagingException {
+        POP3Response msgResponse = sendCommand("LIST " + sequenceNumber); 
+        // Convert this into the parsed response type we need. 
+        POP3ListResponse list = new POP3ListResponse(msgResponse); 
+        // this returns the total message size 
+        return list.getSize(); 
+    }
+    
+    /**
+     * Retrieve the mail drop status information.
+     * 
+     * @return An object representing the returned mail drop status. 
+     * @exception MessagingException
+     */
+    public POP3StatusResponse retrieveMailboxStatus() throws MessagingException {
+        // issue the STAT command and return this into a status response 
+        return new POP3StatusResponse(sendCommand("STAT")); 
+    }
+    
+    
+    /**
+     * Retrieve the UID for an individual message.
+     * 
+     * @param sequenceNumber
+     *               The target message sequence number.
+     * 
+     * @return The string UID maintained by the server. 
+     * @exception MessagingException
+     */
+    public String retrieveMessageUid(int sequenceNumber) throws MessagingException {
+        POP3Response msgResponse = sendCommand("UIDL " + sequenceNumber); 
+        
+        String message = msgResponse.getFirstLine(); 
+        // the UID is everything after the blank separating the message number and the UID. 
+        // there's not supposed to be anything else on the message, but trim it of whitespace 
+        // just to be on the safe side. 
+        return message.substring(message.indexOf(' ') + 1).trim(); 
+    }
+    
+    
+    /**
+     * Delete a single message from the mail server.
+     * 
+     * @param sequenceNumber
+     *               The sequence number of the message to delete.
+     * 
+     * @exception MessagingException
+     */
+    public void deleteMessage(int sequenceNumber) throws MessagingException {
+        // just issue the command...we ignore the command response 
+        sendCommand("DELE " + sequenceNumber); 
+    }
+    
+    /**
+     * Logout from the mail server.  This sends a QUIT 
+     * command, which will likely sever the mail connection.
+     * 
+     * @exception MessagingException
+     */
+    public void logout() throws MessagingException {
+        // we may have already sent the QUIT command
+        if (!loggedIn) {
+            return; 
+        }
+        // just issue the command...we ignore the command response 
+        sendCommand("QUIT"); 
+        loggedIn = false; 
+    }
+    
+    /**
+     * Perform a reset on the mail server.                   
+     * 
+     * @exception MessagingException
+     */
+    public void reset() throws MessagingException {
+        // some mail servers mark retrieved messages for deletion 
+        // automatically.  This will reset the read flags before 
+        // we go through normal cleanup. 
+        if (props.getBooleanProperty(MAIL_RESET_QUIT, false)) {
+            // just send an RSET command first
+            sendCommand("RSET"); 
+        }
+    }
+    
+    /**
+     * Ping the mail server to see if we still have an active connection. 
+     * 
+     * @exception MessagingException thrown if we do not have an active connection. 
+     */
+    public void pingServer() throws MessagingException {
+        // just issue the command...we ignore the command response 
+        sendCommand("NOOP"); 
+    }
+    
+    /**
+     * Login to the mail server, using whichever method is 
+     * configured.  This will try multiple methods, if allowed, 
+     * in decreasing levels of security. 
+     * 
+     * @return true if the login was successful. 
+     * @exception MessagingException
+     */
+    public synchronized boolean login() throws MessagingException {
+        // permitted to use the AUTH command?
+        if (authEnabled) {
+            try {
+                // go do the SASL thing 
+                return processSaslAuthentication(); 
+            } catch (MessagingException e) {
+                // Any error here means fall back to the next mechanism 
+            }
+        }
+        
+        if (apopEnabled) {
+            try {
+                // go do the SASL thing 
+                return processAPOPAuthentication(); 
+            } catch (MessagingException e) {
+                // Any error here means fall back to the next mechanism 
+            }
+        }
+        
+        try {
+            // do the tried and true login processing. 
+            return processLogin(); 
+        } catch (MessagingException e) {
+        }
+        // everything failed...can't get in 
+        return false; 
+    }
+    
+    
+    /**
+     * Process a basic LOGIN operation, using the 
+     * plain test USER/PASS command combo. 
+     * 
+     * @return true if we logged successfully. 
+     * @exception MessagingException
+     */
+    public boolean processLogin() throws MessagingException {
+        // start by sending the USER command, followed by  
+        // the PASS command
+        sendCommand("USER " + username); 
+        sendCommand("PASS " + password); 
+        return true;       // we're in 
+    }
+    
+    /**
+     * Process logging in using the APOP command.  Only 
+     * works on servers that give a timestamp value 
+     * in the welcome response. 
+     * 
+     * @return true if the login was accepted. 
+     * @exception MessagingException
+     */
+    public boolean processAPOPAuthentication() throws MessagingException {
+        int timeStart = greeting.indexOf('<'); 
+        // if we didn't get an APOP challenge on the greeting, throw an exception 
+        // the main login processor will swallow that and fall back to the next 
+        // mechanism 
+        if (timeStart == -1) {
+            throw new MessagingException("POP3 Server does not support APOP"); 
+        }
+        int timeEnd = greeting.indexOf('>'); 
+        String timeStamp = greeting.substring(timeStart, timeEnd + 1); 
+        
+        // we create the digest password using the timestamp value sent to use 
+        // concatenated with the password. 
+        String digestPassword = timeStamp + password; 
+        
+        byte[] digest; 
+        
+        try {
+            // create a digest value from the password. 
+            MessageDigest md = MessageDigest.getInstance("MD5"); 
+            digest = md.digest(digestPassword.getBytes("iso-8859-1")); 
+        } catch (NoSuchAlgorithmException e) {
+            // this shouldn't happen, but if it does, we'll just try a plain 
+            // login. 
+            throw new MessagingException("Unable to create MD5 digest", e); 
+        } catch (UnsupportedEncodingException e) {
+            // this shouldn't happen, but if it does, we'll just try a plain 
+            // login. 
+            throw new MessagingException("Unable to create MD5 digest", e); 
+        }
+        // this will throw an exception if it gives an error failure
+        sendCommand("APOP " + username + " " + Hex.encode(digest)); 
+        // no exception, we must have passed 
+        return true; 
+    }
+
+    
+    /**
+     * Process SASL-type authentication.
+     * 
+     * @return Returns true if the server support a SASL authentication mechanism and
+     *         accepted reponse challenges.
+     * @exception MessagingException
+     */
+    protected boolean processSaslAuthentication() throws MessagingException {
+        // if unable to get an appropriate authenticator, just fail it. 
+        ClientAuthenticator authenticator = getSaslAuthenticator(); 
+        if (authenticator == null) {
+            throw new MessagingException("Unable to obtain SASL authenticator"); 
+        }
+        
+        // go process the login.
+        return processLogin(authenticator);
+    }
+    
+    /**
+     * Attempt to retrieve a SASL authenticator for this 
+     * protocol. 
+     * 
+     * @return A SASL authenticator, or null if a suitable one 
+     *         was not located.
+     */
+    protected ClientAuthenticator getSaslAuthenticator() {
+        return AuthenticatorFactory.getAuthenticator(props, selectSaslMechanisms(), serverHost, username, password, authid, realm); 
+    }
+
+
+    /**
+     * Process a login using the provided authenticator object.
+     * 
+     * NB:  This method is synchronized because we have a multi-step process going on 
+     * here.  No other commands should be sent to the server until we complete. 
+     *
+     * @return Returns true if the server support a SASL authentication mechanism and
+     * accepted reponse challenges.
+     * @exception MessagingException
+     */
+    protected synchronized boolean processLogin(ClientAuthenticator authenticator) throws MessagingException {
+        if (debug) {
+            debugOut("Authenticating for user: " + username + " using " + authenticator.getMechanismName());
+        }
+
+        POP3Response response = sendCommand("AUTH " + authenticator.getMechanismName()); 
+
+        // now process the challenge sequence.  We get a continuation response back for each stage of the 
+        // authentication, and finally an OK when everything passes muster.     
+        while (true) {
+            // this should be a continuation reply, if things are still good.
+            if (response.isChallenge()) {
+                // we're passed back a challenge value, Base64 encoded.
+                byte[] challenge = response.decodeChallengeResponse();
+                
+                String responseString = new String(Base64.encode(authenticator.evaluateChallenge(challenge)));
+
+                // have the authenticator evaluate and send back the encoded response.
+                response = sendCommand(responseString);
+            }
+            else {
+                // there are only two choices here, OK or a continuation.  OK means 
+                // we've passed muster and are in. 
+                return true; 
+            }
+        }
+    }
+    
+    
+    /**
+     * Merge the configured SASL mechanisms with the capabilities that the 
+     * server has indicated it supports, returning a merged list that can 
+     * be used for selecting a mechanism. 
+     * 
+     * @return A List representing the intersection of the configured list and the 
+     *         capabilities list.
+     */
+    protected List selectSaslMechanisms() {
+        // just return the set that have been explicity permitted 
+        return getSaslMechanisms(); 
+    }
+}
+

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,224 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.pop3.connection;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.mail.MessagingException; 
+import javax.mail.Session;
+import javax.mail.Store;
+
+import javax.mail.StoreClosedException;
+
+import org.apache.geronimo.javamail.store.pop3.POP3Store; 
+import org.apache.geronimo.javamail.util.ProtocolProperties; 
+
+public class POP3ConnectionPool {
+
+    protected static final String MAIL_PORT = "port";
+    
+    protected static final String MAIL_SASL_REALM = "sasl.realm"; 
+    protected static final String MAIL_AUTHORIZATIONID = "sasl.authorizationid"; 
+
+    protected static final String DEFAULT_MAIL_HOST = "localhost";
+
+    // Our hosting Store instance
+    protected POP3Store store;
+    // our Protocol abstraction 
+    protected ProtocolProperties props; 
+    // POP3 is not nearly as multi-threaded as IMAP.  We really just have a single folder, 
+    // plus the Store, but the Store doesn't really talk to the server very much.  We only
+    // hold one connection available, and on the off chance there is a situation where 
+    // we need to create a new one, we'll authenticate on demand.  The one case where 
+    // I know this might be an issue is a folder checking back with the Store to see it if
+    // it is still connected.  
+    protected POP3Connection availableConnection;      
+    
+    // our debug flag
+    protected boolean debug;
+
+    // the target host
+    protected String host;
+    // the target server port.
+    protected int port;
+    // the username we connect with
+    protected String username;
+    // the authentication password.
+    protected String password;
+    // the SASL realm name 
+    protected String realm; 
+    // the authorization id.  
+    protected String authid; 
+    // Turned on when the store is closed for business. 
+    protected boolean closed = false; 
+
+    /**
+     * Create a connection pool associated with a give POP3Store instance.  The
+     * connection pool manages handing out connections for both the Store and
+     * Folder and Message usage.
+     * 
+     * @param store  The Store we're creating the pool for.
+     * @param props  The protocol properties abstraction we use.
+     */
+    public POP3ConnectionPool(POP3Store store, ProtocolProperties props) {
+        this.store = store;
+        this.props = props; 
+    }
+
+
+    /**
+     * Manage the initial connection to the POP3 server.  This is the first 
+     * point where we obtain the information needed to make an actual server 
+     * connection.  Like the Store protocolConnect method, we return false 
+     * if there's any sort of authentication difficulties. 
+     * 
+     * @param host     The host of the mail server.
+     * @param port     The mail server connection port.
+     * @param user     The connection user name.
+     * @param password The connection password.
+     * 
+     * @return True if we were able to connect and authenticate correctly. 
+     * @exception MessagingException
+     */
+    public synchronized boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
+        // NOTE:  We don't check for the username/password being null at this point.  It's possible that 
+        // the server will send back a PREAUTH response, which means we don't need to go through login 
+        // processing.  We'll need to check the capabilities response after we make the connection to decide 
+        // if logging in is necesssary. 
+        
+        // save this for subsequent connections.  All pool connections will use this info.
+        // if the port is defaulted, then see if we have something configured in the session.
+        // if not configured, we just use the default default.
+        if (port == -1) {
+            // check for a property and fall back on the default if it's not set.
+            port = props.getIntProperty(MAIL_PORT, props.getDefaultPort());
+            // it's possible that -1 might have been explicitly set, so one last check. 
+            if (port == -1) {
+                port = props.getDefaultPort(); 
+            }
+        }
+    	
+    	// Before we do anything, let's make sure that we succesfully received a host
+    	if ( host == null ) {
+    		host = DEFAULT_MAIL_HOST;
+    	}
+        
+        this.host = host;
+        this.port = port;
+        this.username = username;
+        this.password = password;
+        
+        // make sure we have the realm information 
+        realm = props.getProperty(MAIL_SASL_REALM); 
+        // get an authzid value, if we have one.  The default is to use the username.
+        authid = props.getProperty(MAIL_AUTHORIZATIONID, username);
+
+        // go create a connection and just add it to the pool.  If there is an authenticaton error, 
+        // return the connect failure, and we may end up trying again. 
+        availableConnection = createPoolConnection(); 
+        if (availableConnection == null) {
+            return false; 
+        }
+        // we're connected, authenticated, and ready to go. 
+        return true; 
+    }
+
+    /**
+     * Creates an authenticated pool connection and adds it to
+     * the connection pool.  If there is an existing connection
+     * already in the pool, this returns without creating a new
+     * connection.
+     *
+     * @exception MessagingException
+     */
+    protected POP3Connection createPoolConnection() throws MessagingException {
+        POP3Connection connection = new POP3Connection(props);
+        if (!connection.protocolConnect(host, port, authid, realm, username, password)) {
+            // we only add live connections to the pool.  Sever the connections and 
+            // allow it to go free. 
+            connection.closeServerConnection(); 
+            return null; 
+        }
+        // just return this connection 
+        return connection; 
+    }
+
+
+    /**
+     * Get a connection from the pool.  We try to retrieve a live
+     * connection, but we test the connection's liveness before
+     * returning one.  If we don't have a viable connection in
+     * the pool, we'll create a new one.  The returned connection
+     * will be in the authenticated state already.
+     *
+     * @return A POP3Connection object that is connected to the server.
+     */
+    public synchronized POP3Connection getConnection() throws MessagingException {
+        // if we have an available one (common when opening the INBOX), just return it 
+        POP3Connection connection = availableConnection; 
+        
+        if (connection != null) {
+            availableConnection = null; 
+            return connection; 
+        }
+        // we need an additional connection...rare, but it can happen if we've closed the INBOX folder. 
+        return createPoolConnection(); 
+    }
+    
+    
+    /**
+     * Return a connection to the connection pool.
+     * 
+     * @param connection The connection getting returned.
+     * 
+     * @exception MessagingException
+     */
+    public synchronized void releaseConnection(POP3Connection connection) throws MessagingException
+    {
+        // we're generally only called if the store needed to talk to the server and 
+        // then returned the connection to the pool.  So it's pretty likely that we'll just cache this
+        if (availableConnection == null) {
+            availableConnection = connection; 
+        }
+        else {
+            // got too many connections created...not sure how, but get rid of this one. 
+            connection.close(); 
+        }
+    }
+    
+    
+    /**
+     * Close the entire connection pool. 
+     * 
+     * @exception MessagingException
+     */
+    public synchronized void close() throws MessagingException {
+        // we'll on have the single connection in reserver 
+        if (availableConnection != null) {
+            availableConnection.close(); 
+            availableConnection = null; 
+        }
+        // turn out the lights, hang the closed sign on the wall. 
+        closed = true; 
+    }
+}
+

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.store.pop3.connection;
+
+import java.io.ByteArrayInputStream; 
+
+import java.util.ArrayList; 
+import java.util.List;     
+
+import javax.mail.MessagingException;
+
+/**
+ * This class adds functionality to the basic response by parsing the reply for
+ * LIST command and obtaining specific information about the msgnum and the
+ * size. It could be for one or more msgs depending on wether a msg number was
+ * passed or not into the LIST command
+ * 
+ * @see org.apache.geronimo.javamail.store.pop3.POP3Response
+ * @see org.apache.geronimo.javamail.store.pop3.response.DefaultPOP3Response
+ * 
+ * @version $Rev$ $Date$
+ */
+
+public class POP3ListResponse extends POP3Response {
+
+    private int msgnum = 0;
+
+    private int size = 0;
+
+    private List multipleMsgs = null;
+
+    POP3ListResponse(POP3Response baseRes) throws MessagingException {
+        super(baseRes.getStatus(), baseRes.getFirstLine(), baseRes.getData());
+
+        // if ERR not worth proceeding any further
+        if (OK == getStatus()) {
+
+            // if data == null, then it mean it's a single line response
+            if (baseRes.getData() == null) {
+                String[] args = getFirstLine().split(SPACE);
+                try {
+                    msgnum = Integer.parseInt(args[0]);
+                } catch (NumberFormatException e) {
+                    throw new MessagingException("Invalid response for LIST command", e);
+                }
+                try {
+                    size = Integer.parseInt(args[1]);
+                } catch (NumberFormatException e) {
+                    throw new MessagingException("Invalid response for LIST command", e);
+                }
+            } else {
+                int totalMsgs = 0;
+                String[] args = getFirstLine().split(SPACE);
+                try {
+                    totalMsgs = Integer.parseInt(args[0]);
+                } catch (NumberFormatException e) {
+                    throw new MessagingException("Invalid response for LIST command", e);
+                }
+                multipleMsgs = new ArrayList(totalMsgs);
+                // Todo : multi-line response parsing
+            }
+
+        }
+    }
+
+    public int getMessageNumber() {
+        return msgnum;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    /**
+     * Messages can be accessed by multipleMsgs.getElementAt(msgnum)
+     * 
+     */
+    public List getMultipleMessageDetails() {
+        return multipleMsgs;
+    }
+
+}

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.store.pop3.connection;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.geronimo.javamail.store.pop3.POP3Constants;
+
+import org.apache.geronimo.mail.util.Base64;
+
+/**
+ * This class provides the basic implementation for the POP3Response.
+ * 
+ * @see org.apache.geronimo.javamail.store.pop3.POP3Response
+ * @version $Rev$ $Date$
+ */
+
+public class POP3Response implements POP3Constants {
+
+    private int status = ERR;
+
+    private String firstLine;
+
+    private byte[] data;
+
+    POP3Response(int status, String firstLine, byte []data) {
+        this.status = status;
+        this.firstLine = firstLine;
+        this.data = data;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+    
+    public byte[] getData() {
+        return data; 
+    }
+
+    public ByteArrayInputStream getContentStream() {
+        return new ByteArrayInputStream(data);
+    }
+
+    public String getFirstLine() {
+        return firstLine;
+    }
+    
+    public boolean isError() {
+        return status == ERR; 
+    }
+    
+    public boolean isChallenge() {
+        return status == CHALLENGE; 
+    }
+    
+    /**
+     * Decode the message portion of a continuation challenge response.
+     * 
+     * @return The byte array containing the decoded data. 
+     */
+    public byte[] decodeChallengeResponse() 
+    {
+        // the challenge response is a base64 encoded string...
+        return Base64.decode(firstLine.trim()); 
+    }
+
+}
+

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.store.pop3.connection;
+
+import javax.mail.MessagingException;
+
+/**
+ * This class adds functionality to the basic response by parsing the status
+ * line and obtaining specific information about num of msgs and the size
+ * 
+ * @see org.apache.geronimo.javamail.store.pop3.POP3Response
+ * @see org.apache.geronimo.javamail.store.pop3.response.DefaultPOP3Response
+ * 
+ * @version $Rev$ $Date$
+ */
+
+public class POP3StatusResponse extends POP3Response {
+
+    private int numMessages = 0;
+
+    private int size = 0;
+
+    POP3StatusResponse(POP3Response baseRes) throws MessagingException {
+        super(baseRes.getStatus(), baseRes.getFirstLine(), baseRes.getData());
+
+        // if ERR not worth proceeding any further
+        if (OK == getStatus()) {
+            String[] args = getFirstLine().split(SPACE);
+            try {
+                numMessages = Integer.parseInt(args[0]);
+            } catch (NumberFormatException e) {
+                throw new MessagingException("Invalid response for STAT command", e);
+            }
+            try {
+                size = Integer.parseInt(args[1]);
+            } catch (NumberFormatException e) {
+                throw new MessagingException("Invalid response for STAT command", e);
+            }
+        }
+    }
+
+    public int getNumMessages() {
+        return numMessages;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+}

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java?rev=597135&view=auto
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java (added)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java Wed Nov 21 08:26:57 2007
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.javamail.util;
+
+import java.io.IOException;
+import java.io.Reader; 
+
+/**
+ * An implementation of an OutputStream that performs MIME linebreak
+ * canonicalization and "byte-stuff" so that data content does not get mistaken
+ * for a message data-end marker (CRLF.CRLF)l
+ * 
+ * @version $Rev$ $Date$
+ */
+public class MIMEInputReader extends Reader {
+
+    // the wrappered output stream.
+    protected Reader source;
+
+    // a flag to indicate we've just processed a line break. This is used for
+    // byte stuffing purposes. This
+    // is initially true, because if the first character of the content is a
+    // period, we need to byte-stuff
+    // immediately.
+    protected boolean atLineBreak = true;
+    // we've hit the terminating marker on the data
+    protected boolean endOfData = false; 
+    
+
+    /**
+     * Create an input reader that reads from the source input reader  
+     * 
+     * @param out
+     *            The wrapped Reader        
+     */
+    public MIMEInputReader(Reader source) {
+        this.source = source; 
+    }
+    
+    /**
+     * Concrete implementation of the Reader read() 
+     * abstract method.  This appears to be the only 
+     * abstract method, so all of the other reads must 
+     * funnel through this method. 
+     * 
+     * @param buffer The buffer to fill.
+     * @param off    The offset to start adding characters.
+     * @param len    The number of requested characters.
+     * 
+     * @return The actual count of characters read.  Returns -1 
+     *         if we hit an EOF without reading any characters.
+     * @exception IOException
+     */
+    public int read(char buffer[], int off, int len) throws IOException {
+        // we've been asked for nothing, we'll return nothing. 
+        if (len == 0) {
+            return 0; 
+        }
+        
+        // have we hit the end of data?  Return a -1 indicator
+        if (endOfData) {
+            return -1; 
+        }
+        
+        // number of bytes read 
+        int bytesRead = 0; 
+        
+        int lastRead; 
+        
+        while (bytesRead < len && (lastRead = source.read()) >= 0) {
+            // We are checking for the end of a multiline response
+            // the format is .CRLF
+            
+            // we also have to check for byte-stuffing situation 
+            // where we remove a leading period.  
+            if (atLineBreak && lastRead == '.') {
+                // step to the next character 
+                lastRead = source.read();
+                // we have ".CR"...this is our end of stream 
+                // marker.  Consume the LF from the reader and return 
+                if (lastRead == '\r') {
+                    source.read(); 
+                    // no more reads from this point. 
+                    endOfData = true; 
+                    break; 
+                }
+                // the next character SHOULD be a ".".  We swallow the first 
+                // dot and just write the next character to the buffer 
+                atLineBreak = false; 
+            }
+            else if (lastRead == '\n') {
+                // hit an end-of-line marker?
+                // remember we just had a line break 
+                atLineBreak = true; 
+            }
+            else 
+            {
+                // something other than a line break character 
+                atLineBreak = false; 
+            }
+            // add the character to the buffer 
+            buffer[off++] = (char)lastRead; 
+            bytesRead++; 
+        }
+        
+        // we must have had an EOF condition of some sort 
+        if (bytesRead == 0) {
+            return -1; 
+        }
+        // return the actual length read in 
+        return bytesRead; 
+    }
+    
+     /**
+      * Close the stream.  This is a NOP for this stream.  
+      * 
+      * @exception IOException
+      */
+     public void close() throws IOException {
+         // does nothing 
+     }
+}
+

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers?rev=597135&r1=597134&r2=597135&view=diff
==============================================================================
--- geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers (original)
+++ geronimo/javamail/trunk/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers Wed Nov 21 08:26:57 2007
@@ -35,6 +35,7 @@
 protocol=nntp-post; type=transport; class=org.apache.geronimo.javamail.transport.nntp.NNTPTransport; vendor=Apache Software Foundation; version=1.0
 protocol=nntp; type=store; class=org.apache.geronimo.javamail.store.nntp.NNTPStore; vendor=Apache Software Foundation; version=1.0
 protocol=pop3; type=store; class=org.apache.geronimo.javamail.store.pop3.POP3Store; vendor=Apache Software Foundation; version=1.0
+protocol=pop3s; type=store; class=org.apache.geronimo.javamail.store.pop3.POP3SSLStore; vendor=Apache Software Foundation; version=1.0
 protocol=imap; type=store; class=org.apache.geronimo.javamail.store.imap.IMAPStore; vendor=Apache Software Foundation; version=1.0
 protocol=imaps; type=store; class=org.apache.geronimo.javamail.store.imap.IMAPSSLStore; vendor=Apache Software Foundation; version=1.0
 



Mime
View raw message