package er.imadaptor;
import java.beans.PropertyChangeEvent;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.kano.joustsim.Screenname;
import net.kano.joustsim.oscar.AimConnection;
import net.kano.joustsim.oscar.AimConnectionProperties;
import net.kano.joustsim.oscar.AimSession;
import net.kano.joustsim.oscar.BuddyInfo;
import net.kano.joustsim.oscar.BuddyInfoManager;
import net.kano.joustsim.oscar.DefaultAimSession;
import net.kano.joustsim.oscar.GlobalBuddyInfoListener;
import net.kano.joustsim.oscar.State;
import net.kano.joustsim.oscar.StateEvent;
import net.kano.joustsim.oscar.StateListener;
import net.kano.joustsim.oscar.oscar.service.icbm.Conversation;
import net.kano.joustsim.oscar.oscar.service.icbm.ConversationEventInfo;
import net.kano.joustsim.oscar.oscar.service.icbm.ConversationListener;
import net.kano.joustsim.oscar.oscar.service.icbm.IcbmBuddyInfo;
import net.kano.joustsim.oscar.oscar.service.icbm.IcbmListener;
import net.kano.joustsim.oscar.oscar.service.icbm.IcbmService;
import net.kano.joustsim.oscar.oscar.service.icbm.Message;
import net.kano.joustsim.oscar.oscar.service.icbm.MessageInfo;
import net.kano.joustsim.oscar.oscar.service.icbm.SimpleMessage;
import net.kano.joustsim.oscar.oscar.service.ssi.Buddy;
import net.kano.joustsim.oscar.oscar.service.ssi.MutableBuddy;
import net.kano.joustsim.oscar.oscar.service.ssi.MutableBuddyList;
import net.kano.joustsim.oscar.oscar.service.ssi.MutableGroup;
import net.kano.joustsim.oscar.oscar.service.ssi.SsiService;
public class JOscarInstantMessenger extends AbstractInstantMessenger {
private AimSession _aimSession;
private AimConnection _conn;
private IcbmHandler _icbmHandler;
private ConversationHandler _conversationHandler;
private boolean _connected;
private long _lastConnectionAttempt;
private long _lastBuddyListChange;
public JOscarInstantMessenger(String screenName, String password) {
super(screenName, password);
_icbmHandler = new IcbmHandler();
_conversationHandler = new ConversationHandler();
}
public long buddyListLastModified() {
return _lastBuddyListChange;
}
protected void buddyListModified() {
_lastBuddyListChange = System.currentTimeMillis();
}
protected class AimStateHandler implements StateListener {
public void handleStateChange(StateEvent event) {
State state = event.getNewState();
if (state == State.ONLINE) {
_conn = event.getAimConnection();
_conn.getBuddyInfoManager().addGlobalBuddyInfoListener(new BuddyChangeListener());
IcbmService icbmService = _conn.getIcbmService();
icbmService.addIcbmListener(_icbmHandler);
_connected = true;
}
else {
AimConnection conn = event.getAimConnection();
IcbmService icbmService = conn.getIcbmService();
if (icbmService != null) {
icbmService.removeIcbmListener(_icbmHandler);
}
_connected = false;
}
}
}
protected class BuddyChangeListener implements GlobalBuddyInfoListener {
public void buddyInfoChanged(BuddyInfoManager buddyinfomanager, Screenname screenname, BuddyInfo buddyinfo, PropertyChangeEvent propertychangeevent) {
buddyListModified();
}
public void newBuddyInfo(BuddyInfoManager buddyinfomanager, Screenname screenname, BuddyInfo buddyinfo) {
buddyListModified();
}
public void receivedStatusUpdate(BuddyInfoManager buddyinfomanager, Screenname screenname, BuddyInfo buddyinfo) {
buddyListModified();
}
}
protected class IcbmHandler implements IcbmListener {
public void buddyInfoUpdated(IcbmService service, Screenname sn, IcbmBuddyInfo buddyInfo) {
buddyListModified();
}
public void newConversation(IcbmService service, Conversation conv) {
conv.addConversationListener(_conversationHandler);
}
public void sendAutomaticallyFailed(IcbmService service, Message message, Set conversations) {
}
}
public synchronized boolean isBuddyOnline(String buddyName) {
boolean buddyOnline = false;
BuddyInfo buddyInfo = _addBuddyIfNecessary(buddyName);
if (buddyInfo != null) {
buddyOnline = buddyInfo.isOnline();
}
return buddyOnline;
}
public synchronized boolean isBuddyAway(String buddyName) {
boolean buddyAway = false;
BuddyInfo buddyInfo = _addBuddyIfNecessary(buddyName);
if (buddyInfo != null) {
buddyAway = buddyInfo.isAway();
}
return buddyAway;
}
public synchronized String getStatusMessage(String buddyName) {
String statusMessage = null;
BuddyInfo buddyInfo = _addBuddyIfNecessary(buddyName);
if (buddyInfo != null) {
statusMessage = buddyInfo.getStatusMessage();
}
return statusMessage;
}
public synchronized String getAwayMessage(String buddyName) {
String awayMessage = null;
BuddyInfo buddyInfo = _addBuddyIfNecessary(buddyName);
if (buddyInfo != null) {
awayMessage = buddyInfo.getAwayMessage();
}
return awayMessage;
}
public String[] getGroupNames() {
String[] groupNames;
if (_connected && _conn != null) {
BuddyInfoManager buddyInfoManager = _conn.getBuddyInfoManager();
SsiService ssiService = _conn.getSsiService();
MutableBuddyList buddyList = ssiService.getBuddyList();
List groupsList = buddyList.getGroups();
groupNames = new String[groupsList.size()];
int groupNum = 0;
Iterator groupsIter = groupsList.iterator();
while (groupsIter.hasNext()) {
MutableGroup group = (MutableGroup) groupsIter.next();
groupNames[groupNum++] = group.getName();
}
}
else {
groupNames = new String[0];
}
return groupNames;
}
public String[] getBuddiesInGroupNamed(String groupName) {
String[] buddyNames = null;
if (_connected && _conn != null) {
BuddyInfoManager buddyInfoManager = _conn.getBuddyInfoManager();
SsiService ssiService = _conn.getSsiService();
MutableBuddyList buddyList = ssiService.getBuddyList();
List groupsList = buddyList.getGroups();
Iterator groupsIter = groupsList.iterator();
while (groupsIter.hasNext()) {
MutableGroup group = (MutableGroup) groupsIter.next();
if (groupName.equals(group.getName())) {
List buddies = group.getBuddiesCopy();
buddyNames = new String[buddies.size()];
int buddyNum = 0;
Iterator buddiesIter = buddies.iterator();
while (buddiesIter.hasNext()) {
MutableBuddy buddy = (MutableBuddy) buddiesIter.next();
buddyNames[buddyNum++] = buddy.getScreenname().getNormal();
}
}
}
}
if (buddyNames == null) {
buddyNames = new String[0];
}
return buddyNames;
}
public void removeBuddy(String buddyName) {
if (_connected && _conn != null) {
Screenname buddyScreenName = new Screenname(buddyName);
BuddyInfoManager buddyInfoManager = _conn.getBuddyInfoManager();
SsiService ssiService = _conn.getSsiService();
MutableBuddyList buddyList = ssiService.getBuddyList();
List groups = buddyList.getGroups();
Iterator groupsIter = groups.iterator();
while (groupsIter.hasNext()) {
MutableGroup group = (MutableGroup) groupsIter.next();
Buddy matchingBuddy = null;
Iterator buddiesIter = group.getBuddiesCopy().iterator();
while (matchingBuddy == null && buddiesIter.hasNext()) {
Buddy buddy = (Buddy) buddiesIter.next();
if (buddy.getScreenname().equals(buddyScreenName)) {
matchingBuddy = buddy;
}
}
if (matchingBuddy != null) {
group.deleteBuddy(matchingBuddy);
}
}
}
}
public void addBuddy(String buddyName) {
_addBuddyIfNecessary(buddyName);
}
public BuddyInfo _addBuddyIfNecessary(String buddyName) {
BuddyInfo buddyInfo = null;
if (_connected && _conn != null) {
Screenname buddy = new Screenname(buddyName);
BuddyInfoManager buddyInfoManager = _conn.getBuddyInfoManager();
buddyInfo = buddyInfoManager.getBuddyInfo(buddy);
boolean isOnBuddyList = false;
if (buddyInfo != null) {
isOnBuddyList = buddyInfo.isOnBuddyList();
}
if (!isOnBuddyList) {
SsiService ssiService = _conn.getSsiService();
MutableBuddyList buddyList = ssiService.getBuddyList();
List groups = buddyList.getGroups();
if (groups.size() == 0) {
buddyList.addGroup("Buddies");
groups = buddyList.getGroups();
}
MutableGroup group = (MutableGroup) groups.get(0);
group.addBuddy(buddyName);
for (int attempt = 0; attempt < 10 && !buddyInfo.isOnBuddyList(); attempt++) {
try {
Thread.sleep(100);
}
catch (Throwable t) {
// ignore
}
buddyInfo = buddyInfoManager.getBuddyInfo(buddy);
}
}
}
return buddyInfo;
}
public synchronized void connect() throws IMConnectionException {
boolean wasConnected = _connected;
if (wasConnected || _conn != null) {
disconnect();
}
long now = System.currentTimeMillis();
if (wasConnected || now - _lastConnectionAttempt > (1000 * 60 * 15)) {
_lastConnectionAttempt = now;
Screenname sn = new Screenname(getScreenName());
_aimSession = new DefaultAimSession(sn);
AimConnectionProperties props = new AimConnectionProperties(sn, getPassword());
AimConnection conn = _aimSession.openConnection(props);
conn.addStateListener(new AimStateHandler());
conn.connect();
}
else {
throw new ConnectedTooFastException("You attempted to connect repeatedly too quickly.");
}
}
public synchronized void disconnect() {
if (_connected) {
if (_conn != null) {
_conn.disconnect();
_conn = null;
_aimSession = null;
}
_connected = false;
}
}
public synchronized boolean isConnected() {
return _connected;
}
public synchronized void sendMessage(String buddyName, String message, boolean ignoreIfOffline) throws MessageException {
if (message != null) {
BuddyInfo buddyInfo = _addBuddyIfNecessary(buddyName);
if (buddyInfo != null) {
if (!buddyInfo.isOnline()) {
if (!ignoreIfOffline) {
throw new BuddyOfflineException("The buddy '" + buddyName + "' is not online.");
}
}
else {
if (message.length() > 2048) {
message = message.substring(0, 2048);
}
Conversation conv = _conn.getIcbmService().getImConversation(buddyInfo.getScreenname());
conv.open();
conv.sendMessage(new SimpleMessage(message));
}
}
}
}
protected class ConversationHandler implements ConversationListener {
public void canSendMessageChanged(Conversation c, boolean canSend) {
// do nothing
}
public void conversationClosed(Conversation c) {
// do nothing
}
public void conversationOpened(Conversation c) {
// do nothing
}
public void gotMessage(Conversation c, MessageInfo minfo) {
fireMessageReceived(minfo.getFrom().getNormal(), minfo.getMessage().getMessageBody());
}
public void gotOtherEvent(Conversation conversation, ConversationEventInfo event) {
// do nothing
}
public void sentMessage(Conversation c, MessageInfo minfo) {
// do nothing
}
public void sentOtherEvent(Conversation conversation, ConversationEventInfo event) {
// do nothing
}
}
public static class Factory implements IInstantMessengerFactory {
public IInstantMessenger createInstantMessenger(String screenName, String password) {
return new JOscarInstantMessenger(screenName, password);
}
}
}