2008-10-31 13:12:30 -04:00
|
|
|
package davmail.exchange;
|
|
|
|
|
|
|
|
import davmail.Settings;
|
2008-11-03 20:47:10 -05:00
|
|
|
import davmail.http.DavGatewayHttpClientFacade;
|
2008-10-31 13:12:30 -04:00
|
|
|
import org.apache.commons.httpclient.HttpClient;
|
|
|
|
import org.apache.commons.httpclient.HttpMethod;
|
|
|
|
import org.apache.commons.httpclient.HttpStatus;
|
|
|
|
import org.apache.commons.httpclient.methods.GetMethod;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.net.NetworkInterface;
|
|
|
|
import java.net.SocketException;
|
|
|
|
import java.net.UnknownHostException;
|
2008-12-04 06:50:31 -05:00
|
|
|
import java.util.*;
|
2008-10-31 13:12:30 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create ExchangeSession instances.
|
|
|
|
*/
|
2008-12-17 10:31:08 -05:00
|
|
|
public final class ExchangeSessionFactory {
|
2008-12-04 06:50:31 -05:00
|
|
|
private static final Object LOCK = new Object();
|
|
|
|
private static final Map<PoolKey, ExchangeSessionStack> poolMap = new HashMap<PoolKey, ExchangeSessionStack>();
|
|
|
|
|
|
|
|
static class PoolKey {
|
2008-12-17 10:31:08 -05:00
|
|
|
public final String url;
|
|
|
|
public final String userName;
|
|
|
|
public final String password;
|
2008-12-04 06:50:31 -05:00
|
|
|
|
|
|
|
public PoolKey(String url, String userName, String password) {
|
|
|
|
this.url = url;
|
|
|
|
this.userName = userName;
|
|
|
|
this.password = password;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object object) {
|
|
|
|
return object == this ||
|
|
|
|
object instanceof PoolKey &&
|
|
|
|
((PoolKey) object).url.equals(this.url) &&
|
|
|
|
((PoolKey) object).userName.equals(this.userName) &&
|
|
|
|
((PoolKey) object).password.equals(this.password);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
return url.hashCode() + userName.hashCode() + password.hashCode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
2008-12-08 08:49:21 -05:00
|
|
|
pop();
|
2008-12-04 06:50:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-05 09:53:38 -05:00
|
|
|
private ExchangeSessionFactory() {
|
|
|
|
}
|
|
|
|
|
2008-10-31 13:12:30 -04:00
|
|
|
/**
|
|
|
|
* Create authenticated Exchange session
|
|
|
|
*
|
|
|
|
* @param userName user login
|
|
|
|
* @param password user password
|
|
|
|
* @return authenticated session
|
|
|
|
* @throws java.io.IOException on error
|
|
|
|
*/
|
|
|
|
public static ExchangeSession getInstance(String userName, String password) throws IOException {
|
|
|
|
try {
|
2008-12-04 06:50:31 -05:00
|
|
|
String baseUrl = Settings.getProperty("davmail.url");
|
|
|
|
PoolKey poolKey = new PoolKey(baseUrl, userName, password);
|
|
|
|
|
|
|
|
ExchangeSession session = null;
|
|
|
|
synchronized (LOCK) {
|
|
|
|
Stack<ExchangeSession> sessionStack = poolMap.get(poolKey);
|
|
|
|
if (sessionStack != null && !sessionStack.isEmpty()) {
|
|
|
|
session = sessionStack.pop();
|
|
|
|
ExchangeSession.LOGGER.debug("Got session " + session + " from pool");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session != null && session.isExpired()) {
|
|
|
|
ExchangeSession.LOGGER.debug("Session " + session + " expired");
|
|
|
|
session = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session == null) {
|
|
|
|
session = new ExchangeSession(poolKey);
|
|
|
|
session.login();
|
|
|
|
ExchangeSession.LOGGER.debug("Created new session: " + session);
|
|
|
|
}
|
2008-10-31 13:12:30 -04:00
|
|
|
return session;
|
|
|
|
} catch (IOException e) {
|
|
|
|
if (checkNetwork()) {
|
|
|
|
throw e;
|
|
|
|
} else {
|
2008-11-24 07:35:58 -05:00
|
|
|
throw new NetworkDownException("All network interfaces down !");
|
2008-10-31 13:12:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-04 06:50:31 -05:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
2008-12-08 08:49:21 -05:00
|
|
|
// keep httpClient
|
2008-12-04 06:50:31 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-31 13:12:30 -04:00
|
|
|
|
|
|
|
public static void checkConfig() throws IOException {
|
2008-11-03 20:47:10 -05:00
|
|
|
String url = Settings.getProperty("davmail.url");
|
2008-11-30 13:05:36 -05:00
|
|
|
HttpClient httpClient = DavGatewayHttpClientFacade.getInstance();
|
2008-11-03 20:47:10 -05:00
|
|
|
HttpMethod testMethod = new GetMethod(url);
|
2008-10-31 13:12:30 -04:00
|
|
|
try {
|
|
|
|
// get webmail root url (will not follow redirects)
|
|
|
|
testMethod.setFollowRedirects(false);
|
2008-11-04 05:37:36 -05:00
|
|
|
testMethod.setDoAuthentication(false);
|
2008-10-31 13:12:30 -04:00
|
|
|
int status = httpClient.executeMethod(testMethod);
|
|
|
|
ExchangeSession.LOGGER.debug("Test configuration status: " + status);
|
|
|
|
if (status != HttpStatus.SC_OK && status != HttpStatus.SC_UNAUTHORIZED
|
2008-12-22 19:14:41 -05:00
|
|
|
&& status != HttpStatus.SC_MOVED_TEMPORARILY && status != HttpStatus.SC_MOVED_PERMANENTLY) {
|
2008-10-31 13:12:30 -04:00
|
|
|
throw new IOException("Unable to connect to OWA at " + url + ", status code " +
|
|
|
|
status + ", check configuration");
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (UnknownHostException exc) {
|
2008-11-03 05:56:57 -05:00
|
|
|
String message = "DavMail configuration exception: \n";
|
2008-10-31 13:12:30 -04:00
|
|
|
if (checkNetwork()) {
|
2008-11-03 05:56:57 -05:00
|
|
|
message += "Unknown host " + exc.getMessage();
|
2008-11-24 07:35:58 -05:00
|
|
|
ExchangeSession.LOGGER.error(message, exc);
|
|
|
|
throw new IOException(message);
|
2008-10-31 13:12:30 -04:00
|
|
|
} else {
|
2008-12-17 10:31:08 -05:00
|
|
|
message = "All network interfaces down !";
|
|
|
|
ExchangeSession.LOGGER.error(message);
|
2008-11-24 07:35:58 -05:00
|
|
|
throw new NetworkDownException(message);
|
2008-10-31 13:12:30 -04:00
|
|
|
}
|
|
|
|
|
2008-11-24 07:35:58 -05:00
|
|
|
} catch (NetworkDownException exc) {
|
|
|
|
throw exc;
|
2008-10-31 13:12:30 -04:00
|
|
|
} catch (Exception exc) {
|
|
|
|
ExchangeSession.LOGGER.error("DavMail configuration exception: \n" + exc.getMessage(), exc);
|
2008-11-03 05:56:57 -05:00
|
|
|
throw new IOException("DavMail configuration exception: \n" + exc.getMessage());
|
2008-11-03 20:47:10 -05:00
|
|
|
} finally {
|
|
|
|
testMethod.releaseConnection();
|
2008-10-31 13:12:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if at least one network interface is up and active (i.e. has an address)
|
2008-11-03 05:56:57 -05:00
|
|
|
*
|
2008-10-31 13:12:30 -04:00
|
|
|
* @return true if network available
|
|
|
|
*/
|
|
|
|
protected static boolean checkNetwork() {
|
|
|
|
boolean up = false;
|
|
|
|
Enumeration<NetworkInterface> enumeration;
|
|
|
|
try {
|
|
|
|
enumeration = NetworkInterface.getNetworkInterfaces();
|
|
|
|
while (!up && enumeration.hasMoreElements()) {
|
|
|
|
NetworkInterface networkInterface = enumeration.nextElement();
|
|
|
|
up = networkInterface.isUp() && !networkInterface.isLoopback()
|
|
|
|
&& networkInterface.getInetAddresses().hasMoreElements();
|
|
|
|
}
|
2008-11-03 05:56:57 -05:00
|
|
|
} catch (NoSuchMethodError error) {
|
|
|
|
ExchangeSession.LOGGER.debug("Unable to test network interfaces (not available under Java 1.5)");
|
|
|
|
up = true;
|
2008-10-31 13:12:30 -04:00
|
|
|
} catch (SocketException exc) {
|
|
|
|
ExchangeSession.LOGGER.error("DavMail configuration exception: \n Error listing network interfaces " + exc.getMessage(), exc);
|
|
|
|
}
|
|
|
|
return up;
|
|
|
|
}
|
2008-12-08 08:49:21 -05:00
|
|
|
|
|
|
|
public static void reset() {
|
|
|
|
poolMap.clear();
|
|
|
|
}
|
2008-10-31 13:12:30 -04:00
|
|
|
}
|