/*****************************************************************************
* Copyright (c) 2006-2007, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
*****************************************************************************/
package org.eclipse.buckminster.jnlp.distroprovider.cloudsmith;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.eclipse.buckminster.core.helpers.CryptoUtils;
import org.eclipse.buckminster.jnlp.distroprovider.IRemoteDistroProvider;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.jabsorb.client.Client;
import org.jabsorb.client.ErrorResponse;
import org.jabsorb.client.HTTPSession;
import org.jabsorb.client.TransportRegistry;
/**
* @author Karel Brezina
*
*/
public class DistroProvider implements IRemoteDistroProvider
{
abstract class MethodWrapper<T>
{
abstract public T process() throws Exception;
public T run() throws Exception
{
if(m_currentStatus == AuthenticationStatus.BEFORE_INIT && m_remoteAccountService == null)
{
throw new Exception("Authenticator is not initialized - initialize method needs to be called");
}
try
{
return process();
}
catch(ErrorResponse e)
{
try
{
refresh();
return process();
}
catch(ErrorResponse e1)
{
throw new Exception("Cannot connect to the remote authentication service", e1);
}
}
}
}
private enum AuthenticationStatus
{
BEFORE_INIT, AFTER_INIT, AFTER_LOGIN
}
private static final String ACCOUNTSERVICE_BRIDGE_URL_SUFFIX = "json-rpc-bridge/accountService";
private static final String ACCOUNTSERVICE_URL_SUFFIX = "json-rpc/accountService";
private static final String DISTROSERVICE_BRIDGE_URL_SUFFIX = "json-rpc-bridge/distroService";
private static final String DISTROSERVICE_URL_SUFFIX = "json-rpc/distroService";
private static final String ENCRYPT_ALGORITHM = "SHA-256";
private AuthenticationStatus m_currentStatus = AuthenticationStatus.BEFORE_INIT;
private String m_lastLoginUserName;
private String m_lastLoginPassword;
private String m_lastLoginKey;
private LoginResponse m_lastLoginResponse;
private String m_serviceURL;
private IAccountService m_remoteAccountService = null;
private IDistroService m_remoteDistroService = null;
private HttpClient m_httpClient;
public int checkFolderReadAccess(final String folderPath) throws Exception
{
MethodWrapper<Integer> method = new MethodWrapper<Integer>()
{
@Override
public Integer process() throws Exception
{
return Integer.valueOf(m_remoteAccountService.checkFolderReadAccess(folderPath));
}
};
return method.run().intValue();
}
public IRemoteDistroProvider createDuplicate(boolean login) throws Exception
{
DistroProvider authenticator = new DistroProvider();
authenticator.initialize(m_serviceURL);
if(m_currentStatus == AuthenticationStatus.AFTER_LOGIN && login)
{
if(m_lastLoginKey != null)
authenticator.login(m_lastLoginKey);
else
authenticator.login(m_lastLoginUserName, m_lastLoginPassword);
}
return authenticator;
}
public String getCurrenlyLoggedUserName()
{
return m_lastLoginResponse == null
? null
: m_lastLoginResponse.getUserName();
}
public Properties getDistroP2Properties(final boolean draft, final Long cspecId, final IProgressMonitor monitor)
throws Exception
{
MethodWrapper<Properties> method = new MethodWrapper<Properties>()
{
@Override
public Properties process() throws Exception
{
Properties properties = new Properties();
try
{
monitor.beginTask(null, IProgressMonitor.UNKNOWN);
monitor.subTask("Starting distro resolution");
int lastWorked = 0;
try
{
m_remoteDistroService.fireDistroResolution(draft, cspecId);
}
catch(Exception e)
{
throw BuckminsterException.wrap(e);
}
IProgressInfo progressInfo = null;
while(progressInfo == null || !progressInfo.isDone())
{
try
{
Thread.sleep(500);
}
catch(InterruptedException i)
{
}
progressInfo = m_remoteDistroService.getProgressInfo();
String message = progressInfo.getMessage();
int worked = progressInfo.getWorked() * 100;
monitor.subTask(message);
monitor.worked(worked - lastWorked);
lastWorked = worked;
if(monitor.isCanceled())
{
m_remoteDistroService.cancel();
throw new InterruptedException();
}
}
try
{
Map<String, String> remoteProperties = m_remoteDistroService.getDistroP2Properties();
if(remoteProperties != null)
properties.putAll(remoteProperties);
}
catch(Exception e)
{
throw BuckminsterException.wrap(e);
}
}
finally
{
monitor.done();
}
return properties;
}
};
return method.run();
}
public HttpClient getHttpClient()
{
return m_httpClient;
}
public String getLoginKey() throws Exception
{
MethodWrapper<String> method = new MethodWrapper<String>()
{
@Override
public String process() throws Exception
{
return m_remoteAccountService.getLoginKey();
}
};
return method.run();
}
public void initialize(String serviceURL) throws Exception
{
if(serviceURL == null)
{
throw new Exception("Service URL is missing");
}
m_serviceURL = serviceURL;
m_httpClient = new HttpClient();
HttpState httpState = new HttpState();
m_httpClient.setState(httpState);
GetMethod method = null;
// initialization of account service
try
{
method = new GetMethod(serviceURL + ACCOUNTSERVICE_BRIDGE_URL_SUFFIX);
int status = m_httpClient.executeMethod(method);
if(status != HttpStatus.SC_OK)
throw new IOException(
"Setup did not succeed - make sure the AccountServiceServlet servlet is running on "
+ serviceURL);
}
finally
{
if(method != null)
method.releaseConnection();
}
TransportRegistry registry = new TransportRegistry();
HTTPSession.register(registry);
HTTPSession session = (HTTPSession)registry.createSession(serviceURL + ACCOUNTSERVICE_URL_SUFFIX);
// Pass the the session set up earlier
session.setState(httpState);
Client jsonClient = new Client(session);
m_remoteAccountService = (IAccountService)jsonClient.openProxy("accountService", IAccountService.class);
m_currentStatus = AuthenticationStatus.AFTER_INIT;
// initialization of distro service
try
{
method = new GetMethod(serviceURL + DISTROSERVICE_BRIDGE_URL_SUFFIX);
int status = m_httpClient.executeMethod(method);
if(status != HttpStatus.SC_OK)
throw new IOException(
"Setup did not succeed - make sure the DistroServiceServlet servlet is running on "
+ serviceURL);
}
finally
{
if(method != null)
method.releaseConnection();
}
session = (HTTPSession)registry.createSession(serviceURL + DISTROSERVICE_URL_SUFFIX);
// Pass the the session set up earlier
session.setState(httpState);
jsonClient = new Client(session);
m_remoteDistroService = (IDistroService)jsonClient.openProxy("distroService", IDistroService.class);
}
public boolean isLoggedIn() throws Exception
{
MethodWrapper<Boolean> method = new MethodWrapper<Boolean>()
{
@Override
public Boolean process() throws Exception
{
return Boolean.valueOf(m_remoteAccountService.isLoggedIn());
}
};
return method.run().booleanValue();
}
public void keepAlive() throws Exception
{
MethodWrapper<Boolean> method = new MethodWrapper<Boolean>()
{
@Override
public Boolean process() throws Exception
{
m_remoteAccountService.keepAlive();
return Boolean.valueOf(true);
}
};
method.run();
}
public int login(final String loginKey) throws Exception
{
MethodWrapper<LoginResponse> method = new MethodWrapper<LoginResponse>()
{
@Override
public LoginResponse process() throws Exception
{
return m_remoteAccountService.login(loginKey);
}
};
m_lastLoginResponse = method.run();
int result = m_lastLoginResponse.getResponseId();
if(result == LOGIN_OK)
{
m_currentStatus = AuthenticationStatus.AFTER_LOGIN;
m_lastLoginUserName = null;
m_lastLoginPassword = null;
m_lastLoginKey = loginKey;
}
else
{
m_lastLoginResponse = null;
}
return result;
}
public int login(final String userName, final String password) throws Exception
{
MethodWrapper<LoginResponse> method = new MethodWrapper<LoginResponse>()
{
@Override
public LoginResponse process() throws Exception
{
return m_remoteAccountService.login(userName, CryptoUtils.encrypt(password, ENCRYPT_ALGORITHM));
}
};
m_lastLoginResponse = method.run();
int result = m_lastLoginResponse.getResponseId();
if(result == LOGIN_OK)
{
m_currentStatus = AuthenticationStatus.AFTER_LOGIN;
m_lastLoginUserName = userName;
m_lastLoginPassword = password;
m_lastLoginKey = null;
}
else
{
m_lastLoginResponse = null;
}
return result;
}
public int logout() throws Exception
{
int result;
try
{
result = logoutWithoutRefreshingConnection();
}
finally
{
initialize(m_serviceURL);
}
return result;
}
public int register(final String userName, final String password, final String email) throws Exception
{
MethodWrapper<Integer> method = new MethodWrapper<Integer>()
{
@Override
public Integer process() throws Exception
{
return Integer.valueOf(m_remoteAccountService.register(userName, CryptoUtils.encrypt(password,
ENCRYPT_ALGORITHM), email));
}
};
return method.run().intValue();
}
public void releaseConnection() throws Exception
{
logoutWithoutRefreshingConnection();
}
public int relogin(final String loginKey) throws Exception
{
if(isLoggedIn())
{
if(loginKey != null && loginKey.equals(m_lastLoginKey))
return IRemoteDistroProvider.LOGIN_OK;
logout();
}
return login(loginKey);
}
public int relogin(final String userName, final String password) throws Exception
{
if(isLoggedIn())
{
if(userName != null && userName.equals(m_lastLoginUserName) && password != null
&& password.equals(m_lastLoginPassword))
return IRemoteDistroProvider.LOGIN_OK;
logout();
}
return login(userName, password);
}
private int logoutWithoutRefreshingConnection() throws Exception
{
MethodWrapper<Integer> method = new MethodWrapper<Integer>()
{
@Override
public Integer process() throws Exception
{
return Integer.valueOf(m_remoteAccountService.logoutSession());
}
};
int result;
try
{
result = method.run().intValue();
}
finally
{
m_currentStatus = AuthenticationStatus.BEFORE_INIT;
m_remoteAccountService = null;
}
return result;
}
// refreshes connection after session timeout
private void refresh() throws Exception
{
if(m_currentStatus == AuthenticationStatus.BEFORE_INIT)
return;
initialize(m_serviceURL);
if(m_currentStatus == AuthenticationStatus.AFTER_INIT)
return;
if(m_lastLoginKey != null)
login(m_lastLoginKey);
else
login(m_lastLoginUserName, m_lastLoginPassword);
}
}