/*
*
* Hamsam - Instant Messaging API
*
* Copyright (C) 2003 Mike Miller <mikemil@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package hamsam.protocol.aim;
import java.io.IOException;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import hamsam.api.*;
import hamsam.exception.IllegalArgumentException;
import hamsam.exception.IllegalStateException;
import hamsam.exception.UnsupportedOperationException;
import hamsam.net.*;
import hamsam.protocol.Protocol;
import hamsam.protocol.aim.command.*;
/**
* @author Raghu
*/
public class AIMProtocol extends Thread implements Protocol {
private static final String PROTOCOL_NAME = "AOL Instant Messenger";
private static final String DEFAULT_HOST = "login.oscar.aol.com";
private static final int DEFAULT_PORT = 5190; //22; - for work when firewall blocks me!
/**
* Listener for IM services.
*/
private IMListener listener;
/**
* the current user.
*/
private String userID;
/**
* Password of the current user.
*/
private String password;
/**
* This maps a conference object to its room name.
*/
// private Hashtable confRoomMap;
/**
* This maps a room name to the corresponding conference object.
*/
// private Hashtable roomConfMap;
/**
* This is the number of conferences already you have participated.
*/
// private long conferenceCount;
/**
* Indicates whether we are connected to a AIM Server.
*/
private boolean connected;
/**
* The I/O error received from the reader / writer threads.
*/
private IOException IOError;
/**
* All smileys supported by AIM.
*/
// private SmileyComponent[] smileys;
/** AIM Command Handler */
private CommandHandler cmdHandler;
/** */
private Map statusMap;
/**
* Default Constructor
*/
public AIMProtocol() {
super();
connected = false;
statusMap = new HashMap();
//todo setup status flag masks to put in here
statusMap.put("online",new Integer(0x0000));
statusMap.put("away", new Integer(0x0001));
statusMap.put("dnd", new Integer(0x0002));
statusMap.put("na", new Integer(0x0004));
statusMap.put("busy", new Integer(0x0010));
statusMap.put("invisible", new Integer(0x0100));
setDaemon(true);
setName("AIMProtocol");
cmdHandler = new AuthCommandHandler(this);
this.start();
}
/* todo pull javadoc from protocol and check for incoming
* status not in map and throw whatever exception we are supposed to.
* @see hamsam.protocol.Protocol#changeStatus(java.lang.String)
*/
public void changeStatus(String status) throws IllegalArgumentException {
Integer statusFlag = null;
if (status == null) {
statusFlag = (Integer)statusMap.get("invisible");
} else {
statusFlag = (Integer)statusMap.get(status);
if (statusFlag == null) {
throw new IllegalArgumentException("status "+status+" not supported");
}
}
//send the status flag mask down to be processed
cmdHandler.changeStatus(statusFlag);
}
/** Connect to the AIM server
* @param username Buddy name to login into
* @param password Password for the buddy
* @param info ProxyInfo object
* @see hamsam.protocol.Protocol#connect(java.lang.String, java.lang.String, hamsam.net.ProxyInfo)
*/
public void connect(String username, String password, ProxyInfo info) throws IllegalStateException {
if (listener == null)
throw new IllegalStateException("Listener not set");
listener.connecting(this);
this.userID = username;
this.password = password;
/* send the initial command */
if (cmdHandler instanceof ConnectionHandler) {
((ConnectionHandler) cmdHandler).connect(info, DEFAULT_HOST, DEFAULT_PORT, username, password);
connected = true;
}
}
/**
* This method is invoked by the reader and writer threads to indicate
* an I/O error.
*
* <p>
* All operations will be stopped and the service will be shut down
* once this method is invoked.
*/
void shutdown(IOException e) {
IOError = e;
}
/**
* Disconnect from AIM
* @throws IllegalStateException if either the interal reader or write background
* threads are null
* @see hamsam.protocol.Protocol#disconnect()
*/
public void disconnect() throws IllegalStateException {
if (connected == true) {
// tell command handler to disconnect/cleanup
if (cmdHandler instanceof ConnectionHandler) {
((ConnectionHandler) cmdHandler).disconnect();
connected = false;
}
}
}
/** Gets the protocol name
* @return String containing the protocol name
* @see hamsam.protocol.Protocol#getProtocolName()
*/
public String getProtocolName() {
return PROTOCOL_NAME;
}
/** Checks if Add Buddy request is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isBuddyAddRequestSupported()
*/
public boolean isBuddyAddRequestSupported() {
return true;
}
/** Checks if Buddy group is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isBuddyGroupSupported()
*/
public boolean isBuddyGroupSupported() {
return true;
}
/** Checks if ignore is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isIgnoreSupported()
*/
public boolean isIgnoreSupported() {
return true;
}
/** Checks if Offline Message is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isOfflineMessageSupported()
*/
public boolean isOfflineMessageSupported() {
// todo check how to implement!!!
return false;
}
/** Checks if typing notifications are supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isTypingNotifySupported()
*/
public boolean isTypingNotifySupported() {
return true;
}
/** Checks if Conferencing is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isConferenceSupported()
*/
public boolean isConferenceSupported() {
//todo find out how to implement
return false;
}
/** Checks if new mail notification is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isMailNotifySupported()
*/
public boolean isMailNotifySupported() {
// todo find out how to implement
return false;
}
/** Checks if Invisible is supported
* @return true if supported, otherwise false
* @see hamsam.protocol.Protocol#isInvisibleSupported()
*/
public boolean isInvisibleSupported() {
return true;
}
/** Sets the listener
* @param listener Listener for this protocol.
* @see hamsam.protocol.Protocol#setListener(hamsam.api.IMListener)
*/
public void setListener(IMListener listener) {
this.listener = listener;
if (cmdHandler != null) {
cmdHandler.setListener(listener);
}
}
/** Starts a conference
* @param conf Conference
* @param message Message
* @throws IllegalStateException if the protocol is not yet connected.
* @see hamsam.protocol.Protocol#startConference(hamsam.api.Conference, java.lang.String)
*/
public void startConference(Conference conf, String message)
throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
}
/** Quits a conference
* @param conf conference to quit
* @see hamsam.protocol.Protocol#quitConference(hamsam.api.Conference)
*/
public void quitConference(Conference conf) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
}
/** Sends an instant message to the conference
* @param conf Conference
* @param message Message to send to the conference
* @see hamsam.protocol.Protocol#sendConferenceMessage(hamsam.api.Conference, hamsam.api.Message)
*/
public void sendConferenceMessage(Conference conf, Message message) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
}
/** Adds a buddy to the Buddy List
* @param buddy Buddy to be added to the Buddy List
* @see hamsam.protocol.Protocol#addToBuddyList(hamsam.api.Buddy)
*/
public void addToBuddyList(Buddy buddy) throws IllegalArgumentException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
cmdHandler.addToBuddyList(buddy);
//todo need to be sure it worked!
listener.buddyAdded(buddy);
}
/** Deletes a buddy from the Buddy List
* @param buddy Buddy to be deleted from the Buddy List
* @see hamsam.protocol.Protocol#deleteFromBuddyList(hamsam.api.Buddy)
*/
public void deleteFromBuddyList(Buddy buddy) throws IllegalArgumentException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
cmdHandler.deleteFromBuddyList(buddy);
//todo need to be sure it worked
listener.buddyDeleted(buddy);
}
/** Ignores a buddy
* @param buddy Buddy to ignore
* @see hamsam.protocol.Protocol#ignoreBuddy(hamsam.api.Buddy)
*/
public void ignoreBuddy(Buddy buddy) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
//TODO think this means making them invisible - double check this
cmdHandler.ignoreBuddy(buddy);
listener.buddyIgnored(buddy);
}
/** Unignores a buddy
* @param buddy Buddy to unignore
* @see hamsam.protocol.Protocol#unignoreBuddy(hamsam.api.Buddy)
*/
public void unignoreBuddy(Buddy buddy) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
//TODO think this means making them visible again - remove from invisible
cmdHandler.unIgnoreBuddy(buddy);
listener.buddyUnignored(buddy);
}
/** Sends an instant message to a buddy
* @param buddy Buddy to send message to
* @param message Message to send
* @see hamsam.protocol.Protocol#sendInstantMessage(hamsam.api.Buddy, hamsam.api.Message)
*/
public void sendInstantMessage(Buddy buddy, Message message) throws IllegalStateException {
if (!connected){
throw new IllegalStateException("not connected yet!");
}
cmdHandler.sendInstantMessage(buddy, message);
}
/**
* @see hamsam.protocol.Protocol#typingStarted(hamsam.api.Buddy)
*/
public void typingStarted(Buddy buddy) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
cmdHandler.typingStarted(buddy);
// todo - how do I get notified that my buddy started typing??? Not working yet
//listener.typingStarted(buddy);
}
/* (non-Javadoc)
* @see hamsam.protocol.Protocol#typingStopped(hamsam.api.Buddy)
*/
public void typingStopped(Buddy buddy) throws UnsupportedOperationException, IllegalStateException {
if (!connected) {
throw new IllegalStateException("not connected yet!");
}
cmdHandler.typingStopped(buddy);
//todo - how do I get notified that my buddy stopped typing???
//listener.typingStopped(buddy);
}
/* (non-Javadoc)
* @see hamsam.protocol.Protocol#getSupportedSmileys()
*/
public SmileyComponent[] getSupportedSmileys() {
return null;
}
/**
*
* @see java.lang.Runnable#run()
*/
public void run() {
CommandEvent evt = null;
//GregorianCalendar prevKeepAliveTime = new GregorianCalendar();
while (true) {
if (evt != null)
cmdHandler.handleCommand(evt);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
}
}
/* todo - pull javadoc from protocol
* @see hamsam.protocol.Protocol#getSupportedStatusMessages()
*/
public String[] getSupportedStatusMessages() {
return (String[]) statusMap.keySet().toArray(new String[0]);
}
/* (non-Javadoc)
* @see hamsam.protocol.Protocol#isBuddyNameAliasSupported()
*/
public boolean isBuddyNameAliasSupported() {
// todo Auto-generated method stub
return false;
}
/* (non-Javadoc)
* @see hamsam.protocol.Protocol#changeBuddyAlias(hamsam.api.Buddy, java.lang.String)
*/
public void changeBuddyAlias(Buddy buddy, String alias) throws UnsupportedOperationException {
// todo Auto-generated method stub
// needs to be implemented!!!
}
}