package pl.radical.open.gg;
import pl.radical.open.gg.event.ContactListListener;
import pl.radical.open.gg.event.GGPacketListener;
import pl.radical.open.gg.packet.GGIncomingPackage;
import pl.radical.open.gg.packet.GGOutgoingPackage;
import pl.radical.open.gg.packet.dicts.SessionState;
import pl.radical.open.gg.packet.in.GGUserListReply;
import pl.radical.open.gg.packet.out.GGUserListRequest;
import pl.radical.open.gg.utils.GGUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The default implementation of <code>IContactListService</code>.
* <p>
* Created on 2004-12-11
*
* @author <a href="mailto:mati@sz.home.pl">Mateusz Szczap</a>
*/
public class DefaultContactListService implements IContactListService {
private static final Logger LOG = LoggerFactory.getLogger(DefaultContactListService.class);
private Set<ContactListListener> m_contactListListeners = null;
private Session m_session = null;
// friendly
DefaultContactListService(final Session session) {
if (session == null) {
throw new IllegalArgumentException("session cannot be null");
}
m_session = session;
m_contactListListeners = new HashSet<ContactListListener>();
}
/**
* @see pl.radical.open.gg.IContactListService#clearContactList()
*/
public void clearContactList() throws GGException {
checkSessionState();
try {
final GGUserListRequest clearContactListRequest = GGUserListRequest.createClearUserListRequest();
m_session.getSessionAccessor().sendPackage(clearContactListRequest);
} catch (final IOException ex) {
throw new GGException("Unable to clear contact list", ex);
}
}
/**
* @see pl.radical.open.gg.IContactListService#exportContactList(java.util.Collection)
*/
public void exportContactList(final Collection<LocalUser> localUsers) throws GGException {
if (LOG.isDebugEnabled()) {
LOG.debug("Exporting contact list users...");
}
checkSessionState();
try {
final List<GGUserListRequest> packageList = createExportContactListPackageList(localUsers);
final ContactListSenderThread contactListSenderThread = new ContactListSenderThread(packageList);
contactListSenderThread.start();
} catch (final IOException ex) {
throw new GGException("Unable to export contact list", ex);
}
}
private List<GGUserListRequest> createExportContactListPackageList(final Collection<LocalUser> localUsers) throws IOException {
final String allUsers = GGUserListRequest.prepareRequest(localUsers);
final List<String> lines = GGUserListReply.getLinesStringList(allUsers.getBytes());
return exportContactListAsLines(lines);
}
private List<GGUserListRequest> exportContactListAsLines(final List<String> lines) {
final List<GGUserListRequest> packageList = new ArrayList<GGUserListRequest>();
final ArrayList<String> tempLines = new ArrayList<String>();
int counter = 0;
for (int i = 0; i < lines.size(); i++) {
final String line = lines.get(i);
tempLines.add(line);
counter += line.getBytes().length;
if (counter >= 1500) {
final GGUserListRequest putRequest = GGUserListRequest.createPutMoreUserListRequest(tempLines);
packageList.add(putRequest);
tempLines.clear();
counter = 0;
}
}
if (!packageList.isEmpty()) {
// Change first package to GG_USER_LIST_PUT
final GGUserListRequest userListRequest = packageList.get(0);
GGUserListRequest.changeRequestType(userListRequest, GGUserListRequest.GG_USER_LIST_PUT);
}
return packageList;
}
/**
* @see pl.radical.open.gg.IContactListService#importContactList()
*/
public void importContactList() throws GGException {
checkSessionState();
try {
final GGUserListRequest getContactListRequest = GGUserListRequest.createGetUserListRequest();
m_session.getSessionAccessor().sendPackage(getContactListRequest);
} catch (final IOException ex) {
throw new GGException("Unable to import contact list", ex);
}
}
public void exportContactList(final InputStream is) throws GGException {
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
final int byteCount = GGUtils.copy(is, bos);
if (byteCount == 0) {
return;
}
final byte[] data = bos.toByteArray();
final List<String> lines = GGUserListReply.getLinesStringList(data);
final List<GGUserListRequest> packageList = exportContactListAsLines(lines);
final ContactListSenderThread contactListSenderThread = new ContactListSenderThread(packageList);
contactListSenderThread.start();
} catch (final IOException ex) {
throw new GGException("Unable to export contact list.", ex);
}
}
private void checkSessionState() throws GGSessionException {
if (m_session.getSessionState() != SessionState.LOGGED_IN) {
throw new GGSessionException(m_session.getSessionState());
}
}
/**
* @see pl.radical.open.gg.IContactListService#addContactListListener(pl.radical.open.gg.event.ContactListListener)
*/
public void addContactListListener(final ContactListListener contactListListener) {
if (contactListListener == null) {
throw new IllegalArgumentException("contactListListener cannot be null");
}
m_contactListListeners.add(contactListListener);
}
/**
* @see pl.radical.open.gg.IContactListService#removeContactListlistener(pl.radical.open.gg.event.ContactListListener)
*/
public void removeContactListlistener(final ContactListListener contactListListener) {
if (contactListListener == null) {
throw new IllegalArgumentException("conractListListener cannot be null");
}
m_contactListListeners.add(contactListListener);
}
// TODO clone the listeners list before notifing
protected void notifyContactListExported() {
for (final Object element : m_contactListListeners) {
final ContactListListener contactListListener = (ContactListListener) element;
contactListListener.contactListExported();
}
}
// TODO clone the listeners list before notifing
protected void notifyContactListReceived(final Collection<LocalUser> users) {
for (final Object element : m_contactListListeners) {
final ContactListListener contactListListener = (ContactListListener) element;
contactListListener.contactListReceived(users);
}
}
private class ContactListSenderThread extends Thread implements GGPacketListener {
private List<GGUserListRequest> m_packagesToSend = null;
private boolean isRunning = true;
private ContactListSenderThread(final List<GGUserListRequest> packagesToSend) {
if (packagesToSend == null) {
throw new IllegalArgumentException("packagesToSend cannot be null");
}
m_packagesToSend = packagesToSend;
}
@Override
public void run() {
startUp();
while (!isRunning) {
try {
Thread.sleep(1000);
} catch (final InterruptedException ex) {
if (LOG.isDebugEnabled()) {
LOG.debug("ContactListSenderThread: thread interrupted.");
}
terminate();
}
}
}
public void startUp() {
m_session.getConnectionService().addPacketListener(this);
if (m_packagesToSend.isEmpty()) {
return;
}
final GGOutgoingPackage outgoingPackage = m_packagesToSend.remove(0);
try {
m_session.getSessionAccessor().sendPackage(outgoingPackage);
} catch (final IOException ex) {
LOG.warn("Unable to send contact list packet", ex);
}
}
public void terminate() {
if (LOG.isDebugEnabled()) {
LOG.debug("ContactListSenderThread: terminating...");
}
isRunning = false;
m_session.getConnectionService().removePacketListener(this);
}
public void sentPacket(final GGOutgoingPackage outgoingPacket) {
}
public void receivedPacket(final GGIncomingPackage incomingPacket) {
if (!(incomingPacket instanceof GGUserListReply)) {
return;
}
if (m_packagesToSend.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("ContactListSenderThread: Nothing more to send.");
}
terminate();
return;
}
final GGOutgoingPackage outgoingPackage = m_packagesToSend.remove(0);
try {
if (LOG.isDebugEnabled()) {
LOG.debug("ContactListSenderThread: Sending outgoing package...");
}
m_session.getSessionAccessor().sendPackage(outgoingPackage);
} catch (final IOException ex) {
LOG.warn("Unable to send contact list packet", ex);
terminate();
}
}
}
}