package pl.radical.open.gg;
import pl.radical.open.gg.event.LoginFailedEvent;
import pl.radical.open.gg.event.LoginListener;
import pl.radical.open.gg.event.UserListener;
import pl.radical.open.gg.packet.dicts.SessionState;
import pl.radical.open.gg.packet.dicts.StatusType;
import pl.radical.open.gg.packet.out.GGLogin80;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The default implementation of <code>ILoginService</code>.
* <p>
* Created on 2004-11-28
*
* @author <a href="mailto:mati@sz.home.pl">Mateusz Szczap</a>
* @author <a href="mailto:lukasz.rzanek@radical.com.pl>Łukasz Rżanek</a>
*/
public class DefaultLoginService implements ILoginService, UserListener {
private static final Logger LOG = LoggerFactory.getLogger(DefaultLoginService.class);
/** The session associated with this service */
private Session session = null;
/** The set of <code>LoginListener</code>'s */
private final Set<LoginListener> loginListeners = new HashSet<LoginListener>();
private LoginContext loginContext = null;
// friendly
DefaultLoginService(final Session session) {
if (session == null) {
throw new IllegalArgumentException("session cannot be null");
}
this.session = session;
}
/**
* @see pl.radical.open.gg.ILoginService#login()
*/
public void login(final LoginContext loginContext) throws GGException {
LOG.debug("Logging in, loginContext: " + loginContext);
if (loginContext == null) {
throw new IllegalArgumentException("loginContext cannot be null");
}
this.loginContext = loginContext;
if (session.getSessionState() != SessionState.AUTHENTICATION_AWAITING) {
throw new GGSessionException(session.getSessionState());
}
session.getPresenceService().addUserListener(this);
try {
final int uin = loginContext.getUin();
final String password = loginContext.getPassword();
final int seed = session.getSessionAccessor().getLoginSeed();
final GGLogin80 login = new GGLogin80(uin, password.toCharArray(), seed);
login.setStatus(loginContext.getStatus());
if (loginContext.getImageSize() != -1) {
login.setImageSize(loginContext.getImageSize());
}
if (loginContext.getLocalIP() != null) {
login.setLocalIP(loginContext.getLocalIP());
}
if (loginContext.getLocalPort() != -1) {
login.setLocalPort(loginContext.getLocalPort());
}
if (loginContext.getExternalIP() != null) {
login.setExternalIP(loginContext.getExternalIP());
}
if (loginContext.getExternalPort() != -1) {
login.setExternalPort(loginContext.getExternalPort());
}
session.getSessionAccessor().sendPackage(login);
} catch (final IOException ex) {
session.getSessionAccessor().setSessionState(SessionState.DISCONNECTED);
throw new GGException("Unable to login, loginContext: " + loginContext, ex);
}
}
/**
* @see pl.radical.open.gg.ILoginService#logout()
*/
public void logout() throws GGException {
LOG.debug("Logging out, loginContext: " + loginContext);
logout(false, null, null, true);
}
/**
* @see pl.radical.open.gg.ILoginService#logout(java.lang.String, java.util.Date returnTime)
*/
public void logout(String description, final Date returnTime) throws GGException {
if (description == null) {
description = "";
}
checkSessionState();
logout(true, description, returnTime, true);
}
/**
* @see pl.radical.open.gg.ILoginService#getLoginContext()
*/
public LoginContext getLoginContext() {
return loginContext;
}
/**
* @see pl.radical.open.gg.ILoginService#isLoggedIn()
*/
public boolean isLoggedIn() {
return session.getSessionState() == SessionState.LOGGED_IN;
}
/**
* @see pl.radical.open.gg.ILoginService#addLoginListener(pl.radical.open.gg.event.LoginListener)
*/
public void addLoginListener(final LoginListener loginListener) {
if (loginListener == null) {
throw new IllegalArgumentException("loginListener cannot be null");
}
loginListeners.add(loginListener);
}
/**
* @see pl.radical.open.gg.ILoginService#removeLoginListener(pl.radical.open.gg.event.LoginListener)
*/
public void removeLoginListener(final LoginListener loginListener) {
if (loginListener == null) {
throw new IllegalArgumentException("loginListener cannot be null");
}
loginListeners.remove(loginListener);
}
protected void notifyLoginOK() throws GGException {
session.getSessionAccessor().setSessionState(SessionState.LOGGED_IN);
for (final Object element : loginListeners) {
final LoginListener loginListener = (LoginListener) element;
loginListener.loginOK();
}
}
protected void notifyLoginFailed(final LoginFailedEvent loginFailedEvent) throws GGException {
session.getSessionAccessor().setSessionState(SessionState.CONNECTION_ERROR);
for (final Object element : loginListeners) {
final LoginListener loginListener = (LoginListener) element;
loginListener.loginFailed(loginFailedEvent);
}
}
protected void notifyLoggedOut() throws GGException {
for (final Object element : loginListeners) {
final LoginListener loginListener = (LoginListener) element;
loginListener.loggedOut();
}
}
/**
* @see pl.radical.open.gg.event.UserListener#localStatusChanged(pl.radical.open.gg.ILocalStatus)
*/
public void localStatusChanged(final ILocalStatus localStatus) throws GGException {
if (localStatus.getStatusType() == StatusType.OFFLINE) {
logout(false, null, null, false);
} else if (localStatus.getStatusType() == StatusType.OFFLINE_WITH_DESCRIPTION) {
logout(true, localStatus.getDescription(), localStatus.getReturnDate(), false);
}
}
/**
* @see pl.radical.open.gg.event.UserListener#userStatusChanged(pl.radical.open.gg.IUser,
* pl.radical.open.gg.IRemoteStatus)
*/
public void userStatusChanged(final IUser user, final IRemoteStatus newStatus) throws GGException {
}
private void checkSessionState() throws GGException {
if (session.getSessionState() != SessionState.LOGGED_IN) {
throw new GGSessionException(session.getSessionState());
}
}
private void logout(final boolean offLineWithStatus, final String description, final Date returnDate, final boolean sendStatus) throws GGException {
checkSessionState();
if (!offLineWithStatus) {
if (sendStatus) {
final ILocalStatus localStatus = new LocalStatus(StatusType.OFFLINE);
session.getPresenceService().setStatus(localStatus);
}
session.getSessionAccessor().setSessionState(SessionState.LOGGED_OUT);
loginContext = null;
session.getSessionAccessor().notifyLoggedOut();
} else {
if (description == null) {
throw new IllegalArgumentException("description cannot be null");
}
if (description.length() > 0) {
if (sendStatus) {
final LocalStatus localStatus = new LocalStatus(StatusType.OFFLINE_WITH_DESCRIPTION, description);
if (returnDate != null) {
localStatus.setReturnDate(returnDate);
}
session.getPresenceService().setStatus(localStatus);
}
loginContext = null;
session.getSessionAccessor().setSessionState(SessionState.LOGGED_OUT);
notifyLoggedOut();
}
}
}
}