package org.limewire.xmpp.client.impl;
import java.util.concurrent.Callable;
import org.jivesoftware.smack.Roster;
import org.limewire.concurrent.ExecutorsHelper;
import org.limewire.concurrent.ListeningExecutorService;
import org.limewire.concurrent.ListeningFuture;
import org.limewire.friend.api.FriendConnection;
import org.limewire.friend.api.FriendConnectionConfiguration;
import org.limewire.friend.api.FriendConnectionEvent;
import org.limewire.friend.api.FriendConnectionFactory;
import org.limewire.friend.api.FriendConnectionFactoryRegistry;
import org.limewire.friend.api.FriendException;
import org.limewire.friend.api.FriendPresence;
import org.limewire.friend.api.Network;
import org.limewire.inject.EagerSingleton;
import org.limewire.lifecycle.Asynchronous;
import org.limewire.lifecycle.Service;
import org.limewire.listener.EventBean;
import org.limewire.listener.EventMulticaster;
import org.limewire.listener.EventUtils;
import org.limewire.logging.Log;
import org.limewire.logging.LogFactory;
import org.limewire.xmpp.api.client.JabberSettings;
import com.google.inject.Inject;
@EagerSingleton
public class XMPPConnectionFactoryImpl implements Service, FriendConnectionFactory {
private static final Log LOG = LogFactory.getLog(XMPPConnectionFactoryImpl.class);
private final XMPPConnectionImplFactory connectionImplFactory;
private final JabberSettings jabberSettings;
private final ListeningExecutorService executorService;
private final EventBean<FriendConnectionEvent> friendConnectionEventBean;
@Inject
public XMPPConnectionFactoryImpl(XMPPConnectionImplFactory connectionImplFactory,
EventMulticaster<FriendConnectionEvent> connectionBroadcaster,
EventBean<FriendConnectionEvent> friendConnectionEventBean,
JabberSettings jabberSettings) {
this.connectionImplFactory = connectionImplFactory;
this.friendConnectionEventBean = friendConnectionEventBean;
this.jabberSettings = jabberSettings;
connectionBroadcaster.addListener(new ReconnectionManager(this));
// We'll install our own subscription listeners
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);
executorService = ExecutorsHelper.newSingleThreadExecutor(ExecutorsHelper.daemonThreadFactory("XMPPServiceImpl"));
}
@Inject
void register(org.limewire.lifecycle.ServiceRegistry registry) {
registry.register(this);
}
@Override
public void initialize() {
}
@Override
public void start() {
}
/**
* Logs out all existing connections.
*/
@Asynchronous
@Override
public void stop() {
XMPPFriendConnectionImpl connection = getActiveConnection();
if (connection != null) {
connection.logoutImpl(null);
}
}
@Override
public String getServiceName() {
return "XMPP";
}
@Override
public ListeningFuture<FriendConnection> login(final FriendConnectionConfiguration configuration) {
return executorService.submit(new Callable<FriendConnection>() {
@Override
public FriendConnection call() throws Exception {
return loginImpl(configuration);
}
});
}
@Override
@Inject
public void register(FriendConnectionFactoryRegistry registry) {
registry.register(Network.Type.XMPP, this);
}
FriendConnection loginImpl(FriendConnectionConfiguration configuration) throws FriendException {
return loginImpl(configuration, false);
}
FriendConnection loginImpl(FriendConnectionConfiguration configuration, boolean isReconnect) throws FriendException {
synchronized (this) {
XMPPFriendConnectionImpl activeConnection = getActiveConnection();
if(isReconnect) {
if(activeConnection != null) {
return activeConnection;
}
} else {
if(activeConnection != null) {
if (activeConnection.getConfiguration().equals(configuration)) {
return activeConnection;
} else {
// logout synchronously
activeConnection.logoutImpl(null);
}
}
}
XMPPFriendConnectionImpl connection = connectionImplFactory.createConnection(
configuration, executorService);
try {
connection.loginImpl();
//maintain the last set login state available or do not disturb
connection.setModeImpl(jabberSettings.isDoNotDisturbSet() ? FriendPresence.Mode.dnd : FriendPresence.Mode.available);
return connection;
} catch(FriendException e) {
LOG.debug(e.getMessage(), e);
throw new FriendException(e);
}
}
}
XMPPFriendConnectionImpl getActiveConnection() {
FriendConnection friendConnection = EventUtils.getSource(friendConnectionEventBean);
if (friendConnection instanceof XMPPFriendConnectionImpl && friendConnection.isLoggedIn()) {
return (XMPPFriendConnectionImpl)friendConnection;
}
return null;
}
@SuppressWarnings("unused")
private void setModeImpl(FriendPresence.Mode mode) throws FriendException {
XMPPFriendConnectionImpl connection = getActiveConnection();
if (connection != null) {
connection.setModeImpl(mode);
}
}
@Override
public ListeningFuture<String> requestLoginUrl(FriendConnectionConfiguration configuration) {
return null;
}
}