Make ExchangeSession thread safe and replace stack pool with simple instance pool

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@458 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2009-03-19 08:58:55 +00:00
parent 263826ce9a
commit a38055b5ea
4 changed files with 22 additions and 89 deletions

View File

@ -163,7 +163,6 @@ public class AbstractConnection extends Thread {
} catch (IOException e2) {
DavGatewayTray.warn("Exception closing client socket", e2);
}
ExchangeSessionFactory.close(session);
}
protected String base64Encode(String value) {

View File

@ -86,13 +86,6 @@ public class ExchangeSession {
PRIORITIES.put("2", "1 (Highest)");
}
/**
* Date parser/formatter from Exchange format
*/
private final SimpleDateFormat dateFormatter;
private final SimpleDateFormat dateParser;
/**
* Various standard mail boxes Urls
*/
@ -127,17 +120,15 @@ public class ExchangeSession {
*/
ExchangeSession(ExchangeSessionFactory.PoolKey poolKey) {
this.poolKey = poolKey;
// SimpleDateFormat are not thread safe, need to create one instance for
// each session
dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
dateFormatter.setTimeZone(GMT_TIMEZONE);
dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
dateParser.setTimeZone(GMT_TIMEZONE);
LOGGER.debug("Session " + this + " created");
}
protected String formatDate(Date date) {
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
dateFormatter.setTimeZone(GMT_TIMEZONE);
return dateFormatter.format(date);
}
public boolean isExpired() {
boolean isExpired = false;
try {
@ -727,7 +718,7 @@ public class ExchangeSession {
String searchRequest = "Select \"DAV:uid\"" +
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
" WHERE \"DAV:isfolder\" = False\n" +
" AND \"DAV:getlastmodified\" < '" + dateFormatter.format(cal.getTime()) + "'\n";
" AND \"DAV:getlastmodified\" < '" + formatDate(cal.getTime()) + "'\n";
Enumeration folderEnum = DavGatewayHttpClientFacade.executeSearchMethod(
httpClient, URIUtil.encodePath(folderUrl), searchRequest);
@ -1196,7 +1187,7 @@ public class ExchangeSession {
if (caldavPastDelay != Integer.MAX_VALUE) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, -caldavPastDelay);
dateCondition = " AND \"urn:schemas:calendar:dtstart\" > '" + dateFormatter.format(cal.getTime()) + "'\n";
dateCondition = " AND \"urn:schemas:calendar:dtstart\" > '" + formatDate(cal.getTime()) + "'\n";
}
String searchQuery = "Select \"DAV:getetag\"" +

View File

@ -18,7 +18,7 @@ import java.util.*;
*/
public final class ExchangeSessionFactory {
private static final Object LOCK = new Object();
private static final Map<PoolKey, ExchangeSessionStack> poolMap = new HashMap<PoolKey, ExchangeSessionStack>();
private static final Map<PoolKey, ExchangeSession> poolMap = new HashMap<PoolKey, ExchangeSession>();
static class PoolKey {
public final String url;
@ -46,34 +46,6 @@ public final class ExchangeSessionFactory {
}
}
static class ExchangeSessionStack extends Stack<ExchangeSession> {
// 15 minutes expire delay
protected static final long EXPIRE_DELAY = 1000 * 60 * 15;
protected long timestamp = System.currentTimeMillis();
@Override
public ExchangeSession pop() throws EmptyStackException {
timestamp = System.currentTimeMillis();
return super.pop();
}
@Override
public ExchangeSession push(ExchangeSession session) {
timestamp = System.currentTimeMillis();
return super.push(session);
}
public boolean isExpired() {
return (System.currentTimeMillis() - timestamp) > EXPIRE_DELAY;
}
public void clean() {
while (!isEmpty()) {
pop();
}
}
}
private ExchangeSessionFactory() {
}
@ -90,18 +62,21 @@ public final class ExchangeSessionFactory {
String baseUrl = Settings.getProperty("davmail.url");
PoolKey poolKey = new PoolKey(baseUrl, userName, password);
ExchangeSession session = null;
ExchangeSession session;
synchronized (LOCK) {
Stack<ExchangeSession> sessionStack = poolMap.get(poolKey);
if (sessionStack != null && !sessionStack.isEmpty()) {
session = sessionStack.pop();
ExchangeSession.LOGGER.debug("Got session " + session + " from pool");
}
session = poolMap.get(poolKey);
}
if (session != null) {
ExchangeSession.LOGGER.debug("Got session " + session + " from cache");
}
if (session != null && session.isExpired()) {
ExchangeSession.LOGGER.debug("Session " + session + " expired");
session = null;
// expired session, remove from cache
synchronized (LOCK) {
poolMap.remove(poolKey);
}
}
if (session == null) {
@ -109,6 +84,10 @@ public final class ExchangeSessionFactory {
session.login();
ExchangeSession.LOGGER.debug("Created new session: " + session);
}
// successfull login, put session in cache
synchronized (LOCK) {
poolMap.put(poolKey, session);
}
return session;
} catch (IOException e) {
if (checkNetwork()) {
@ -119,41 +98,6 @@ public final class ExchangeSessionFactory {
}
}
/**
* Close (or pool) session.
*
* @param session exchange session
*/
public static void close(ExchangeSession session) {
synchronized (LOCK) {
if (session != null) {
PoolKey poolKey = session.getPoolKey();
ExchangeSessionStack sessionStack = poolMap.get(poolKey);
if (sessionStack == null) {
sessionStack = new ExchangeSessionStack();
poolMap.put(poolKey, sessionStack);
}
// keep httpClient
sessionStack.push(session);
ExchangeSession.LOGGER.debug("Pooled session: " + session);
}
// clean pool
List<PoolKey> toDeleteKeys = new ArrayList<PoolKey>();
for (Map.Entry<PoolKey, ExchangeSessionStack> entry : poolMap.entrySet()) {
if (entry.getValue().isExpired()) {
ExchangeSession.LOGGER.debug("Session pool for " + entry.getKey().userName + " expired");
entry.getValue().clean();
toDeleteKeys.add(entry.getKey());
}
}
for (PoolKey toDeleteKey : toDeleteKeys) {
poolMap.remove(toDeleteKey);
}
}
}
public static void checkConfig() throws IOException {
String url = Settings.getProperty("davmail.url");
HttpClient httpClient = DavGatewayHttpClientFacade.getInstance();

View File

@ -413,7 +413,6 @@ public class LdapConnection extends AbstractConnection {
} else if (requestOperation == LDAP_REQ_UNBIND) {
DavGatewayTray.debug("LDAP_REQ_UNBIND " + currentMessageId);
if (session != null) {
ExchangeSessionFactory.close(session);
session = null;
}
} else if (requestOperation == LDAP_REQ_SEARCH) {