mirror of
https://github.com/moparisthebest/davmail
synced 2025-02-28 09:21:49 -05:00
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:
parent
263826ce9a
commit
a38055b5ea
@ -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) {
|
||||
|
@ -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\"" +
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user