GERONIMO-3623 javamail POP3 implementation has numerous incompatibilities with Sun impl.



git-svn-id: https://svn.apache.org/repos/asf/geronimo/javamail/trunk@597135 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPSSLStore.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPSSLStore.java
index fa33a43..c844e9b 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPSSLStore.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/IMAPSSLStore.java
@@ -22,9 +22,7 @@
 import javax.mail.URLName;
 
 /**
- * IMAP implementation of javax.mail.Store
- * POP protocol spec is implemented in
- * org.apache.geronimo.javamail.store.pop3.IMAPConnection
+ * IMAP implementation of javax.mail.Store for SSL connections. 
  *
  * @version $Rev$ $Date$
  */
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnection.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnection.java
index 5a0f179..ecbac91 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnection.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnection.java
@@ -101,18 +101,10 @@
 
     /**
      * Normal constructor for an IMAPConnection() 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.
+     * 
+     * @param props  The protocol properties abstraction containing our
+     *               property modifiers.
+     * @param pool
      */
     public IMAPConnection(ProtocolProperties props, IMAPConnectionPool pool) {
         super(props);
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnectionPool.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnectionPool.java
index 05002ec..f89619c 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnectionPool.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/imap/connection/IMAPConnectionPool.java
@@ -90,26 +90,19 @@
     protected Map capabilities; 
 
     /**
-     * Create a connection pool associated with a give IMAPStore instance.  The 
-     * connection pool manages handing out connections for both the Store and 
-     * Folder and Message usage.  
+     * Create a connection pool associated with a give IMAPStore instance.  The
+     * connection pool manages handing out connections for both the Store and
+     * Folder and Message usage.
      * 
-     * Depending on the session properties, the Store may be given a dedicated 
-     * connection, or will share connections with the Folders.  Connections may 
-     * be requested from either the Store or Folders.  Messages must request 
-     * their connections from their hosting Folder, and only one connection is 
-     * allowed per folder. 
+     * Depending on the session properties, the Store may be given a dedicated
+     * connection, or will share connections with the Folders.  Connections may
+     * be requested from either the Store or Folders.  Messages must request
+     * their connections from their hosting Folder, and only one connection is
+     * allowed per folder.
      * 
-     * @param store   The Store we're creating the pool for.
-     * @param session The Session this Store is created under.  This contains the properties
-     *                we used to tailor behavior.
-     * @param sslConnection
-     *                Indicates whether we need to start connections using an SSL connection.
-     * @param defaultPort
-     *                The default port.  Used if we receive a -1 port value on the initial
-     *                connection request.
-     * @param debug   The debug flag.  Tells us whether to wrapper connections with debug
-     *                capture streams.
+     * @param store  The Store we're creating the pool for.
+     * @param props  The property bundle that defines protocol properties
+     *               that alter the connection behavior.
      */
     public IMAPConnectionPool(IMAPStore store, ProtocolProperties props) {
         this.store = store;
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Command.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Command.java
deleted file mode 100644
index b161994..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Command.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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;
-
-/**
- * An abstraction for POP3Commands
- * 
- * @see org.apache.geronimo.javamail.store.pop3.POP3CommandFactory
- * 
- * @version $Rev$ $Date$
- */
-public interface POP3Command {
-
-    /**
-     * This method will get the POP3 command in string format according o
-     * rfc1939
-     */
-    public String getCommand();
-
-    /**
-     * Indicates wether this command expects a multiline response or not
-     * 
-     */
-    public boolean isMultiLineResponse();
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3CommandFactory.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3CommandFactory.java
deleted file mode 100644
index a66f97f..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3CommandFactory.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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;
-
-/**
- * Provides concrete implementations of
- * org.apache.geronimo.javamail.store.pop3.POP3Command objects representing the
- * POP3 commands defined in rfc 1939
- * 
- * @link http://www.faqs.org/rfcs/rfc1939.html
- * @version $Rev$ $Date$
- */
-public final class POP3CommandFactory implements POP3Constants {
-
-    public static POP3Command getCOMMAND_USER(final String user) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "USER" + SPACE + user + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_PASS(final String passwd) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "PASS" + SPACE + passwd + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_QUIT() {
-        return new POP3Command() {
-            public String getCommand() {
-                return "QUIT" + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_NOOP() {
-        return new POP3Command() {
-            public String getCommand() {
-                return "NOOP" + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_STAT() {
-        return new POP3Command() {
-            public String getCommand() {
-                return "STAT" + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_LIST() {
-        return getCOMMAND_LIST(-1);
-    }
-
-    public static POP3Command getCOMMAND_LIST(final int msgNo) {
-        return new POP3Command() {
-            public String getCommand() {
-                if (msgNo > 0) {
-                    return "LIST" + SPACE + msgNo + CRLF;
-                } else {
-                    return "LIST" + CRLF;
-                }
-            }
-
-            /**
-             * If a msg num is specified then the the message details will be on
-             * the first line for ex. +OK 3 4520
-             * 
-             * if no msgnum is specified then all the msg details are return in
-             * a multiline format for ex. +OK 2 messages 1 456 2 46456 ..... n
-             * 366
-             */
-            public boolean isMultiLineResponse() {
-                return (msgNo < 0);
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_RETR(final int msgNo) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "RETR" + SPACE + msgNo + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return true;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_DELE(final int msgNo) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "DELE" + SPACE + msgNo + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_REST(final int msgNo) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "REST" + SPACE + msgNo + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return false;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_TOP(final int msgNo, final int numLines) {
-        return new POP3Command() {
-            public String getCommand() {
-                return "TOP" + SPACE + msgNo + SPACE + numLines + CRLF;
-            }
-
-            public boolean isMultiLineResponse() {
-                return true;
-            }
-        };
-    }
-
-    public static POP3Command getCOMMAND_UIDL() {
-        return getCOMMAND_UIDL(-1);
-    }
-
-    public static POP3Command getCOMMAND_UIDL(final int msgNo) {
-        return new POP3Command() {
-            public String getCommand() {
-                if (msgNo > 0) {
-                    return "UIDL" + SPACE + msgNo + CRLF;
-                } else {
-                    return "UIDL" + CRLF;
-                }
-            }
-
-            public boolean isMultiLineResponse() {
-                return true;
-            }
-        };
-    }
-    
-    public static POP3Command getCOMMAND_CAPA() {
-    	return new POP3Command() {
-    		public String getCommand() {
-                return "CAPA" + CRLF;
-    		}
-    		
-    		public boolean isMultiLineResponse() {
-    			return true;
-    		}
-    	};
-    }
-
-    public static POP3Command getCOMMAND_AUTH(final String protocol) {
-    	return new POP3Command() {
-    		public String getCommand() {
-    			return "AUTH " + protocol + CRLF;
-    		}
-    		
-    		public boolean isMultiLineResponse() {
-    			return false;
-    		}
-    	};
-    }
-    
-    public static POP3Command getCOMMAND_AUTH(final String protocol, final String initialResponse) {
-    	return new POP3Command() {
-    		public String getCommand() {
-    			return "AUTH " + protocol + " " + initialResponse + CRLF;
-    		}
-    		
-    		public boolean isMultiLineResponse() {
-    			return false;
-    		}
-    	};
-    }
-    
-    public static POP3Command getCOMMAND_ChallengeReply(final String command) {
-    	return new POP3Command() {
-    			public String getCommand() {
-   						return command + CRLF;
-   				}
-    			
-    			public boolean isMultiLineResponse() {
-    				return false;
-    			}	
-    		};
-    }
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Connection.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Connection.java
deleted file mode 100644
index e5ccd4f..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Connection.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * 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;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.Socket;
-
-import javax.mail.MessagingException;
-import javax.mail.Session;
-
-/**
- * Represents a connection with the POP3 mail server. The connection is owned by
- * a pop3 store and is only associated with one user who owns the respective
- * POP3Store instance
- * 
- * @version $Rev$ $Date$
- */
-
-
-public class POP3Connection {
-
-	protected static final String MAIL_SSLFACTORY_CLASS = "mail.SSLSocketFactory.class";
-	
-    protected static final String MAIL_POP3_FACTORY_CLASS = "socketFactory.class";
-
-    protected static final String MAIL_POP3_FACTORY_FALLBACK = "socketFactory.fallback";
-
-    protected static final String MAIL_POP3_FACTORY_PORT = "socketFactory.port";
-    
-    protected static final String MAIL_POP3_LOCALADDRESS = "localAddress";
-    
-    protected static final String MAIL_POP3_LOCALPORT = "localPort";
-    
-    protected static final String MAIL_POP3_TIMEOUT = "timeout";
-	
-    private Socket socket;
-
-    private Session session;
-
-    private String host;
-
-    private int port;
-
-    private PrintWriter writer;
-
-    private BufferedReader reader;
-    
-    private String protocol;
-    
-    private boolean sslConnection;
-
-    POP3Connection(Session session, String host, int port, boolean sslConnection, String protocol) {
-
-        this.session = session;
-        this.host = host;
-        this.port = port;
-        this.sslConnection = sslConnection;
-        this.protocol = protocol;
-    }
-
-    public void open() throws Exception {
-        try {
-
-        	if (!sslConnection) {
-        		getConnectedSocket();
-        	} else {
-        		getConnectedSSLSocket();
-        	}
-
-            if (session.getDebug()) {
-                session.getDebugOut().println("Connection successful " + this.toString());
-            }
-
-            buildInputReader();
-            buildOutputWriter();
-
-            // consume the greeting
-            if (session.getDebug()) {
-                session.getDebugOut().println("Greeting from server " + reader.readLine());
-            } else {
-                reader.readLine();
-            }
-
-        } catch (IOException e) {
-            Exception ex = new Exception("Error opening connection " + this.toString(), e);
-            throw ex;
-        }
-    }
-
-    void close() throws Exception {
-        try {
-            socket.close();
-            if (session.getDebug()) {
-                session.getDebugOut().println("Connection successfuly closed " + this.toString());
-            }
-
-        } catch (IOException e) {
-            Exception ex = new Exception("Error closing connection " + this.toString(), e);
-            throw ex;
-        }
-
-    }
-
-    public synchronized POP3Response sendCommand(POP3Command cmd) throws MessagingException {
-        if (socket.isConnected()) {
-
-            // if the underlying output stream is down
-            // attempt to rebuild the writer
-            if (socket.isOutputShutdown()) {
-                buildOutputWriter();
-            }
-
-            // if the underlying inout stream is down
-            // attempt to rebuild the reader
-            if (socket.isInputShutdown()) {
-                buildInputReader();
-            }
-
-            if (session.getDebug()) {
-                session.getDebugOut().println("\nCommand sent " + cmd.getCommand());
-            }
-
-            POP3Response res = null;
-
-            // this method supresses IOException
-            // but choose bcos of ease of use
-            {
-                writer.write(cmd.getCommand());
-                writer.flush();
-                res = POP3ResponseBuilder.buildResponse(session, reader, cmd.isMultiLineResponse());
-            }
-
-            return res;
-        }
-
-        throw new MessagingException("Connection to Mail Server is lost, connection " + this.toString());
-    }
-
-    private void buildInputReader() throws MessagingException {
-        try {
-            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-        } catch (IOException e) {
-            throw new MessagingException("Error obtaining input stream " + this.toString(), e);
-        }
-    }
-
-    private void buildOutputWriter() throws MessagingException {
-        try {
-            writer = new PrintWriter(new BufferedOutputStream(socket.getOutputStream()));
-        } catch (IOException e) {
-            throw new MessagingException("Error obtaining output stream " + this.toString(), e);
-        }
-    }
-
-    public String toString() {
-        return "POP3Connection host: " + host + " port: " + port;
-    }
-
-
-	/**
-	 * Creates a connected socket
-	 *
-	 * @exception MessagingException
-	 */
-	protected void getConnectedSocket() throws IOException {
-	
-	    // the socket factory can be specified via a session property. By
-	    // default, we just directly
-	    // instantiate a socket without using a factor.
-	    String socketFactory = getProtocolProperty(MAIL_POP3_FACTORY_CLASS);
-	
-	    // there are several protocol properties that can be set to tune the
-	    // created socket. We need to
-	    // retrieve those bits before creating the socket.
-	    int timeout = getIntProtocolProperty(MAIL_POP3_TIMEOUT, -1);
-	    InetAddress localAddress = null;
-	    // see if we have a local address override.
-	    String localAddrProp = getProtocolProperty(MAIL_POP3_LOCALADDRESS);
-	    if (localAddrProp != null) {
-	        localAddress = InetAddress.getByName(localAddrProp);
-	    }
-	
-	    // check for a local port...default is to allow socket to choose.
-	    int localPort = getIntProtocolProperty(MAIL_POP3_LOCALPORT, 0);
-	
-	    socket = null;
-	
-	    // if there is no socket factory defined (normal), we just create a
-	    // socket directly.
-	    if (socketFactory == null) {
-	        socket = new Socket(host, port, localAddress, localPort);
-	    }
-	
-	    else {
-	        try {
-	            int socketFactoryPort = getIntProtocolProperty(MAIL_POP3_FACTORY_PORT, -1);
-	
-	            // we choose the port used by the socket based on overrides.
-	            Integer portArg = new Integer(socketFactoryPort == -1 ? port : socketFactoryPort);
-	
-	            // use the current context loader to resolve this.
-	            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-	            Class factoryClass = loader.loadClass(socketFactory);
-	
-	            // done indirectly, we need to invoke the method using
-	            // reflection.
-	            // This retrieves a factory instance.
-	            Method getDefault = factoryClass.getMethod("getDefault", new Class[0]);
-	            Object defFactory = getDefault.invoke(new Object(), new Object[0]);
-	
-	            // now that we have the factory, there are two different
-	            // createSocket() calls we use,
-	            // depending on whether we have a localAddress override.
-	
-	            if (localAddress != null) {
-	                // retrieve the createSocket(String, int, InetAddress, int)
-	                // method.
-	                Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class, Integer.TYPE };
-	                Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
-	
-	                Object[] createSocketArgs = new Object[] { host, portArg, localAddress, new Integer(localPort) };
-	                socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
-	            } else {
-	                // retrieve the createSocket(String, int) method.
-	                Class[] createSocketSig = new Class[] { String.class, Integer.TYPE };
-	                Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
-	
-	                Object[] createSocketArgs = new Object[] { host, portArg };
-	                socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
-	            }
-	        } catch (Throwable e) {
-	            // if a socket factory is specified, then we may need to fall
-	            // back to a default. This behavior
-	            // is controlled by (surprise) more session properties.
-	            if (isProtocolPropertyTrue(MAIL_POP3_FACTORY_FALLBACK)) {
-	                socket = new Socket(host, port, localAddress, localPort);
-	            }
-	            // we have an exception. We're going to throw an IOException,
-	            // which may require unwrapping
-	            // or rewrapping the exception.
-	            else {
-	                // we have an exception from the reflection, so unwrap the
-	                // base exception
-	                if (e instanceof InvocationTargetException) {
-	                    e = ((InvocationTargetException) e).getTargetException();
-	                }
-
-	
-	                // throw this as an IOException, with the original exception
-	                // attached.
-	                IOException ioe = new IOException("Error connecting to " + host + ", " + port);
-	                ioe.initCause(e);
-	                throw ioe;
-	            }
-	        }
-	    }
-	
-	    if (timeout >= 0) {
-	        socket.setSoTimeout(timeout);
-	    }
-	}
-
-	/**
-	 * Creates a connected SSL socket for an initial SSL connection.
-	 *
-	 * @exception MessagingException
-	 */
-	protected void getConnectedSSLSocket() throws IOException {
-
-	    if (session.getDebug()) {
-	        session.getDebugOut().println("Attempting SSL socket connection to server " + host + ":" + port);
-	    }
-	    // the socket factory can be specified via a protocol property, a
-	    // session property, and if all else
-	    // fails (which it usually does), we fall back to the standard factory
-	    // class.
-	    String socketFactory = getProtocolProperty(MAIL_POP3_FACTORY_CLASS, getSessionProperty(MAIL_SSLFACTORY_CLASS,
-	            "javax.net.ssl.SSLSocketFactory"));
-	
-	    // there are several protocol properties that can be set to tune the
-	    // created socket. We need to
-	    // retrieve those bits before creating the socket.
-	    int timeout = getIntProtocolProperty(MAIL_POP3_TIMEOUT, -1);
-	    InetAddress localAddress = null;
-	    // see if we have a local address override.
-	    String localAddrProp = getProtocolProperty(MAIL_POP3_LOCALADDRESS);
-	    if (localAddrProp != null) {
-	        localAddress = InetAddress.getByName(localAddrProp);
-	    }
-	
-	    // check for a local port...default is to allow socket to choose.
-	    int localPort = getIntProtocolProperty(MAIL_POP3_LOCALPORT, 0);
-	
-	    socket = null;
-	
-	    // if there is no socket factory defined (normal), we just create a
-	    // socket directly.
-	    if (socketFactory == null) {
-	    	System.out.println("SocketFactory was null so creating the connection using a default");
-	        socket = new Socket(host, port, localAddress, localPort);
-	    }
-	
-	    else {
-	        // we'll try this with potentially two different factories if we're
-	        // allowed to fall back.
-	        boolean fallback = isProtocolPropertyTrue(MAIL_POP3_FACTORY_FALLBACK);
-	        while(true) {
-	            try {
-	            	
-	            	
-	            	if (socket != null) {
-	            		if (socket.isConnected())
-	            		break;
-	            	}
-	            	
-	                if (session.getDebug()) {
-	                    session.getDebugOut().println("Creating SSL socket using factory " + socketFactory);
-	                }
-	                
-	                int socketFactoryPort = getIntProtocolProperty(MAIL_POP3_FACTORY_PORT, -1);
-	
-	                // we choose the port used by the socket based on overrides.
-	                Integer portArg = new Integer(socketFactoryPort == -1 ? port : socketFactoryPort);
-	
-	                // use the current context loader to resolve this.
-	                ClassLoader loader = Thread.currentThread().getContextClassLoader();
-	                Class factoryClass = loader.loadClass(socketFactory);
-	
-	                // done indirectly, we need to invoke the method using
-	                // reflection.
-	                // This retrieves a factory instance.
-	                Method getDefault = factoryClass.getMethod("getDefault", new Class[0]);
-	                Object defFactory = getDefault.invoke(new Object(), new Object[0]);
-	
-	                // now that we have the factory, there are two different
-	                // createSocket() calls we use,
-	                // depending on whether we have a localAddress override.
-	
-	                if (localAddress != null) {
-	                    // retrieve the createSocket(String, int, InetAddress,
-	                    // int) method.
-	                    Class[] createSocketSig = new Class[] { String.class, Integer.TYPE, InetAddress.class,
-	                            Integer.TYPE };
-	                    Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
-	
-	                    Object[] createSocketArgs = new Object[] { host, portArg, localAddress, new Integer(localPort) };
-	                    socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
-	                } else {
-	                    // retrieve the createSocket(String, int) method.
-	                    Class[] createSocketSig = new Class[] { String.class, Integer.TYPE };
-	                    Method createSocket = factoryClass.getMethod("createSocket", createSocketSig);
-	
-	                    Object[] createSocketArgs = new Object[] { host, portArg };
-	                    socket = (Socket) createSocket.invoke(defFactory, createSocketArgs);
-	                }
-	            } catch (Throwable e) {
-	                // if we're allowed to fallback, then use the default
-	                // factory and try this again. We only
-	                // allow this to happen once.
-                    if (session.getDebug()) {
-                        session.getDebugOut().println("First attempt at creating SSL socket failed, falling back to default factory");
-                    }
-	                if (fallback) {
-	                    socketFactory = "javax.net.ssl.SSLSocketFactory";
-	                    fallback = false;
-	                    continue;
-	                }
-	                // we have an exception. We're going to throw an
-	                // IOException, which may require unwrapping
-	                // or rewrapping the exception.
-	                else {
-	                    // we have an exception from the reflection, so unwrap
-	                    // the base exception
-	                    if (e instanceof InvocationTargetException) {
-	                        e = ((InvocationTargetException) e).getTargetException();
-	                    }
-	
-	                    if (session.getDebug()) {
-	                        session.getDebugOut().println("Failure creating SSL socket: " + e);
-	                    }
-	                    // throw this as an IOException, with the original
-	                    // exception attached.
-	                    IOException ioe = new IOException("Error connecting to " + host + ", " + port);
-	                    ioe.initCause(e);
-	                    throw ioe;
-	                }
-	            }
-	        }
-	    }
-	
-	    if (timeout >= 0) {
-	        socket.setSoTimeout(timeout);
-	    }
-	}
-	
-    /**
-     * Process a session property as a boolean value, returning either true or
-     * false.
-     *
-     * @return True if the property value is "true". Returns false for any other
-     *         value (including null).
-     */
-    protected boolean isProtocolPropertyTrue(String name) {
-        // the name we're given is the least qualified part of the name. We
-        // construct the full property name
-        // using the protocol ("pop3").
-        String fullName = "mail." + protocol + "." + name;
-        return isSessionPropertyTrue(fullName);
-    }
-
-    /**
-     * Process a session property as a boolean value, returning either true or
-     * false.
-     *
-     * @return True if the property value is "true". Returns false for any other
-     *         value (including null).
-     */
-    protected boolean isSessionPropertyTrue(String name) {
-        String property = session.getProperty(name);
-        if (property != null) {
-            return property.equals("true");
-        }
-        return false;
-    }
-    
-    /**
-     * Get a property associated with this mail session as an integer value.
-     * Returns the default value if the property doesn't exist or it doesn't
-     * have a valid int value.
-     *
-     * @param name
-     *            The name of the property.
-     * @param defaultValue
-     *            The default value to return if the property doesn't exist.
-     *
-     * @return The property value converted to an int.
-     */
-    protected int getIntProtocolProperty(String name, int defaultValue) {
-        // the name we're given is the least qualified part of the name. We
-        // construct the full property name
-        // using the protocol (pop3).
-        String fullName = "mail." + protocol + "." + name;
-        return getIntSessionProperty(fullName, defaultValue);
-    }
-    
-    /**
-     * Get a property associated with this mail session as an integer value.
-     * Returns the default value if the property doesn't exist or it doesn't
-     * have a valid int value.
-     *
-     * @param name
-     *            The name of the property.
-     * @param defaultValue
-     *            The default value to return if the property doesn't exist.
-     *
-     * @return The property value converted to an int.
-     */
-    protected int getIntSessionProperty(String name, int defaultValue) {
-        String result = getSessionProperty(name);
-        if (result != null) {
-            try {
-                // convert into an int value.
-                return Integer.parseInt(result);
-            } catch (NumberFormatException e) {
-            }
-        }
-        // return default value if it doesn't exist is isn't convertable.
-        return defaultValue;
-    }
-
-    /**
-     * Get a property associated with this mail session. Returns the provided
-     * default if it doesn't exist.
-     *
-     * @param name
-     *            The name of the property.
-     * @param defaultValue
-     *            The default value to return if the property doesn't exist.
-     *
-     * @return The property value (returns defaultValue if the property has not
-     *         been set).
-     */
-    protected String getSessionProperty(String name, String defaultValue) {
-        String result = session.getProperty(name);
-        if (result == null) {
-            return defaultValue;
-        }
-        return result;
-    }
-
-    /**
-     * Get a property associated with this mail session. Returns the provided
-     * default if it doesn't exist.
-     *
-     * @param name
-     *            The name of the property.
-     * @param defaultValue
-     *            The default value to return if the property doesn't exist.
-     *
-     * @return The property value (returns defaultValue if the property has not
-     *         been set).
-     */
-    protected String getProtocolProperty(String name, String defaultValue) {
-        // the name we're given is the least qualified part of the name. We
-        // construct the full property name
-        // using the protocol ("pop3").
-        String fullName = "mail." + protocol + "." + name;
-        return getSessionProperty(fullName, defaultValue);
-    }
-    
-    /**
-     * Get a property associated with this mail protocol.
-     *
-     * @param name
-     *            The name of the property.
-     *
-     * @return The property value (returns null if the property has not been
-     *         set).
-     */
-    protected String getProtocolProperty(String name) {
-        // the name we're given is the least qualified part of the name. We
-        // construct the full property name
-        // using the protocol ("pop3").
-        String fullName = "mail." + protocol + "." + name;
-        return getSessionProperty(fullName);
-    }
-
-    /**
-     * Get a property associated with this mail session.
-     *
-     * @param name
-     *            The name of the property.
-     *
-     * @return The property value (returns null if the property has not been
-     *         set).
-     */
-    protected String getSessionProperty(String name) {
-        return session.getProperty(name);
-    }
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Constants.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Constants.java
index 57aed7e..6b3f5ef 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Constants.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Constants.java
@@ -30,10 +30,6 @@
 
     public final static String CRLF = "\r\n";
 
-    public final static int LF = '\n';
-
-    public final static int CR = '\r';
-
     public final static int DOT = '.';
 
     public final static int OK = 0;
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
index 042c170..6e59064 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
@@ -19,11 +19,12 @@
 
 package org.apache.geronimo.javamail.store.pop3;
 
-import java.util.Vector;
+import java.util.List;     
 
 import javax.mail.FetchProfile;
 import javax.mail.Flags;
 import javax.mail.Folder;
+import javax.mail.FolderClosedException;
 import javax.mail.Message;
 import javax.mail.MessagingException;
 import javax.mail.MethodNotSupportedException;
@@ -32,10 +33,8 @@
 import javax.mail.URLName;
 import javax.mail.event.ConnectionEvent;
 
-import org.apache.geronimo.javamail.store.pop3.message.POP3Message;
-import org.apache.geronimo.javamail.store.pop3.message.POP3MessageFactory;
-import org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory;
-import org.apache.geronimo.javamail.store.pop3.response.POP3StatusResponse;
+import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection; 
+import org.apache.geronimo.javamail.store.pop3.connection.POP3StatusResponse; 
 
 /**
  * The POP3 implementation of the javax.mail.Folder Note that only INBOX is
@@ -50,53 +49,90 @@
  */
 public class POP3Folder extends Folder {
 
-    private boolean isFolderOpen = false;
+    protected boolean isFolderOpen = false;
 
-    private int mode;
+    protected int mode;
 
-    private POP3Connection pop3Con;
+    protected POP3Connection currentConnection; 
 
-    private int msgCount;
+    protected int msgCount;
 
-    private Session session;
+    private POP3Message[] messageCache; 
+    // The fully qualified name of the folder.  For a POP3 folder, this is either "" for the root or 
+    // "INPUT" for the in-basket.  It is possible to create other folders, but they will report that 
+    // they don't exist. 
+    protected String fullName;  
+    // indicates whether this folder exists or not 
+    protected boolean exists = false; 
+    // indicates the type of folder this is. 
+    protected int folderType; 
+    
+    /**
+     * Create a new folder associate with a POP3 store instance.
+     * 
+     * @param store  The owning Store.
+     * @param name   The name of the folder.  Note that POP3 stores only
+     *               have 2 real folders, the root ("") and the in-basket
+     *               ("INBOX").  It is possible to create other instances
+     *               of Folder associated with the Store, but they will
+     *               be non-functional.
+     */
+     public POP3Folder(POP3Store store, String name) {
+        super(store);
+        this.fullName = name; 
+        // if this is the input folder, this exists 
+        if (name.equalsIgnoreCase("INPUT")) {
+            exists = true; 
+        }
+        // by default, we're holding messages. 
+        folderType = Folder.HOLDS_MESSAGES; 
+    }
+    
+    
+    /**
+     * Retrieve the folder name.  This is the simple folder
+     * name at the its hiearchy level.  This can be invoked when the folder is closed.
+     * 
+     * @return The folder's name.
+     */
+	public String getName() {
+        // the name and the full name are always the same
+        return fullName; 
+	}
 
     /**
-     * Vector is synchronized so choose over the other Collection impls This is
-     * initialized on open A chache will save the expensive operation of
-     * retrieving the message again from the server.
+     * Retrieve the folder's full name (including hierarchy information).
+     * This can be invoked when the folder is closed.
+     *
+     * @return The full name value.
      */
-    private Vector msgCache;
+	public String getFullName() {
+        return fullName;
+	}
 
-    protected POP3Folder(Store store, URLName url) {
-        super(store);
-    }
-
-    protected POP3Folder(Store store, Session session, POP3Connection pop3Con) {
-        super(store);
-        this.pop3Con = pop3Con;
-        this.session = session;
-    }
-
-    public String getName() {
-        return "INBOX";
-    }
-
-    public String getFullName() {
-        return "INBOX";
-    }
-
+    
     /**
      * Never return "this" as the parent folder. Somebody not familliar with
      * POP3 may do something like while(getParent() != null) or something
      * simmilar which will result in an infinte loop
      */
     public Folder getParent() throws MessagingException {
-        throw new MethodNotSupportedException("INBOX is the root folder");
+        // the default folder returns null.  We return the default 
+        // folder 
+        return store.getDefaultFolder(); 
     }
 
+    /**
+     * Indicate whether a folder exists.  Only the root 
+     * folder and "INBOX" will ever return true. 
+     * 
+     * @return true for real POP3 folders, false for any other 
+     *         instances that have been created.
+     * @exception MessagingException
+     */
     public boolean exists() throws MessagingException {
-        // INBOX always exists at the backend
-        return true;
+        // only one folder truely exists...this might be it.
+        return exists; 
     }
 
     public Folder[] list(String pattern) throws MessagingException {
@@ -104,22 +140,44 @@
     }
 
     /**
-     * No sub folders, hence there is no notion of a seperator
+     * No sub folders, hence there is no notion of a seperator.  This is always a null character. 
      */
     public char getSeparator() throws MessagingException {
-        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
+        return '\0';
     }
 
+    /**
+     * There's no hierarchy in POP3, so the only type 
+     * is HOLDS_MESSAGES (and only one of those exists).
+     * 
+     * @return Always returns HOLDS_MESSAGES. 
+     * @exception MessagingException
+     */
     public int getType() throws MessagingException {
-        return HOLDS_MESSAGES;
+        return folderType;      
     }
 
+    /**
+     * Always returns false as any creation operation must 
+     * fail. 
+     * 
+     * @param type   The type of folder to create.  This is ignored.
+     * 
+     * @return Always returns false. 
+     * @exception MessagingException
+     */
     public boolean create(int type) throws MessagingException {
-        throw new MethodNotSupportedException("Only INBOX is supported in POP3, no sub folders");
+        return false; 
     }
 
+    /**
+     * No way to detect new messages, so always return false. 
+     * 
+     * @return Always returns false. 
+     * @exception MessagingException
+     */
     public boolean hasNewMessages() throws MessagingException {
-        throw new MethodNotSupportedException("POP3 doesn't support this operation");
+        return false; 
     }
 
     public Folder getFolder(String name) throws MessagingException {
@@ -142,13 +200,14 @@
         checkClosed();
 
         try {
+            
+            // ask the store to kindly hook us up with a connection.
+            // We're going to hang on to this until we're closed, so store it in 
+            // the Folder field.  We need to make sure our mailbox is selected while 
+            // we're working things. 
+            currentConnection = ((POP3Store)store).getFolderConnection(this); 
 
-            POP3StatusResponse res = (POP3StatusResponse) POP3ResponseFactory.getStatusResponse(pop3Con
-                    .sendCommand(POP3CommandFactory.getCOMMAND_STAT()));
-
-            // I am not checking for the res == null condition as the
-            // try catch block will handle it.
-
+            POP3StatusResponse res = currentConnection.retrieveMailboxStatus();
             this.mode = mode;
             this.isFolderOpen = true;
             this.msgCount = res.getNumMessages();
@@ -156,11 +215,9 @@
             // size (no of bytes) of the mail drop;
 
             // NB:  We use the actual message number to access the messages from 
-            // the cache, which is origin 1.  Vectors are origin 0, so we add one additional 
-            // element and burn the 
-            msgCache = new Vector(msgCount + 1);
-            msgCache.setSize(msgCount + 1);
-
+            // the cache, which is origin 1.  Vectors are origin 0, so we have to subtract each time 
+            // we access a messagge.  
+            messageCache = new POP3Message[msgCount]; 
         } catch (Exception e) {
             throw new MessagingException("Unable to execute STAT command", e);
         }
@@ -168,57 +225,137 @@
         notifyConnectionListeners(ConnectionEvent.OPENED);
     }
 
+    /**
+     * Close a POP3 folder.
+     * 
+     * @param expunge The expunge flag (ignored for POP3).
+     * 
+     * @exception MessagingException
+     */
     public void close(boolean expunge) throws MessagingException {
         // Can only be performed on an open folder
         checkOpen();
-
         try {
-            if (mode == READ_WRITE) {
-                // find all messages marked deleted and issue DELE commands
-                POP3Message m;
-                // NB: the first element in the cache is not used.
-                for (int i = 1; i < msgCache.size(); i++) {
-                    if ((m = (POP3Message) msgCache.elementAt(i)) != null) {
-                        if (m.isSet(Flags.Flag.DELETED)) {
-                            try {
-                                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_DELE(i + 1));
-                            } catch (Exception e) {
-                                throw new MessagingException("Exception deleting message no [" + (i + 1)
-                                        + "] during close", e);
-                            }
+            // we might need to reset the connection before we 
+            // process deleted messages and send the QUIT.  The 
+            // connection knows if we need to do this. 
+            currentConnection.reset(); 
+            // clean up any messages marked for deletion 
+            expungeDeletedMessages(); 
+        } finally {
+            // cleanup the the state even if exceptions occur when deleting the 
+            // messages. 
+            cleanupFolder(false); 
+        }
+    }
+    
+    /**
+     * Mark any messages we've flagged as deleted from the 
+     * IMAP server before closing. 
+     * 
+     * @exception MessagingException
+     */
+    protected void expungeDeletedMessages() throws MessagingException {
+        if (mode == READ_WRITE) {
+            for (int i = 0; i < messageCache.length; i++) {
+                POP3Message msg = messageCache[i]; 
+                if (msg != null) {
+                    // if the deleted flag is set, go delete this 
+                    // message. NB:  We adjust the index back to an 
+                    // origin 1 value 
+                    if (msg.isSet(Flags.Flag.DELETED)) {
+                        try {
+                            currentConnection.deleteMessage(i + 1); 
+                        } catch (MessagingException e) {
+                            throw new MessagingException("Exception deleting message number " + (i + 1), e); 
                         }
                     }
                 }
             }
-
-            try {
-                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_QUIT());
-            } catch (Exception e) {
-                // doesn't really care about the response
-            }
-            // dosn't need a catch block here, but added incase something goes
-            // wrong
-            // so that the finnaly is garunteed to execute in such a case.
-        } finally {
-            try {
-                pop3Con.close();
-            } catch (Exception e) {
-                // doesn't really care about the response
-                // all we can do is to set the reference explicitly to null
-                pop3Con = null;
-            }
-
-            /*
-             * The message numbers depend on the mail drop if the connection is
-             * closed, then purge the cache
-             */
-            msgCache = null;
-            isFolderOpen = false;
-            notifyConnectionListeners(ConnectionEvent.CLOSED);
         }
     }
+    
+    
+    /**
+     * Do folder cleanup.  This is used both for normal
+     * close operations, and adnormal closes where the
+     * server has sent us a BYE message.
+     * 
+     * @param expunge Indicates whether open messages should be expunged.
+     * @param disconnected
+     *                The disconnected flag.  If true, the server has cut
+     *                us off, which means our connection can not be returned
+     *                to the connection pool.
+     * 
+     * @exception MessagingException
+     */
+    protected void cleanupFolder(boolean disconnected) throws MessagingException {
+        messageCache = null;
+        isFolderOpen = false;
+        // if we have a connection active at the moment
+        if (currentConnection != null) {
+            // was this a forced disconnect by the server?
+            if (disconnected) {
+                currentConnection.setClosed(); 
+            }
+            else {
+                // have this close the selected mailbox 
+                currentConnection.logout();           
+            }
+            // we need to release the connection to the Store once we're closed 
+            ((POP3Store)store).releaseFolderConnection(this, currentConnection); 
+            currentConnection = null; 
+        }
+		notifyConnectionListeners(ConnectionEvent.CLOSED);
+    }
+    
+    
+    /**
+     * Obtain a connection object for a Message attached to this Folder.  This 
+     * will be the Folder's connection, which is only available if the Folder 
+     * is currently open.
+     * 
+     * @return The connection object for the Message instance to use. 
+     * @exception MessagingException
+     */
+    synchronized POP3Connection getMessageConnection() throws MessagingException {
+        // if we're not open, the messages can't communicate either
+        if (currentConnection == null) {
+            throw new FolderClosedException(this, "No Folder connections available"); 
+        }
+        // return the current Folder connection.  At this point, we'll be sharing the 
+        // connection between the Folder and the Message (and potentially, other messages).  The 
+        // command operations on the connection are synchronized so only a single command can be 
+        // issued at one time. 
+        return currentConnection; 
+    }
+    
+    
+    /**
+     * Release the connection object back to the Folder instance.  
+     * 
+     * @param connection The connection being released.
+     * 
+     * @exception MessagingException
+     */
+    void releaseMessageConnection(POP3Connection connection) throws MessagingException {
+        // This is a NOP for this folder type. 
+    }
 
     public boolean isOpen() {
+        // if we're not open, we're not open 
+        if (!isFolderOpen) {
+            return false; 
+        }
+        
+        try {
+            // we might be open, but the Store has been closed.  In which case, we're not any more
+            // closing also changes the isFolderOpen flag. 
+            if (!((POP3Store)store).isConnected()) {
+                close(false); 
+            }
+        } catch (MessagingException e) {
+        }
         return isFolderOpen;
     }
 
@@ -233,7 +370,14 @@
         return new Flags();
     }
 
+    /**
+     * Get the folder message count.
+     * 
+     * @return The number of messages in the folder.
+     * @exception MessagingException
+     */
     public int getMessageCount() throws MessagingException {
+        // NB: returns -1 if the folder isn't open. 
         return msgCount;
     }
 
@@ -250,15 +394,10 @@
             throw new MessagingException("Invalid Message number");
         }
 
-        Message msg = null;
-        try {
-            msg = (Message) msgCache.elementAt(msgNum);
-        } catch (RuntimeException e) {
-            session.getDebugOut().println("Message not in cache");
-        }
+        Message msg = messageCache[msgNum - 1];
         if (msg == null) {
-            msg = POP3MessageFactory.createMessage(this, session, pop3Con, msgNum);
-            msgCache.setElementAt(msg, msgNum);
+            msg = new POP3Message(this, msgNum); 
+            messageCache[msgNum - 1] = (POP3Message)msg; 
         }
 
         return msg;
@@ -286,29 +425,50 @@
      * The JavaMail API recommends that this method be overrident to provide a
      * meaningfull implementation.
      */
-    public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException {
+    public synchronized void fetch(Message[] msgs, FetchProfile fp) throws MessagingException {
         // Can only be performed on an Open folder
         checkOpen();
         for (int i = 0; i < msgs.length; i++) {
             Message msg = msgs[i];
-            if (msg == null) {
-                msg = POP3MessageFactory.createMessage(this, session, pop3Con, i);
-            }
+            
             if (fp.contains(FetchProfile.Item.ENVELOPE)) {
-                msg = POP3MessageFactory.createMessageWithEvelope((POP3Message) msg);
+                // fetching the size and the subject will force all of the 
+                // envelope information to load 
+                msg.getHeader("Subject"); 
+                msg.getSize(); 
             }
-
             if (fp.contains(FetchProfile.Item.CONTENT_INFO)) {
-                msg = POP3MessageFactory.createMessageWithContentInfo((POP3Message) msg);
+                // force the content to load...this also fetches the header information. 
+                // C'est la vie. 
+                ((POP3Message)msg).loadContent(); 
+                msg.getSize(); 
             }
-
+            // force flag loading for this message 
             if (fp.contains(FetchProfile.Item.FLAGS)) {
-                msg = POP3MessageFactory.createMessageWithFlags((POP3Message) msg);
+                msg.getFlags(); 
             }
-
-            msgs[i] = msg;
+            
+            if (fp.getHeaderNames().length > 0) {
+                // loading any header loads all headers, so just grab the header set. 
+                msg.getHeader("Subject"); 
+            }
         }
     }
+    
+    /**
+     * Retrieve the UID for a given message.
+     * 
+     * @param msg    The message of interest.
+     * 
+     * @return The String UID value for this message.
+     * @exception MessagingException
+     */
+    public synchronized String getUID(Message msg) throws MessagingException {
+        checkOpen(); 
+        // the Message knows how to do this 
+        return ((POP3Message)msg).getUID(); 
+    }
+    
 
     /**
      * Below is a list of covinience methods that avoid repeated checking for a
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Message.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Message.java
new file mode 100644
index 0000000..966da66
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Message.java
@@ -0,0 +1,378 @@
+/*
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.IllegalWriteException;
+import javax.mail.MessagingException;
+import javax.mail.event.MessageChangedEvent;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection;
+
+/**
+ * POP3 implementation of javax.mail.internet.MimeMessage
+ * 
+ * Only the most basic information is given and Message objects created here is
+ * a light-weight reference to the actual Message As per the JavaMail spec items
+ * from the actual message will get filled up on demand
+ * 
+ * If some other items are obtained from the server as a result of one call,
+ * then the other details are also processed and filled in. For ex if RETR is
+ * called then header information will also be processed in addition to the
+ * content
+ * 
+ * @version $Rev$ $Date$
+ */
+public class POP3Message extends MimeMessage {
+    // the size of the message, in bytes
+    protected int msgSize = -1;
+    // the size of the headers.  We keep this around, as it's needed to 
+    // properly calculate the size of the message 
+    protected int headerSize = -1;
+    // the UID value retrieved from the server 
+    protected String uid; 
+    // the raw message data from loading the message
+    protected byte[] messageData; 
+
+    /**
+     * Create a new POP3 message associated with a folder.
+     * 
+     * @param folder The owning folder.
+     * @param msgnum The message sequence number in the folder.
+     */
+    protected POP3Message(Folder folder, int msgnum) {
+        super(folder, msgnum);
+        this.session = session;
+        // force the headers to empty so we'll load them the first time they're referenced. 
+        this.headers = null; 
+    }
+
+    /**
+     * Get an InputStream for reading the message content. 
+     * 
+     * @return An InputStream instance initialized to read the message 
+     *         content.
+     * @exception MessagingException
+     */
+    protected InputStream getContentStream() throws MessagingException {
+        // make sure the content is loaded first 
+        loadContent(); 
+        // allow the super class to handle creating it from the loaded content.
+        return super.getContentStream();
+    }
+
+
+    /**
+     * Write out the byte data to the provided output stream.
+     *
+     * @param out    The target stream.
+     *
+     * @exception IOException
+     * @exception MessagingException
+     */
+    public void writeTo(OutputStream out) throws IOException, MessagingException {
+        // make sure we have everything loaded 
+        loadContent(); 
+        // just write out the raw message data 
+        out.write(messageData); 
+    }
+    
+
+    /**
+     * Set a flag value for this Message.  The flags are 
+     * only set locally, not the server.  When the folder 
+     * is closed, any messages with the Deleted flag set 
+     * will be removed from the server. 
+     * 
+     * @param newFlags The new flag values.
+     * @param set      Indicates whether this is a set or an unset operation.
+     * 
+     * @exception MessagingException
+     */
+    public void setFlags(Flags newFlags, boolean set) throws MessagingException {
+        Flags oldFlags = (Flags) flags.clone();
+        super.setFlags(newFlags, set);
+
+        if (!flags.equals(oldFlags)) {
+            ((POP3Folder) folder).notifyMessageChangedListeners(MessageChangedEvent.FLAGS_CHANGED, this);
+        }
+    }
+
+    /**
+     * Unconditionally load the headers from an inputstream. 
+     * When retrieving content, we get back the entire message, 
+     * including the headers.  This allows us to skip over 
+     * them to reach the content, even if we already have 
+     * headers loaded. 
+     * 
+     * @param in     The InputStream with the header data.
+     * 
+     * @exception MessagingException
+     */
+    protected void loadHeaders(InputStream in) throws MessagingException {
+        try {
+            headerSize = in.available(); 
+            // just load and replace the haders 
+            headers = new InternetHeaders(in);
+            headerSize -= in.available(); 
+        } catch (IOException e) {
+            // reading from a ByteArrayInputStream...this should never happen. 
+        }
+    }
+    
+    /**
+     * Lazy loading of the message content. 
+     * 
+     * @exception MessagingException
+     */
+    protected void loadContent() throws MessagingException {
+        if (content == null) {
+            POP3Connection connection = getConnection(); 
+            try {
+                // retrieve (and save the raw message data 
+                messageData = connection.retrieveMessageData(msgnum);
+            } finally {
+                // done with the connection
+                releaseConnection(connection); 
+            }
+            // now create a input stream for splitting this into headers and 
+            // content 
+            ByteArrayInputStream in = new ByteArrayInputStream(messageData); 
+            
+            // the Sun implementation has an option that forces headers loaded using TOP 
+            // should be forgotten when retrieving the message content.  This is because 
+            // some POP3 servers return different results for TOP and RETR.  Since we need to 
+            // retrieve the headers anyway, and this set should be the most complete, we'll 
+            // just replace the headers unconditionally. 
+            loadHeaders(in);
+            // load headers stops loading at the header terminator.  Everything 
+            // after that is content. 
+            loadContent(in);
+        }
+    }
+
+    /**
+     * Load the message content from the server.
+     * 
+     * @param stream A ByteArrayInputStream containing the message content.
+     *               We explicitly use ByteArrayInputStream because
+     *               there are some optimizations that can take advantage
+     *               of the fact it is such a stream.
+     * 
+     * @exception MessagingException
+     */
+    protected void loadContent(ByteArrayInputStream stream) throws MessagingException {
+        // since this is a byte array input stream, available() returns reliable value. 
+        content = new byte[stream.available()];
+        try {
+            // just read everything in to the array 
+            stream.read(content); 
+        } catch (IOException e) {
+            // should never happen 
+            throw new MessagingException("Error loading content info", e);
+        }
+    }
+
+    /**
+     * Get the size of the message.
+     * 
+     * @return The calculated message size, in bytes. 
+     * @exception MessagingException
+     */
+    public int getSize() throws MessagingException {
+        if (msgSize < 0) {
+            // we need to get the headers loaded, since we need that information to calculate the total 
+            // content size without retrieving the content. 
+            loadHeaders();  
+            
+            POP3Connection connection = getConnection(); 
+            try {
+
+                // get the total message size, and adjust by size of the headers to get the content size. 
+                msgSize = connection.retrieveMessageSize(msgnum) - headerSize; 
+            } finally {
+                // done with the connection
+                releaseConnection(connection); 
+            }
+        }
+        return msgSize;
+    }
+
+    /**
+     * notice that we pass zero as the no of lines from the message,as it
+     * doesn't serv any purpose to get only a certain number of lines.
+     * 
+     * However this maybe important if a mail client only shows 3 or 4 lines of
+     * the message in the list and then when the user clicks they would load the
+     * message on demand.
+     * 
+     */
+    protected void loadHeaders() throws MessagingException {
+        if (headers == null) {
+            POP3Connection connection = getConnection(); 
+            try {
+                loadHeaders(connection.retrieveMessageHeaders(msgnum)); 
+            } finally {
+                // done with the connection
+                releaseConnection(connection); 
+            }
+        }
+    }
+    
+    /**
+     * Retrieve the message UID from the server.
+     * 
+     * @return The string UID value. 
+     * @exception MessagingException
+     */
+    protected String getUID() throws MessagingException {
+        if (uid == null) {
+            POP3Connection connection = getConnection(); 
+            try {
+                uid = connection.retrieveMessageUid(msgnum); 
+            } finally {
+                // done with the connection
+                releaseConnection(connection); 
+            }
+        }
+        return uid; 
+    }
+    
+    // The following are methods that deal with all header accesses.  Most of the 
+    // methods that retrieve information from the headers funnel through these, so we 
+    // can lazy-retrieve the header information. 
+
+    public String[] getHeader(String name) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getHeader(name); 
+    }
+
+    public String getHeader(String name, String delimiter) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getHeader(name, delimiter); 
+    }
+
+    public Enumeration getAllHeaders() throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getAllHeaders(); 
+    }
+
+    public Enumeration getMatchingHeaders(String[] names) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getMatchingHeaders(names); 
+    }
+
+    public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getNonMatchingHeaders(names); 
+    }
+
+    public Enumeration getAllHeaderLines() throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getAllHeaderLines();       
+    }
+
+    public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getMatchingHeaderLines(names); 
+    }
+
+    public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
+        // make sure the headers are loaded 
+        loadHeaders(); 
+        // allow the super class to handle everything from here 
+        return super.getNonMatchingHeaderLines(names); 
+    }
+
+    // the following are overrides for header modification methods. These
+    // messages are read only,
+    // so the headers cannot be modified.
+    public void addHeader(String name, String value) throws MessagingException {
+        throw new IllegalWriteException("POP3 messages are read-only");
+    }
+
+    public void setHeader(String name, String value) throws MessagingException {
+        throw new IllegalWriteException("POP3 messages are read-only");
+    }
+
+    public void removeHeader(String name) throws MessagingException {
+        throw new IllegalWriteException("POP3 messages are read-only");
+    }
+
+    public void addHeaderLine(String line) throws MessagingException {
+        throw new IllegalWriteException("POP3 messages are read-only");
+    }
+
+    /**
+     * We cannot modify these messages
+     */
+    public void saveChanges() throws MessagingException {
+        throw new IllegalWriteException("POP3 messages are read-only");
+    }
+
+    
+    /**
+     * get the current connection pool attached to the folder.  We need
+     * to do this dynamically, to A) ensure we're only accessing an
+     * currently open folder, and B) to make sure we're using the
+     * correct connection attached to the folder.
+     *
+     * @return A connection attached to the hosting folder.
+     */
+    protected POP3Connection getConnection() throws MessagingException {
+        // the folder owns everything.
+        return ((POP3Folder)folder).getMessageConnection();
+    }
+    
+    /**
+     * Release the connection back to the Folder after performing an operation 
+     * that requires a connection.
+     * 
+     * @param connection The previously acquired connection.
+     */
+    protected void releaseConnection(POP3Connection connection) throws MessagingException {
+        // the folder owns everything.
+        ((POP3Folder)folder).releaseMessageConnection(connection);
+    }
+}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Response.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Response.java
deleted file mode 100644
index 197ca20..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Response.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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;
-
-import java.io.InputStream;
-
-/**
- * An abstraction for POP3 Response
- * 
- * @see org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory
- * @see org.apache.geronimo.javamail.store.pop3.response.DefaultPOP3Response
- * @see org.apache.geronimo.javamail.store.pop3.response.POP3StatusResponse
- * 
- * @version $Rev$ $Date$
- */
-public interface POP3Response {
-
-    /**
-     * Returns the response OK, CHALLENGE or ERR
-     * <ul>
-     * <li>OK --> +OK in pop3 spec
-     * <li>CHALLENGE --> + in pop3 spec
-     * <li>ERR --> -ERR in pop3 spec
-     * </ul>
-     */
-    public int getStatus();
-
-    /**
-     * this corresponds to the line with the status however the status will be
-     * removed and the remainder is returned. Ex. "+OK 132 3023673" is the first
-     * line of response for a STAT command this method will return "132 3023673"
-     * 
-     * So any subsequent process can parse the params 132 as no of msgs and
-     * 3023674 as the size.
-     * 
-     * @see org.apache.geronimo.javamail.store.pop3.response.POP3StatusResponse
-     */
-    public String getFirstLine();
-
-    /**
-     * This way we are not restricting anybody as InputStream.class is the most
-     * basic type to represent an inputstream and ppl can decorate it anyway
-     * they want, for ex BufferedInputStream or as an InputStreamReader allowing
-     * maximum flexibility in using it.
-     */
-    public InputStream getData();
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3ResponseBuilder.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3ResponseBuilder.java
deleted file mode 100644
index 7b0ab4a..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3ResponseBuilder.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.mail.MessagingException;
-import javax.mail.Session;
-
-import org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory;
-
-;
-
-/**
- * Builds a basic response out of the input stream received by the connection.
- * Performs only two basic functions
- * <ul>
- * <li>Extrats the status code</li>
- * <li>If multi-line response then extract the data as an input stream</li>
- * </ul>
- * 
- * @version $Rev$ $Date$
- */
-
-public final class POP3ResponseBuilder implements POP3Constants {
-
-    public static POP3Response buildResponse(Session session, BufferedReader reader, boolean isMultiLineResponse)
-            throws MessagingException {
-
-        int status = ERR;
-        InputStream data = null;
-
-        String line;
-        try {
-            line = reader.readLine();
-        } catch (IOException e) {
-            throw new MessagingException("Error in receving response");
-        }
-        if (line == null || line.trim().equals("")) {
-            if (session.getDebug()) {
-                session.getDebugOut().println("Empty Response");
-            }
-            throw new MessagingException("Empty Response");
-        }
-        if (session.getDebug()) {
-            session.getDebugOut().println("Response From Server " + line);
-        }
-
-        if (line.startsWith("+OK")) {
-            status = OK;
-            line = removeStatusField(line);
-            if (isMultiLineResponse) {
-                data = getMultiLineResponse(session, reader);
-            }
-        } else if (line.startsWith("-ERR")) {
-            status = ERR;
-            line = removeStatusField(line);
-        }else if (line.startsWith("+")) {
-        	status = CHALLENGE;
-        	line = removeStatusField(line);
-        	if (isMultiLineResponse) {
-        		data = getMultiLineResponse(session, reader);
-        	}
-        } else {
-            throw new MessagingException("Unexpected response: " + line);
-        }
-
-        return POP3ResponseFactory.getDefaultResponse(status, line, data);
-    }
-
-    private static String removeStatusField(String line) {
-        return line.substring(line.indexOf(SPACE) + 1);
-    }
-
-    /**
-     * This could be a multiline response
-     */
-    private static InputStream getMultiLineResponse(Session session, BufferedReader reader) throws MessagingException {
-
-        int byteRead = -1;
-        int lastByteRead = LF;
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            while ((byteRead = reader.read()) >= 0) {
-                // We are checking for the end of a multiline response
-                // the format is .CRLF
-
-                // checking for the DOT and CR
-                if (lastByteRead == DOT && byteRead == CR) {
-                    byteRead = reader.read();
-                    // now checking for the LF of the second CRLF
-                    if (byteRead == LF) {
-                        // end of response
-                        break;
-                    }
-                }
-
-                out.write(byteRead);
-                lastByteRead = byteRead;
-            }
-
-            if (session.getDebug()) {
-                session.getDebugOut().println("\n============================ Response Content==================\n");
-                session.getDebugOut().write(out.toByteArray());
-                session.getDebugOut().println("\n==============================================================\n");
-            }
-
-        } catch (IOException e) {
-            throw new MessagingException("Error processing a multi-line response", e);
-        }
-
-        return new ByteArrayInputStream(out.toByteArray());
-    }
-
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3RootFolder.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3RootFolder.java
new file mode 100644
index 0000000..99cde3b
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3RootFolder.java
@@ -0,0 +1,142 @@
+/**
+ * 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;
+
+import javax.mail.Folder; 
+import javax.mail.Message; 
+import javax.mail.MessagingException; 
+import javax.mail.MethodNotSupportedException;
+import javax.mail.Store; 
+
+import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection; 
+
+/**
+ * An POP3 folder instance for the root of POP3 folder tree.  This has 
+ * some of the folder operations disabled. 
+ */
+public class POP3RootFolder extends POP3Folder {
+    // the inbox folder is the only one that exists 
+    protected Folder inbox; 
+    
+    /**
+     * Create a default POP3RootFolder attached to a specific Store instance.
+     * 
+     * @param store  The Store instance this is the root for.
+     */
+    public POP3RootFolder(POP3Store store) {
+        // create a folder with a null string name and the default separator. 
+        super(store, ""); 
+        // this only holds folders 
+        folderType = HOLDS_FOLDERS; 
+        // this folder does exist
+        exists = true; 
+        // no messages in this folder 
+        msgCount = 0; 
+    }
+
+    
+    /**
+     * Get the parent.  This is the root folder, which 
+     * never has a parent. 
+     * 
+     * @return Always returns null. 
+     */
+    public Folder getParent() {
+        // we never have a parent folder 
+        return null; 
+    }
+
+    /**
+     * We have a separator because the root folder is "special". 
+     */
+    public char getSeparator() throws MessagingException {
+        return '/';
+    }
+    
+    /**
+     * Retrieve a list of folders that match a pattern.
+     * 
+     * @param pattern The match pattern.
+     * 
+     * @return An array of matching folders.
+     * @exception MessagingException
+     */
+    public Folder[] list(String pattern) throws MessagingException {
+        // I'm not sure this is correct, but the Sun implementation appears to 
+        // return a array containing the inbox regardless of what pattern was specified. 
+        return new Folder[] { getInbox() };
+    }
+    
+    /**
+     * Get a folder of a given name from the root folder.
+     * The Sun implementation seems somewhat inconsistent 
+     * here.  The docs for Store claim that only INBOX is 
+     * supported, but it will return a Folder instance for any 
+     * name.  On the other hand, the root folder raises 
+     * an exception for anything but the INBOX.
+     * 
+     * @param name   The folder name (which must be "INBOX".
+     * 
+     * @return The inbox folder instance. 
+     * @exception MessagingException
+     */
+    public Folder getFolder(String name) throws MessagingException {
+        if (!name.equalsIgnoreCase("INBOX")) {
+            throw new MessagingException("Only the INBOX folder is supported"); 
+        }
+        // return the inbox folder 
+        return getInbox(); 
+    }
+    
+    /**
+     * Override for the isOpen method.  The root folder can 
+     * never be opened. 
+     * 
+     * @return always returns false. 
+     */
+    public boolean isOpen() {
+        return false; 
+    }
+    
+    public void open(int mode) throws MessagingException {
+        throw new MessagingException("POP3 root folder cannot be opened"); 
+    }
+    
+    public void open(boolean expunge) throws MessagingException {
+        throw new MessagingException("POP3 root folder cannot be close"); 
+    }
+    
+    
+    /**
+     * Retrieve the INBOX folder from the root. 
+     * 
+     * @return The Folder instance for the inbox. 
+     * @exception MessagingException
+     */
+    protected Folder getInbox() throws MessagingException {
+        // we're the only place that creates folders, and 
+        // we only create the single instance. 
+        if (inbox == null) {
+            inbox = new POP3Folder((POP3Store)store, "INBOX"); 
+        }
+        return inbox; 
+    }
+}
+
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3SSLStore.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3SSLStore.java
new file mode 100644
index 0000000..67c254a
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3SSLStore.java
@@ -0,0 +1,43 @@
+/**
+ * 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;
+
+import javax.mail.Session;
+import javax.mail.URLName;
+
+/**
+ * POP3 implementation of javax.mail.Store over an SSL connection.
+ *
+ * @version $Rev$ $Date$
+ */
+public class POP3SSLStore extends POP3Store {
+    /**
+     * Construct an POP3SSLStore item.
+     *
+     * @param session The owning javamail Session.
+     * @param urlName The Store urlName, which can contain server target information.
+     */
+	public POP3SSLStore(Session session, URLName urlName) {
+        // we're the imaps protocol, our default connection port is 993, and we must use
+        // an SSL connection for the initial hookup 
+		super(session, urlName, "pop3s", DEFAULT_POP3_SSL_PORT, true);
+	}
+}
+
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
index 5caed89..913f356 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
@@ -18,6 +18,10 @@
  */
 
 package org.apache.geronimo.javamail.store.pop3;
+ 
+import java.io.PrintStream; 
+import java.util.LinkedList;
+import java.util.List;
 
 import javax.mail.AuthenticationFailedException;
 import javax.mail.Folder;
@@ -26,6 +30,10 @@
 import javax.mail.Store;
 import javax.mail.URLName;
 
+import org.apache.geronimo.javamail.store.pop3.connection.POP3Connection; 
+import org.apache.geronimo.javamail.store.pop3.connection.POP3ConnectionPool; 
+import org.apache.geronimo.javamail.util.ProtocolProperties;
+
 /**
  * POP3 implementation of javax.mail.Store POP protocol spec is implemented in
  * org.apache.geronimo.javamail.store.pop3.POP3Connection
@@ -34,16 +42,28 @@
  */
 
 public class POP3Store extends Store {
-
-    private POP3Connection pop3Con;
-
-    protected static final int DEFAULT_MAIL_POP3_PORT = 110;
-    private boolean sslConnection;
-    private int defaultPort;
+    protected static final int DEFAULT_POP3_PORT = 110;
+    protected static final int DEFAULT_POP3_SSL_PORT = 995;
     
-    private String protocol;
+    
+    // our accessor for protocol properties and the holder of 
+    // protocol-specific information 
+    protected ProtocolProperties props; 
+    // our connection object    
+    protected POP3ConnectionPool connectionPool; 
+    // our session provided debug output stream.
+    protected PrintStream debugStream;
+    // the debug flag 
+    protected boolean debug; 
+    // the root folder 
+    protected POP3RootFolder root; 
+    // until we're connected, we're closed 
+    boolean closedForBusiness = true; 
+    protected LinkedList openFolders = new LinkedList(); 
+    
+    
     public POP3Store(Session session, URLName name) {
-        this(session, name, "pop3", DEFAULT_MAIL_POP3_PORT, false);
+        this(session, name, "pop3", DEFAULT_POP3_PORT, false);
     }
 
     /**
@@ -68,173 +88,227 @@
      */
     protected POP3Store(Session session, URLName name, String protocol, int defaultPort, boolean sslConnection) {
         super(session, name);
-        this.protocol = protocol;
+        
+        // create the protocol property holder.  This gives an abstraction over the different 
+        // flavors of the protocol. 
+        props = new ProtocolProperties(session, protocol, sslConnection, defaultPort); 
 
-        // these are defaults based on what the superclass specifies.
-        this.sslConnection = sslConnection;
-        this.defaultPort = defaultPort;
-
-    }
-    /**
-     * @see javax.mail.Store#getDefaultFolder()
-     * 
-     * There is only INBOX supported in POP3 so the default folder is inbox
-     */
-    public Folder getDefaultFolder() throws MessagingException {
-        return getFolder("INBOX");
+        // get our debug settings
+        debugStream = session.getDebugOut();
+        debug = session.getDebug(); 
+        // the connection pool manages connections for the stores, folder, and message usage. 
+        connectionPool = new POP3ConnectionPool(this, props); 
     }
 
+
     /**
-     * @see javax.mail.Store#getFolder(java.lang.String)
+     * Return a Folder object that represents the root of the namespace for the current user.
+     *
+     * Note that in some store configurations (such as IMAP4) the root folder might
+     * not be the INBOX folder.
+     *
+     * @return the root Folder
+     * @throws MessagingException if there was a problem accessing the store
      */
-    public Folder getFolder(String name) throws MessagingException {
-
-        checkConnectionStatus();
-
-        if (!"INBOX".equalsIgnoreCase(name)) {
-            throw new MessagingException("Only INBOX is supported in POP3");
+	public Folder getDefaultFolder() throws MessagingException {
+		checkConnectionStatus();
+        // if no root yet, create a root folder instance. 
+        if (root == null) {
+            return new POP3RootFolder(this);
         }
-        return new POP3Folder(this, session, pop3Con);
-    }
+        return root;
+	}
 
     /**
-     * @see javax.mail.Store#getFolder(javax.mail.URLName)
+     * Return the Folder corresponding to the given name.
+     * The folder might not physically exist; the {@link Folder#exists()} method can be used
+     * to determine if it is real.
+     * 
+     * @param name   the name of the Folder to return
+     * 
+     * @return the corresponding folder
+     * @throws MessagingException
+     *                if there was a problem accessing the store
      */
-    public Folder getFolder(URLName url) throws MessagingException {
-        return getFolder(url.getFile());
-    }
+	public Folder getFolder(String name) throws MessagingException {
+        return getDefaultFolder().getFolder(name);
+	}
 
+    
+    /**
+     * Return the folder identified by the URLName; the URLName must refer to this Store.
+     * Implementations may use the {@link URLName#getFile()} method to determined the folder name.
+     * 
+     * @param url
+     * 
+     * @return the corresponding folder
+     * @throws MessagingException
+     *                if there was a problem accessing the store
+     */
+	public Folder getFolder(URLName url) throws MessagingException {
+        return getDefaultFolder().getFolder(url.getFile());
+	}
+
+    
     /**
      * @see javax.mail.Service#protocolConnect(java.lang.String, int,
      *      java.lang.String, java.lang.String)
      */
-    protected synchronized boolean protocolConnect(String host, int portNum, String user, String passwd)
-            throws MessagingException {
-
-        // Never store the user, passwd for security reasons
-
-        // if these values are null, no connection attempt should be made
-        if (host == null || passwd == null || user == null) {
-            return false;
+    protected synchronized boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
+        
+        if (debug) {
+            debugOut("Connecting to server " + host + ":" + port + " for user " + username);
         }
 
-        // validate port num
-        if (portNum < 1) {
-            String portstring = session.getProperty("mail.pop3.port");
-            if (portstring != null) {
+        // the connection pool handles all of the details here. 
+        if (connectionPool.protocolConnect(host, port, username, password)) 
+        {
+            // the store is now open 
+            closedForBusiness = false; 
+            return true; 
+        }
+        return false; 
+    }
+    
+    
+    protected POP3Connection getConnection() throws MessagingException {
+        return connectionPool.getConnection(); 
+    }
+    
+    protected void releaseConnection(POP3Connection connection) throws MessagingException {
+        connectionPool.releaseConnection(connection); 
+    }
+    
+    synchronized POP3Connection getFolderConnection(POP3Folder folder) throws MessagingException {
+        POP3Connection connection = connectionPool.getConnection(); 
+        openFolders.add(folder);
+        return connection; 
+    }
+    
+    synchronized void releaseFolderConnection(POP3Folder folder, POP3Connection connection) throws MessagingException {
+        openFolders.remove(folder); 
+        // a connection returned from a folder is no longer usable. Just close it and 
+        // let it drift off. 
+        connection.close(); 
+    }
+    
+    /**
+     * Close all open folders.  We have a small problem here with a race condition.  There's no safe, single
+     * synchronization point for us to block creation of new folders while we're closing.  So we make a copy of
+     * the folders list, close all of those folders, and keep repeating until we're done.
+     */
+    protected void closeOpenFolders() {
+        // we're no longer accepting additional opens.  Any folders that open after this point will get an
+        // exception trying to get a connection.
+        closedForBusiness = true;
+
+        while (true) {
+            List folders = null;
+
+            // grab our lock, copy the open folders reference, and null this out.  Once we see a null
+            // open folders ref, we're done closing.
+            synchronized(connectionPool) {
+                folders = openFolders;
+                openFolders = new LinkedList();
+            }
+
+            // null folder, we're done
+            if (folders.isEmpty()) {
+                return;
+            }
+            // now close each of the open folders.
+            for (int i = 0; i < folders.size(); i++) {
+                POP3Folder folder = (POP3Folder)folders.get(i);
                 try {
-                    portNum = Integer.parseInt(portstring);
-                } catch (NumberFormatException e) {
-                    portNum = defaultPort;
+                    folder.close(false);
+                } catch (MessagingException e) {
                 }
             }
         }
-
-        /*
-         * Obtaining a connection to the server.
-         * 
-         */
-        pop3Con = new POP3Connection(this.session, host, portNum, sslConnection, protocol);
-        try {
-            pop3Con.open();
-        } catch (Exception e) {
-            throw new MessagingException("Connection failed", e);
-        }
-
-        /*
-         * Sending the USER command with username
-         * 
-         */
-        POP3Response resUser = null;
-        try {
-            resUser = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_USER(user));
-        } catch (Exception e) {
-            throw new MessagingException("Connection failed", e);
-        }
-
-        if (POP3Constants.ERR == resUser.getStatus()) {
-
-            /*
-             * Authentication failed so sending QUIT
-             * 
-             */
-            try {
-                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_QUIT());
-            } catch (Exception e) {
-                // We don't care about the response or if any error happens
-                // just trying to comply with the spec.
-                // Most likely the server would have terminated the connection
-                // by now.
-            }
-
-            throw new AuthenticationFailedException(resUser.getFirstLine());
-        }
-
-        /*
-         * Sending the PASS command with password
-         * 
-         */
-        POP3Response resPwd = null;
-        try {
-            resPwd = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_PASS(passwd));
-        } catch (Exception e) {
-            throw new MessagingException("Connection failed", e);
-        }
-
-        if (POP3Constants.ERR == resPwd.getStatus()) {
-
-            /*
-             * Authentication failed so sending QUIT
-             * 
-             */
-            try {
-                pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_QUIT());
-            } catch (Exception e) {
-                // We don't care about the response or if any error happens
-                // just trying to comply with the spec.
-                // Most likely the server would have terminated the connection
-                // by now.
-            }
-
-            throw new AuthenticationFailedException(resPwd.getFirstLine());
-        }
-
-        return true;
     }
+    
 
     /**
      * @see javax.mail.Service#isConnected()
      */
     public boolean isConnected() {
-        POP3Response res = null;
         try {
-            res = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_NOOP());
-        } catch (Exception e) {
-            return false;
+            POP3Connection connection = getConnection(); 
+            try {
+                connection.pingServer(); 
+                return true; 
+            }
+            finally {
+                releaseConnection(connection); 
+            }
+        } catch (MessagingException e) {
         }
-
-        return (POP3Constants.OK == res.getStatus());
+        return false; 
     }
 
     /**
-     * @see javax.mail.Service#close()
+     * Close the store, and any open folders associated with the 
+     * store. 
+     * 
+     * @exception MessagingException
      */
-    public void close() throws MessagingException {
-        // This is done to ensure proper event notification.
-        super.close();
-        try {
-            pop3Con.close();
-        } catch (Exception e) {
-            // A message is already set at the connection level
-            // unfortuantely there is no constructor that takes only
-            // the root exception
-            new MessagingException("", e);
+	public synchronized void close() throws MessagingException{
+        // if already closed, nothing to do. 
+        if (closedForBusiness) {
+            return; 
         }
-    }
+        
+        // close the folders first, then shut down the Store. 
+        closeOpenFolders();
+        
+        connectionPool.close(); 
+        connectionPool = null; 
 
+		// make sure we do the superclass close operation first so 
+        // notification events get broadcast properly. 
+		super.close();
+	}
+
+    /**
+     * Check the status of our connection. 
+     * 
+     * @exception MessagingException
+     */
     private void checkConnectionStatus() throws MessagingException {
         if (!this.isConnected()) {
             throw new MessagingException("Not connected ");
         }
     }
+
+    /**
+     * Internal debug output routine.
+     *
+     * @param value  The string value to output.
+     */
+    void debugOut(String message) {
+        debugStream.println("POP3Store DEBUG: " + message);
+    }
+
+    /**
+     * Internal debugging routine for reporting exceptions.
+     *
+     * @param message A message associated with the exception context.
+     * @param e       The received exception.
+     */
+    void debugOut(String message, Throwable e) {
+        debugOut("Received exception -> " + message);
+        debugOut("Exception message -> " + e.getMessage());
+        e.printStackTrace(debugStream);
+    }
+    
+    /**
+     * Finalizer to perform IMAPStore() cleanup when 
+     * no longer in use. 
+     * 
+     * @exception Throwable
+     */
+    protected void finalize() throws Throwable {
+        super.finalize(); 
+        close(); 
+    }
 }
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
new file mode 100644
index 0000000..0b12a09
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Connection.java
@@ -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(); 
+    }
+}
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
new file mode 100644
index 0000000..8aa9c4b
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ConnectionPool.java
@@ -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; 
+    }
+}
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ListResponse.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
similarity index 85%
rename from geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ListResponse.java
rename to geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
index 448322a..d1b2066 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ListResponse.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3ListResponse.java
@@ -17,14 +17,15 @@
  * under the License.
  */
 
-package org.apache.geronimo.javamail.store.pop3.response;
+package org.apache.geronimo.javamail.store.pop3.connection;
 
-import java.util.Vector;
+import java.io.ByteArrayInputStream; 
+
+import java.util.ArrayList; 
+import java.util.List;     
 
 import javax.mail.MessagingException;
 
-import org.apache.geronimo.javamail.store.pop3.POP3Response;
-
 /**
  * This class adds functionality to the basic response by parsing the reply for
  * LIST command and obtaining specific information about the msgnum and the
@@ -37,13 +38,13 @@
  * @version $Rev$ $Date$
  */
 
-public class POP3ListResponse extends DefaultPOP3Response {
+public class POP3ListResponse extends POP3Response {
 
     private int msgnum = 0;
 
     private int size = 0;
 
-    private Vector multipleMsgs = null;
+    private List multipleMsgs = null;
 
     POP3ListResponse(POP3Response baseRes) throws MessagingException {
         super(baseRes.getStatus(), baseRes.getFirstLine(), baseRes.getData());
@@ -57,12 +58,12 @@
                 try {
                     msgnum = Integer.parseInt(args[0]);
                 } catch (NumberFormatException e) {
-                    throw new MessagingException("Invalid response for STAT command", 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 STAT command", e);
+                    throw new MessagingException("Invalid response for LIST command", e);
                 }
             } else {
                 int totalMsgs = 0;
@@ -70,10 +71,9 @@
                 try {
                     totalMsgs = Integer.parseInt(args[0]);
                 } catch (NumberFormatException e) {
-                    throw new MessagingException("Invalid response for STAT command", e);
+                    throw new MessagingException("Invalid response for LIST command", e);
                 }
-                multipleMsgs = new Vector(totalMsgs);
-                multipleMsgs.setSize(totalMsgs);
+                multipleMsgs = new ArrayList(totalMsgs);
                 // Todo : multi-line response parsing
             }
 
@@ -92,7 +92,7 @@
      * Messages can be accessed by multipleMsgs.getElementAt(msgnum)
      * 
      */
-    public Vector getMultipleMessageDetails() {
+    public List getMultipleMessageDetails() {
         return multipleMsgs;
     }
 
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
new file mode 100644
index 0000000..2351187
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3Response.java
@@ -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()); 
+    }
+
+}
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3StatusResponse.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
similarity index 91%
rename from geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3StatusResponse.java
rename to geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
index 4fceb84..dbd3e53 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3StatusResponse.java
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/connection/POP3StatusResponse.java
@@ -17,12 +17,10 @@
  * under the License.
  */
 
-package org.apache.geronimo.javamail.store.pop3.response;
+package org.apache.geronimo.javamail.store.pop3.connection;
 
 import javax.mail.MessagingException;
 
-import org.apache.geronimo.javamail.store.pop3.POP3Response;
-
 /**
  * This class adds functionality to the basic response by parsing the status
  * line and obtaining specific information about num of msgs and the size
@@ -33,7 +31,7 @@
  * @version $Rev$ $Date$
  */
 
-public class POP3StatusResponse extends DefaultPOP3Response {
+public class POP3StatusResponse extends POP3Response {
 
     private int numMessages = 0;
 
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3Message.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3Message.java
deleted file mode 100644
index c8183ec..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3Message.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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.message;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-
-import javax.mail.Flags;
-import javax.mail.Folder;
-import javax.mail.IllegalWriteException;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-import javax.mail.event.MessageChangedEvent;
-import javax.mail.internet.InternetHeaders;
-import javax.mail.internet.MimeMessage;
-
-import org.apache.geronimo.javamail.store.pop3.POP3CommandFactory;
-import org.apache.geronimo.javamail.store.pop3.POP3Connection;
-import org.apache.geronimo.javamail.store.pop3.POP3Folder;
-import org.apache.geronimo.javamail.store.pop3.POP3Response;
-import org.apache.geronimo.javamail.store.pop3.response.POP3ListResponse;
-import org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory;
-
-/**
- * POP3 implementation of javax.mail.internet.MimeMessage
- * 
- * Only the most basic information is given and Message objects created here is
- * a light-weight reference to the actual Message As per the JavaMail spec items
- * from the actual message will get filled up on demand
- * 
- * If some other items are obtained from the server as a result of one call,
- * then the other details are also processed and filled in. For ex if RETR is
- * called then header information will also be processed in addition to the
- * content
- * 
- * @version $Rev$ $Date$
- */
-public class POP3Message extends MimeMessage {
-
-    private POP3Connection pop3Con;
-
-    private int msgSize = -1;
-
-    private int headerSize = -1;
-
-    // We can't use header bcos it's already initialize to
-    // to an empty InternetHeader
-    private InputStream rawHeaders;
-
-    // used to force loading of headers again
-    private boolean loadHeaders = true;
-
-    // to get accessed to the debug setting and log
-    private Session session;
-
-    protected POP3Message(Folder folder, int msgnum, Session session, POP3Connection pop3Con) {
-        super(folder, msgnum);
-        this.pop3Con = pop3Con;
-        this.session = session;
-    }
-
-    /**
-     * @see javax.mail.internet.MimeMessage#getContentStream()
-     */
-    protected InputStream getContentStream() throws MessagingException {
-        POP3Response msgResponse = null;
-        try {
-            msgResponse = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_RETR(msgnum));
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        loadHeaders = true;
-        loadHeaders(msgResponse.getData());
-        loadContent(msgResponse.getData());
-
-        return contentStream;
-    }
-
-    public void setFlags(Flags newFlags, boolean set) throws MessagingException {
-        Flags oldFlags = (Flags) flags.clone();
-        super.setFlags(newFlags, set);
-
-        if (!flags.equals(oldFlags)) {
-            ((POP3Folder) folder).notifyMessageChangedListeners(MessageChangedEvent.FLAGS_CHANGED, this);
-        }
-    }
-
-    protected void loadHeaders(InputStream in) throws MessagingException {
-        if (loadHeaders || rawHeaders == null) {
-            rawHeaders = in;
-            headers = new InternetHeaders(rawHeaders);
-            loadHeaders = false;
-        }
-    }
-
-    protected void loadContent(InputStream stream) throws MessagingException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            int byteRead = stream.read();
-            int lastByte = -1;
-            for (; byteRead > 0;) {
-                if (byteRead == ' ' && lastByte == '\n') {
-                    break;
-                }
-                lastByte = byteRead;
-                byteRead = stream.read();
-            }
-
-            for (; stream.available() > 0;) {
-                out.write(stream.read());
-            }
-
-            contentStream = new ByteArrayInputStream(out.toByteArray());
-            msgSize = contentStream.available();
-
-        } catch (IOException e) {
-
-            throw new MessagingException("Error loading content info", e);
-        }
-    }
-
-    public int getSize() throws MessagingException {
-        if (msgSize >= 0) {
-            return msgSize;
-        }
-        try {
-
-            if (msgSize < 0) {
-                if (rawHeaders == null) {
-                    loadHeaders();
-                }
-                POP3ListResponse res = (POP3ListResponse) POP3ResponseFactory.getListResponse(pop3Con
-                        .sendCommand(POP3CommandFactory.getCOMMAND_LIST(msgnum)));
-                msgSize = res.getSize() - headerSize;
-            }
-            return msgSize;
-        } catch (MessagingException ex) {
-            throw new MessagingException("error getting size", ex);
-        }
-    }
-
-    /**
-     * notice that we pass zero as the no of lines from the message,as it
-     * doesn't serv any purpose to get only a certain number of lines.
-     * 
-     * However this maybe important if a mail client only shows 3 or 4 lines of
-     * the message in the list and then when the user clicks they would load the
-     * message on demand.
-     * 
-     */
-    protected void loadHeaders() throws MessagingException {
-        POP3Response msgResponse = null;
-        try {
-
-            msgResponse = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_TOP(msgnum, 0));
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        loadHeaders(msgResponse.getData());
-    }
-
-    /***************************************************************************
-     * Following is a set of methods that deal with headers I have tried to use
-     * the bare minimum
-     * 
-     * Used sun's POP3 impl & JavaMail API as a guide in decided which methods
-     * are important.
-     **************************************************************************/
-
-    public String[] getHeader(String name) throws MessagingException {
-        if (rawHeaders == null)
-            loadHeaders();
-        return headers.getHeader(name);
-    }
-
-    public String getHeader(String name, String delimiter) throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getHeader(name, delimiter);
-    }
-
-    public Enumeration getAllHeaders() throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getAllHeaders();
-    }
-
-    public Enumeration getMatchingHeaders(String[] names) throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getMatchingHeaders(names);
-    }
-
-    public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getNonMatchingHeaders(names);
-    }
-
-    public Enumeration getAllHeaderLines() throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getAllHeaderLines();
-    }
-
-    public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getMatchingHeaderLines(names);
-    }
-
-    public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
-        if (headers == null)
-            loadHeaders();
-        return headers.getNonMatchingHeaderLines(names);
-    }
-
-    // the following are overrides for header modification methods. These
-    // messages are read only,
-    // so the headers cannot be modified.
-    public void addHeader(String name, String value) throws MessagingException {
-        throw new IllegalWriteException("POP3 messages are read-only");
-    }
-
-    public void setHeader(String name, String value) throws MessagingException {
-        throw new IllegalWriteException("POP3 messages are read-only");
-    }
-
-    public void removeHeader(String name) throws MessagingException {
-        throw new IllegalWriteException("POP3 messages are read-only");
-    }
-
-    public void addHeaderLine(String line) throws MessagingException {
-        throw new IllegalWriteException("POP3 messages are read-only");
-    }
-
-    /**
-     * We cannot modify these messages
-     */
-    public void saveChanges() throws MessagingException {
-        throw new IllegalWriteException("POP3 messages are read-only");
-    }
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageFactory.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageFactory.java
deleted file mode 100644
index 7c8d493..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.message;
-
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-import javax.mail.internet.MimeMessage.RecipientType;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Connection;
-import org.apache.geronimo.javamail.store.pop3.POP3Folder;
-
-/**
- * Fctory class to create POP3Messages based on the fetch profile
- * 
- * @version $Rev$ $Date$
- */
-public final class POP3MessageFactory {
-
-    /**
-     * Creates a basic method with no items, the items will be loaded on demand
-     * 
-     * @param folder
-     * @param session
-     * @param pop3Con
-     * @param msgNum
-     * @return
-     */
-    public static Message createMessage(POP3Folder folder, Session session, POP3Connection pop3Con, int msgNum) {
-        return new POP3Message(folder, msgNum, session, pop3Con);
-    }
-
-    /**
-     * Created in response to <cpde>FetchProfile.ENVELOPE</code>
-     */
-    public static Message createMessageWithEvelope(POP3Message msg) throws MessagingException {
-        msg.getAllHeaders();
-        msg.getSender();
-        msg.getSentDate();
-        msg.getSubject();
-        msg.getReplyTo();
-        msg.getReceivedDate();
-        msg.getRecipients(RecipientType.TO);
-
-        return msg;
-    }
-
-    /**
-     * Created in response to <code>FetchProfile.CONTENT_INFO</code>
-     */
-    public static Message createMessageWithContentInfo(POP3Message msg) throws MessagingException {
-        msg.getContentType();
-        msg.getDisposition();
-        msg.getDescription();
-        msg.getSize();
-        msg.getLineCount();
-
-        return msg;
-    }
-
-    /**
-     * Created in response to <code>FetchProfile.FLAGS</code>
-     */
-    public static Message createMessageWithFlags(POP3Message msg) throws MessagingException {
-        msg.getFlags();
-        return msg;
-    }
-
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithContentInfo.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithContentInfo.java
deleted file mode 100644
index 17ca20d..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithContentInfo.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.message;
-
-import javax.mail.Folder;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Connection;
-
-/**
- * light-weight Message object will be created in response to
- * FetchProfile.CONTENT_INFO other details will be filled on demand *
- * 
- * @version $Rev$ $Date$
- * 
- */
-
-public class POP3MessageWithContentInfo extends POP3Message {
-
-    public POP3MessageWithContentInfo(Folder folder, int msgnum, Session session, POP3Connection pop3Con)
-            throws MessagingException {
-        super(folder, msgnum, null, pop3Con);
-        this.getContentType();
-        this.getDisposition();
-        this.getDescription();
-        this.getSize();
-        this.getLineCount();
-    }
-
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithEnvelope.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithEnvelope.java
deleted file mode 100644
index bc05d39..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithEnvelope.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.message;
-
-import javax.mail.Folder;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Connection;
-
-/**
- * light-weight Message object will be created in response to
- * FetchProfile.ENVELOPE other details will be filled on demand *
- * 
- * @version $Rev$ $Date$
- */
-
-public class POP3MessageWithEnvelope extends POP3Message {
-
-    protected POP3MessageWithEnvelope(Folder folder, int msgnum, Session session, POP3Connection pop3Con)
-            throws MessagingException {
-        super(folder, msgnum, session, pop3Con);
-        this.getAllHeaders();
-        this.getSender();
-        this.getSentDate();
-        this.getSubject();
-        this.getReplyTo();
-        this.getReceivedDate();
-        this.getRecipients(RecipientType.TO);
-    }
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithFlags.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithFlags.java
deleted file mode 100644
index 2c6ac64..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithFlags.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.message;
-
-import javax.mail.Folder;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Connection;
-
-/**
- * light-weight Message object will be created in response to FetchProfile.FLAGS
- * other details will be filled on demand *
- * 
- * @version $Rev$ $Date$
- */
-
-public class POP3MessageWithFlags extends POP3Message {
-
-    protected POP3MessageWithFlags(Folder folder, int msgnum, Session session, POP3Connection pop3Con)
-            throws MessagingException {
-        super(folder, msgnum, session, pop3Con);
-        this.getFlags();
-    }
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/DefaultPOP3Response.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/DefaultPOP3Response.java
deleted file mode 100644
index 43e33ed..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/DefaultPOP3Response.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.response;
-
-import java.io.InputStream;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Constants;
-import org.apache.geronimo.javamail.store.pop3.POP3Response;
-
-/**
- * This class provides the basic implementation for the POP3Response.
- * 
- * @see org.apache.geronimo.javamail.store.pop3.POP3Response
- * @version $Rev$ $Date$
- */
-
-public class DefaultPOP3Response implements POP3Response, POP3Constants {
-
-    private int status = ERR;
-
-    private String firstLine;
-
-    private InputStream data;
-
-    DefaultPOP3Response(int status, String firstLine, InputStream data) {
-        this.status = status;
-        this.firstLine = firstLine;
-        this.data = data;
-    }
-
-    public int getStatus() {
-        return status;
-    }
-
-    public InputStream getData() {
-        return data;
-    }
-
-    public String getFirstLine() {
-        return firstLine;
-    }
-
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ResponseFactory.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ResponseFactory.java
deleted file mode 100644
index 5412746..0000000
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/response/POP3ResponseFactory.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.response;
-
-import java.io.InputStream;
-
-import javax.mail.MessagingException;
-
-import org.apache.geronimo.javamail.store.pop3.POP3Constants;
-import org.apache.geronimo.javamail.store.pop3.POP3Response;
-
-/**
- * This factory provides a uniform way of handling the creation of response
- * objects.
- * 
- * @version $Rev$ $Date$
- */
-
-public final class POP3ResponseFactory implements POP3Constants {
-
-    public static POP3Response getDefaultResponse(int status, String line, InputStream data) {
-        return new DefaultPOP3Response(status, line, data);
-    }
-
-    public static POP3Response getStatusResponse(POP3Response baseRes) throws MessagingException {
-        return new POP3StatusResponse(baseRes);
-    }
-
-    public static POP3Response getListResponse(POP3Response baseRes) throws MessagingException {
-        return new POP3StatusResponse(baseRes);
-    }
-
-}
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
new file mode 100644
index 0000000..5241e78
--- /dev/null
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/util/MIMEInputReader.java
@@ -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 
+     }
+}
+
diff --git a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers
index 15287a7..80f342e 100644
--- a/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers
+++ b/geronimo-javamail_1.4/geronimo-javamail_1.4_provider/src/main/resources/META-INF/javamail.default.providers
@@ -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