package pl.radical.open.gg;
import pl.radical.open.gg.event.LoginFailedEvent;
import pl.radical.open.gg.event.SessionStateListener;
import pl.radical.open.gg.packet.GGIncomingPackage;
import pl.radical.open.gg.packet.GGOutgoingPackage;
import pl.radical.open.gg.packet.dicts.MessageStatus;
import pl.radical.open.gg.packet.dicts.SessionState;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Created on 2004-11-28
*
* @author <a href="mailto:mati@sz.home.pl">Mateusz Szczap</a>
*/
public class Session implements ISession {
private SessionState m_sessionState = SessionState.CONNECTION_AWAITING;
private SessionAccessor sessionAccessor = null;
private Set<SessionStateListener> sessionStateListeners = null;
private Map<String, Integer> sessionAttributes = null;
private IGGConfiguration configuration = new GGConfiguration();
private DefaultConnectionService connectionService = null;
private DefaultLoginService loginService = null;
private DefaultPresenceService presenceService = null;
private DefaultMessageService messageService = null;
private DefaultRegistrationService registrationService = null;
private DefaultContactListService contactListService = null;
private DefaultPublicDirectoryService publicDirectoryService = null;
private final Map<String, Object> proxies = new HashMap<String, Object>();
public Session(final IGGConfiguration configuration) throws GGException {
this();
if (configuration == null) {
throw new IllegalArgumentException("configuration cannot be null");
}
this.configuration = configuration;
}
public Session() throws GGException {
sessionAccessor = new SessionAccessor();
sessionAttributes = new HashMap<String, Integer>();
sessionStateListeners = new HashSet<SessionStateListener>();
connectionService = new DefaultConnectionService(this);
loginService = new DefaultLoginService(this);
messageService = new DefaultMessageService(this);
presenceService = new DefaultPresenceService(this);
contactListService = new DefaultContactListService(this);
publicDirectoryService = new DefaultPublicDirectoryService(this);
registrationService = new DefaultRegistrationService(this);
}
public SessionState getSessionState() {
return m_sessionState;
}
/**
* @see pl.radical.open.gg.ISession#getConfiguration()
*/
public IGGConfiguration getGGConfiguration() {
return configuration;
}
public void addSessionStateListener(final SessionStateListener sessionStateListener) {
if (sessionStateListener == null) {
throw new IllegalArgumentException("sessionStateListener cannot be null.");
}
sessionStateListeners.add(sessionStateListener);
}
public void removeSessionStateListener(final SessionStateListener sessionStateListener) {
if (sessionStateListener == null) {
throw new IllegalArgumentException("sessionStateListener cannot be null");
}
sessionStateListeners.remove(sessionStateListener);
}
/**
* @see pl.radical.open.gg.ISession#getConnectionService()
*/
public IConnectionService getConnectionService() {
if (!proxies.containsKey(IConnectionService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(connectionService);
final IConnectionService connectionServiceProxy = (IConnectionService) Proxy.newProxyInstance(classLoader, new Class[] {
IConnectionService.class
}, invocationHandler);
proxies.put(IConnectionService.class.getName(), connectionServiceProxy);
}
return (IConnectionService) proxies.get(IConnectionService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getLoginService()
*/
public ILoginService getLoginService() {
if (!proxies.containsKey(ILoginService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(loginService);
final ILoginService loginServiceProxy = (ILoginService) Proxy.newProxyInstance(classLoader, new Class[] {
ILoginService.class
}, invocationHandler);
proxies.put(ILoginService.class.getName(), loginServiceProxy);
}
return (ILoginService) proxies.get(ILoginService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getMessageService()
*/
public IMessageService getMessageService() {
if (!proxies.containsKey(IMessageService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(messageService);
final IMessageService messageServiceProxy = (IMessageService) Proxy.newProxyInstance(classLoader, new Class[] {
IMessageService.class
}, invocationHandler);
proxies.put(IMessageService.class.getName(), messageServiceProxy);
}
return (IMessageService) proxies.get(IMessageService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getPresenceService()
*/
public IPresenceService getPresenceService() {
if (!proxies.containsKey(IPresenceService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(presenceService);
final IPresenceService presenceServiceProxy = (IPresenceService) Proxy.newProxyInstance(classLoader, new Class[] {
IPresenceService.class
}, invocationHandler);
proxies.put(IPresenceService.class.getName(), presenceServiceProxy);
}
return (IPresenceService) proxies.get(IPresenceService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getPublicDirectoryService()
*/
public IPublicDirectoryService getPublicDirectoryService() {
if (!proxies.containsKey(IPublicDirectoryService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(publicDirectoryService);
final IPublicDirectoryService publicDirectoryServiceProxy = (IPublicDirectoryService) Proxy
.newProxyInstance(classLoader, new Class[] {
IPublicDirectoryService.class
}, invocationHandler);
proxies.put(IPublicDirectoryService.class.getName(), publicDirectoryServiceProxy);
}
return (IPublicDirectoryService) proxies.get(IPublicDirectoryService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getContactListService()
*/
public IContactListService getContactListService() {
if (!proxies.containsKey(IContactListService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(contactListService);
final IContactListService contactListServiceProxy = (IContactListService) Proxy.newProxyInstance(classLoader, new Class[] {
IContactListService.class
}, invocationHandler);
proxies.put(IContactListService.class.getName(), contactListServiceProxy);
}
return (IContactListService) proxies.get(IContactListService.class.getName());
}
/**
* @see pl.radical.open.gg.ISession#getRegistrationService()
*/
public IRegistrationService getRegistrationService() {
if (!proxies.containsKey(IRegistrationService.class.getName())) {
final ClassLoader classLoader = Session.class.getClassLoader();
final SessionInvocationHandler invocationHandler = new SessionInvocationHandler(registrationService);
final IRegistrationService registrationServiceProxy = (IRegistrationService) Proxy.newProxyInstance(classLoader, new Class[] {
IRegistrationService.class
}, invocationHandler);
proxies.put(IRegistrationService.class.getName(), registrationServiceProxy);
}
return (IRegistrationService) proxies.get(IRegistrationService.class.getName());
}
protected void notifySessionStateChanged(final SessionState oldState, final SessionState newState) {
if (oldState == null) {
throw new IllegalArgumentException("oldState cannot be null");
}
if (newState == null) {
throw new IllegalArgumentException("newState cannot be null");
}
for (final SessionStateListener sessionStateListener : sessionStateListeners) {
if (!oldState.equals(newState)) {
sessionStateListener.sessionStateChanged(oldState, newState);
}
}
}
// TODO restrict accesss by AspectJ friendly
public SessionAccessor getSessionAccessor() {
return sessionAccessor;
}
public class SessionAccessor {
public void setSessionState(final SessionState sessionState) {
if (!m_sessionState.equals(sessionState)) {
final SessionState oldState = m_sessionState;
m_sessionState = sessionState;
notifySessionStateChanged(oldState, sessionState);
}
}
public void sendPackage(final GGOutgoingPackage outgoingPackage) throws IOException {
connectionService.sendPackage(outgoingPackage);
}
public void notifyConnectionEstablished() throws GGException {
connectionService.notifyConnectionEstablished();
}
public void notifyConnectionClosed() throws GGException {
connectionService.notifyConnectionClosed();
}
public void notifyConnectionError(final Exception exception) throws GGException {
connectionService.notifyConnectionError(exception);
}
public void notifyPongReceived() {
connectionService.notifyPongReceived();
}
public void notifyLoginOK() throws GGException {
loginService.notifyLoginOK();
}
public void notifyLoggedOut() throws GGException {
loginService.notifyLoggedOut();
}
public void notifyLoginFailed(final LoginFailedEvent loginFailedEvent) throws GGException {
loginService.notifyLoginFailed(loginFailedEvent);
}
public void notifyUserChangedStatus(final IUser user, final IRemoteStatus newStatus) throws GGException {
presenceService.notifyUserChangedStatus(user, newStatus);
}
public void notifyMessageArrived(final IIncommingMessage incommingMessage) {
messageService.notifyMessageArrived(incommingMessage);
}
public void notifyMessageDelivered(final int uin, final int messageID, final MessageStatus messageStatus) {
messageService.notifyMessageDelivered(uin, messageID, messageStatus);
}
public void notifyGGPacketReceived(final GGIncomingPackage incomingPackage) {
connectionService.notifyPacketReceived(incomingPackage);
}
public void notifyContactListExported() {
contactListService.notifyContactListExported();
}
public void notifyContactListReceived(final Collection<LocalUser> contacts) {
contactListService.notifyContactListReceived(contacts);
}
public void notifyPubdirRead(final int queryID, final PersonalInfo publicDirInfo) {
publicDirectoryService.notifyPubdirRead(queryID, publicDirInfo);
}
public void notifyPubdirUpdated(final int queryID) {
publicDirectoryService.notifyPubdirUpdated(queryID);
}
public void notifyPubdirGotSearchResults(final int queryID, final PublicDirSearchReply searchReply) {
publicDirectoryService.notifyPubdirGotSearchResults(queryID, searchReply);
}
public void setLoginSeed(final int seed) {
sessionAttributes.put("seed", Integer.valueOf(seed));
}
public int getLoginSeed() {
if (!sessionAttributes.containsKey("seed")) {
return -1;
}
final Integer seedInteger = sessionAttributes.get("seed");
return seedInteger.intValue();
}
public void disconnect() throws GGException {
connectionService.disconnect();
}
}
private static final class SessionInvocationHandler implements InvocationHandler {
private Object m_delegate = null;
private SessionInvocationHandler(final Object delegate) {
if (delegate == null) {
throw new IllegalArgumentException("delegate cannot be null.");
}
m_delegate = delegate;
}
/**
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method,
* java.lang.Object[])
*/
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
try {
return method.invoke(m_delegate, args);
} catch (final InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}