GERONIMO-4241 NPE when calling folder.getDeletedMessageCount() for POP3 store
Optimize thread pool usage to only use a single connection for single-threaded operation.
git-svn-id: https://svn.apache.org/repos/asf/geronimo/javamail/trunk/geronimo-javamail_1.4@689140 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java b/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
index 6e59064..8fcfb4a 100644
--- a/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
+++ b/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java
@@ -53,8 +53,6 @@
protected int mode;
- protected POP3Connection currentConnection;
-
protected int msgCount;
private POP3Message[] messageCache;
@@ -199,15 +197,11 @@
// Can only be performed on a closed folder
checkClosed();
+ // get a connection object
+ POP3Connection connection = getConnection();
+
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 = currentConnection.retrieveMailboxStatus();
+ POP3StatusResponse res = connection.retrieveMailboxStatus();
this.mode = mode;
this.isFolderOpen = true;
this.msgCount = res.getNumMessages();
@@ -221,6 +215,10 @@
} catch (Exception e) {
throw new MessagingException("Unable to execute STAT command", e);
}
+ finally {
+ // return the connection when finished
+ releaseConnection(connection);
+ }
notifyConnectionListeners(ConnectionEvent.OPENED);
}
@@ -235,14 +233,19 @@
public void close(boolean expunge) throws MessagingException {
// Can only be performed on an open folder
checkOpen();
+
+ // get a connection object
+ POP3Connection connection = getConnection();
try {
// 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();
+ connection.reset();
// clean up any messages marked for deletion
- expungeDeletedMessages();
+ expungeDeletedMessages(connection);
} finally {
+ // return the connection when finished
+ releaseConnection(connection);
// cleanup the the state even if exceptions occur when deleting the
// messages.
cleanupFolder(false);
@@ -251,11 +254,11 @@
/**
* Mark any messages we've flagged as deleted from the
- * IMAP server before closing.
+ * POP3 server before closing.
*
* @exception MessagingException
*/
- protected void expungeDeletedMessages() throws MessagingException {
+ protected void expungeDeletedMessages(POP3Connection connection) throws MessagingException {
if (mode == READ_WRITE) {
for (int i = 0; i < messageCache.length; i++) {
POP3Message msg = messageCache[i];
@@ -265,7 +268,7 @@
// origin 1 value
if (msg.isSet(Flags.Flag.DELETED)) {
try {
- currentConnection.deleteMessage(i + 1);
+ connection.deleteMessage(i + 1);
} catch (MessagingException e) {
throw new MessagingException("Exception deleting message number " + (i + 1), e);
}
@@ -292,20 +295,6 @@
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);
}
@@ -319,15 +308,9 @@
* @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;
+ // we always get one from the store. If we're fully single threaded, then
+ // we can get away with just a single one.
+ return getConnection();
}
@@ -339,7 +322,8 @@
* @exception MessagingException
*/
void releaseMessageConnection(POP3Connection connection) throws MessagingException {
- // This is a NOP for this folder type.
+ // give this back to the store
+ releaseConnection(connection);
}
public boolean isOpen() {
@@ -503,4 +487,29 @@
super.notifyMessageChangedListeners(type, m);
}
+
+ /**
+ * Retrieve the connection attached to this folder. Throws an
+ * exception if we don't have an active connection.
+ *
+ * @return The current connection object.
+ * @exception MessagingException
+ */
+ protected synchronized POP3Connection getConnection() throws MessagingException {
+ // request a connection from the central store.
+ return ((POP3Store)store).getFolderConnection(this);
+ }
+
+
+ /**
+ * Release our connection back to the Store.
+ *
+ * @param connection The connection to release.
+ *
+ * @exception MessagingException
+ */
+ protected void releaseConnection(POP3Connection connection) throws MessagingException {
+ // we need to release the connection to the Store once we're finished with it
+ ((POP3Store)store).releaseFolderConnection(this, connection);
+ }
}
diff --git a/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java b/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
index 0778430..1c9d69e 100644
--- a/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
+++ b/geronimo-javamail_1.4_provider/src/main/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java
@@ -171,25 +171,55 @@
}
+ /**
+ * Get a connection for the store.
+ *
+ * @return The request connection object.
+ * @exception MessagingException
+ */
protected POP3Connection getConnection() throws MessagingException {
return connectionPool.getConnection();
}
+ /**
+ * Return a connection back to the connection pool after
+ * it has been used for a request.
+ *
+ * @param connection The return connection.
+ *
+ * @exception MessagingException
+ */
protected void releaseConnection(POP3Connection connection) throws MessagingException {
connectionPool.releaseConnection(connection);
}
+ /**
+ * Get a connection object for a folder to use.
+ *
+ * @param folder The requesting folder (always the inbox for POP3).
+ *
+ * @return An active POP3Connection.
+ * @exception MessagingException
+ */
synchronized POP3Connection getFolderConnection(POP3Folder folder) throws MessagingException {
POP3Connection connection = connectionPool.getConnection();
openFolders.add(folder);
return connection;
}
+ /**
+ * Release a connection object after a folder is
+ * finished with a request.
+ *
+ * @param folder The requesting folder.
+ * @param connection
+ *
+ * @exception MessagingException
+ */
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();
+ // return this back to the pool
+ connectionPool.releaseConnection(connection);
}
/**