diff --git a/src/net/java/sip/communicator/impl/protocol/icq/ContactGroupIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/ContactGroupIcqImpl.java
index 08a2d4429..102cb0595 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/ContactGroupIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/ContactGroupIcqImpl.java
@@ -10,6 +10,7 @@
import net.java.sip.communicator.service.protocol.*;
import net.kano.joustsim.oscar.oscar.service.ssi.*;
+import net.java.sip.communicator.util.*;
/**
* The ICQ implementation of the ContactGroup interface. Intances of this class
@@ -88,6 +89,9 @@ public class ContactGroupIcqImpl
for (int i = 0; i < groupMembers.size(); i++)
{
+ // here we are not checking for AwaitingAuthorization buddies
+ // as we are creating group with list of buddies
+ // these checks must have been made already
addContact( new ContactIcqImpl((Buddy)groupMembers.get(i),
ssclCallback, true, true) );
}
@@ -529,6 +533,13 @@ void updateGroup(MutableGroup joustSimGroup,
while(serverBuddiesIter.hasNext())
{
Buddy buddy = (Buddy)serverBuddiesIter.next();
+
+ if(buddy.isAwaitingAuthorization())
+ {
+ ssclCallback.addAwaitingAuthorizationContact(buddy);
+ continue;
+ }
+
ContactIcqImpl contact
= findContact(buddy.getScreenname().getFormatted());
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
index be8833478..52b3d83f2 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java
@@ -365,7 +365,10 @@ private void assertConnected() throws IllegalStateException
*/
public boolean isOfflineMessagingSupported()
{
- return true;
+ if(icqProvider.USING_ICQ)
+ return true;
+ else
+ return false;
}
/**
@@ -397,7 +400,8 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
icqProvider.getSupportedOperationSets()
.get(OperationSetPersistentPresence.class.getName());
- retreiveOfflineMessages();
+ if(icqProvider.USING_ICQ)
+ retreiveOfflineMessages();
// run keepalive thread
if(keepAliveSendTask == null)
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetPersistentPresenceIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetPersistentPresenceIcqImpl.java
index fb32098fd..e0406bead 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetPersistentPresenceIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetPersistentPresenceIcqImpl.java
@@ -119,23 +119,35 @@ public class OperationSetPersistentPresenceIcqImpl
private AuthorizationHandler authorizationHandler = null;
private AuthListener authListener = new AuthListener();
+
+ /**
+ * The timer scheduling task that will query awaiting authorization
+ * contacts for their status
+ */
+ private Timer presenceQueryTimer = null;
+
+ /**
+ * Interval between queries for awaiting authorization
+ * contact statuses
+ */
+ private long PRESENCE_QUERY_INTERVAL = 120000l;
+ /**
+ * Used to request authorization when a user comes online
+ * and haven't granted one
+ */
+ private OperationSetExtendedAuthorizationsIcqImpl opSetExtendedAuthorizations = null;
+
+ /**
+ * Buddies seen availabel
+ */
+ private Vector buddiesSeenAvailable = new Vector();
+
/**
* The array list we use when returning from the getSupportedStatusSet()
* method.
*/
- private static final ArrayList supportedPresenceStatusSet = new ArrayList();
- static{
- supportedPresenceStatusSet.add(IcqStatusEnum.AWAY);
- supportedPresenceStatusSet.add(IcqStatusEnum.DO_NOT_DISTURB);
- supportedPresenceStatusSet.add(IcqStatusEnum.FREE_FOR_CHAT);
- supportedPresenceStatusSet.add(IcqStatusEnum.INVISIBLE);
- supportedPresenceStatusSet.add(IcqStatusEnum.NOT_AVAILABLE);
- supportedPresenceStatusSet.add(IcqStatusEnum.OCCUPIED);
- supportedPresenceStatusSet.add(IcqStatusEnum.OFFLINE);
- supportedPresenceStatusSet.add(IcqStatusEnum.ONLINE);
- }
-
+ private ArrayList supportedPresenceStatusSet = new ArrayList();
/**
* A map containing bindings between SIP Communicator's icq presence status
@@ -160,7 +172,7 @@ public class OperationSetPersistentPresenceIcqImpl
new Long(ICQ_ONLINE_MASK));
}
-
+
/**
* The server stored contact list that will be encapsulating joustsim's
* buddy list.
@@ -584,9 +596,26 @@ public void unsubscribe(Contact contact) throws IllegalArgumentException,
logger.trace("Going to remove contact from ss-list : " + contact);
- MutableGroup joustSimContactGroup = contactGroup.getJoustSimSourceGroup();
+ if( !contactGroup.isPersistent()
+ && contactIcqImpl.getJoustSimBuddy().isAwaitingAuthorization())
+ {
+ // this is contact in AwaitingAuthorization group
+ // we must find the original parent and remove it from there
+ ContactGroupIcqImpl origParent =
+ ssContactList.findGroup(contactIcqImpl.getJoustSimBuddy());
+
+ if(origParent != null)
+ {
+ origParent.getJoustSimSourceGroup().
+ deleteBuddy(contactIcqImpl.getJoustSimBuddy());
+ }
+ }
+ else
+ {
+ MutableGroup joustSimContactGroup = contactGroup.getJoustSimSourceGroup();
- joustSimContactGroup.deleteBuddy(contactIcqImpl.getJoustSimBuddy());
+ joustSimContactGroup.deleteBuddy(contactIcqImpl.getJoustSimBuddy());
+ }
}
/**
@@ -631,16 +660,48 @@ public void publishPresenceStatus(PresenceStatus status,
if (!(status instanceof IcqStatusEnum))
throw new IllegalArgumentException(
status + " is not a valid ICQ status");
-
+
long icqStatus = presenceStatusToIcqStatusLong((IcqStatusEnum)status);
logger.debug("Will set status: " + status + " long=" + icqStatus);
MainBosService bosService
= icqProvider.getAimConnection().getBosService();
-
- bosService.getOscarConnection().sendSnac(new SetExtraInfoCmd(icqStatus));
- bosService.setStatusMessage(statusMessage);
+
+ if(!icqProvider.USING_ICQ)
+ {
+ if(status.equals(IcqStatusEnum.AWAY))
+ {
+ if(getPresenceStatus().equals(IcqStatusEnum.INVISIBLE))
+ bosService.setVisibleStatus(true);
+
+ bosService.getOscarConnection().sendSnac(new SetInfoCmd(
+ new InfoData(null, "I'm away!", null, null)));
+ }
+ else if(status.equals(IcqStatusEnum.INVISIBLE))
+ {
+ if(getPresenceStatus().equals(IcqStatusEnum.AWAY))
+ bosService.getOscarConnection().sendSnac(new SetInfoCmd(
+ new InfoData(null, InfoData.NOT_AWAY, null, null)));
+
+ bosService.setVisibleStatus(false);
+ }
+ else if(status.equals(IcqStatusEnum.ONLINE))
+ {
+ if(getPresenceStatus().equals(IcqStatusEnum.INVISIBLE))
+ bosService.setVisibleStatus(true);
+ else if(getPresenceStatus().equals(IcqStatusEnum.AWAY))
+ {
+ bosService.getOscarConnection().sendSnac(new SetInfoCmd(
+ new InfoData(null, InfoData.NOT_AWAY, null, null)));
+ }
+ }
+ }
+ else
+ {
+ bosService.getOscarConnection().sendSnac(new SetExtraInfoCmd(icqStatus));
+ bosService.setStatusMessage(statusMessage);
+ }
//so that everyone sees the change.
queryContactStatus(
@@ -764,7 +825,26 @@ public void moveContactToGroup(Contact contactToMove,
throw new IllegalArgumentException(
"The specified group is not an icq contact group."
+ newParent);
-
+
+ ContactGroupIcqImpl theAwaitingAuthorizationGroup =
+ ssContactList.findContactGroup(
+ ssContactList.awaitingAuthorizationGroupName);
+
+ if(newParent.equals(theAwaitingAuthorizationGroup))
+ throw new IllegalArgumentException(
+ "Cannot move contacts to this group : " +
+ theAwaitingAuthorizationGroup);
+
+ if(((ContactIcqImpl)contactToMove).isPersistent()
+ && !contactToMove.getParentContactGroup().isPersistent())
+ {
+ if(contactToMove.getParentContactGroup().equals(
+ theAwaitingAuthorizationGroup))
+ throw new IllegalArgumentException(
+ "Cannot move contacts from this group : " +
+ theAwaitingAuthorizationGroup);
+ }
+
ssContactList.moveContact((ContactIcqImpl)contactToMove,
(ContactGroupIcqImpl)newParent);
}
@@ -802,6 +882,23 @@ public PresenceStatus getPresenceStatus()
*/
public Iterator getSupportedStatusSet()
{
+ if(supportedPresenceStatusSet.size() == 0)
+ {
+ supportedPresenceStatusSet.add(IcqStatusEnum.ONLINE);
+
+ if(icqProvider.USING_ICQ)
+ {
+ supportedPresenceStatusSet.add(IcqStatusEnum.DO_NOT_DISTURB);
+ supportedPresenceStatusSet.add(IcqStatusEnum.FREE_FOR_CHAT);
+ supportedPresenceStatusSet.add(IcqStatusEnum.NOT_AVAILABLE);
+ supportedPresenceStatusSet.add(IcqStatusEnum.OCCUPIED);
+ }
+
+ supportedPresenceStatusSet.add(IcqStatusEnum.AWAY);
+ supportedPresenceStatusSet.add(IcqStatusEnum.INVISIBLE);
+ supportedPresenceStatusSet.add(IcqStatusEnum.OFFLINE);
+ }
+
return supportedPresenceStatusSet.iterator();
}
@@ -1250,6 +1347,25 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
icqProvider.getAimConnection().getExternalServiceManager().
getIconServiceArbiter().addIconRequestListener(
new IconUpdateListener());
+
+ if(icqProvider.USING_ICQ)
+ {
+ opSetExtendedAuthorizations =
+ (OperationSetExtendedAuthorizationsIcqImpl)
+ icqProvider.getSupportedOperationSets()
+ .get(OperationSetExtendedAuthorizations.class.getName());
+
+ if(presenceQueryTimer == null)
+ presenceQueryTimer = new Timer();
+ else
+ presenceQueryTimer.cancel();
+
+ AwaitingAuthorizationContactsPresenceTimer
+ queryTask = new AwaitingAuthorizationContactsPresenceTimer();
+
+ presenceQueryTimer.scheduleAtFixedRate(
+ queryTask, PRESENCE_QUERY_INTERVAL, PRESENCE_QUERY_INTERVAL);
+ }
}
else if(evt.getNewState() == RegistrationState.UNREGISTERED
|| evt.getNewState() == RegistrationState.AUTHENTICATION_FAILED
@@ -1358,21 +1474,43 @@ public void handleYourInfo(MainBosService service,
{
logger.debug("Received our own user info: " + userInfo);
logger.debug("previous status was: " + currentIcqStatus);
+ logger.debug("new status is: " + userInfo.getIcqStatus());
//update the last received field.
long oldStatus = currentIcqStatus;
- currentIcqStatus = userInfo.getIcqStatus();
-
- //it might happen that the info here is -1 (in case we're going back
- //to online). Yet the fact that we're getting the event means
- //that we're very much online so make sure we change accordingly
- if (currentIcqStatus == -1 )
- currentIcqStatus = ICQ_ONLINE_MASK;
-
- //only notify of an event change if there was really one.
- if( oldStatus != userInfo.getIcqStatus() )
- fireProviderPresenceStatusChangeEvent(oldStatus,
- currentIcqStatus);
+
+ if(icqProvider.USING_ICQ)
+ {
+ currentIcqStatus = userInfo.getIcqStatus();
+
+ //it might happen that the info here is -1 (in case we're going back
+ //to online). Yet the fact that we're getting the event means
+ //that we're very much online so make sure we change accordingly
+ if (currentIcqStatus == -1 )
+ currentIcqStatus = ICQ_ONLINE_MASK;
+
+ //only notify of an event change if there was really one.
+ if( oldStatus != userInfo.getIcqStatus() )
+ fireProviderPresenceStatusChangeEvent(oldStatus,
+ currentIcqStatus);
+ }
+ else
+ {
+ if(userInfo.getAwayStatus() != null && userInfo.getAwayStatus().equals(Boolean.TRUE))
+ {
+ currentIcqStatus = presenceStatusToIcqStatusLong(IcqStatusEnum.AWAY);
+ }
+ else if(userInfo.getIcqStatus() != -1)
+ {
+ currentIcqStatus = userInfo.getIcqStatus();
+ }
+ else // online status
+ currentIcqStatus = ICQ_ONLINE_MASK;
+
+ if( oldStatus != currentIcqStatus )
+ fireProviderPresenceStatusChangeEvent(oldStatus,
+ currentIcqStatus);
+ }
}
}
@@ -1408,8 +1546,20 @@ public void gotBuddyStatus(BuddyService service, Screenname buddy,
}
PresenceStatus oldStatus
= sourceContact.getPresenceStatus();
- PresenceStatus newStatus
- = icqStatusLongToPresenceStatus(info.getIcqStatus());
+
+ PresenceStatus newStatus = null;
+
+ if(!icqProvider.USING_ICQ)
+ {
+ Boolean awayStatus = info.getAwayStatus();
+ if(awayStatus == null || awayStatus.equals(Boolean.FALSE))
+ newStatus = IcqStatusEnum.ONLINE;
+ else
+ newStatus = IcqStatusEnum.AWAY;
+ }
+ else
+ newStatus = icqStatusLongToPresenceStatus(info.getIcqStatus());
+
sourceContact.updatePresenceStatus(newStatus);
ContactGroupIcqImpl parent
@@ -1493,12 +1643,21 @@ public void authorizationDenied(Screenname screenname, String reason)
authorizationHandler.processAuthorizationResponse(
new AuthorizationResponse(AuthorizationResponse.REJECT, reason)
, srcContact);
+ try
+ {
+ unsubscribe(srcContact);
+ } catch (OperationFailedException ex)
+ {
+ logger.error("cannot remove denied contact : " + srcContact, ex);
+ }
}
public void authorizationAccepted(Screenname screenname, String reason)
{
logger.trace("authorizationAccepted from " + screenname);
Contact srcContact = findContactByID(screenname.getFormatted());
+ ssContactList.moveAwaitingAuthorizationContact(
+ (ContactIcqImpl)srcContact);
authorizationHandler.processAuthorizationResponse(
new AuthorizationResponse(AuthorizationResponse.ACCEPT, reason)
@@ -1537,13 +1696,50 @@ public boolean authorizationRequired(Screenname screenname, Group parentGroup)
logger.trace("authorizationRequired from " + screenname);
logger.trace("finding buddy : " + screenname);
- Contact srcContact = findContactByID(screenname.getFormatted());
+ ContactIcqImpl srcContact =
+ ssContactList.findContactByScreenName(screenname.getFormatted());
if(srcContact == null)
{
- ContactGroup parent = ssContactList.findContactGroup(parentGroup);
- srcContact =
- createUnresolvedContact(screenname.getFormatted(), null, parent);
+ ContactGroupIcqImpl parent =
+ ssContactList.findContactGroup(parentGroup);
+ srcContact = ssContactList.
+ createUnresolvedContact((ContactGroupIcqImpl)parent, screenname);
+
+ Buddy buddy = ((ContactIcqImpl)srcContact).getJoustSimBuddy();
+
+ if(buddy instanceof VolatileBuddy)
+ ((VolatileBuddy)buddy).setAwaitingAuthorization(true);
+
+ ContactGroupIcqImpl theAwaitingAuthorizationGroup =
+ ssContactList.findContactGroup(ssContactList.awaitingAuthorizationGroupName);
+
+
+ if(theAwaitingAuthorizationGroup == null)
+ {
+ List emptyBuddies = new LinkedList();
+ theAwaitingAuthorizationGroup = new ContactGroupIcqImpl(
+ new VolatileGroup(ssContactList.awaitingAuthorizationGroupName),
+ emptyBuddies, ssContactList, false);
+
+ ((RootContactGroupIcqImpl)ssContactList.getRootGroup()).
+ addSubGroup(theAwaitingAuthorizationGroup);
+
+ ssContactList.fireGroupEvent(theAwaitingAuthorizationGroup
+ , ServerStoredGroupEvent.GROUP_CREATED_EVENT);
+ }
+
+
+ ((ContactGroupIcqImpl)parent).removeContact(srcContact);
+ theAwaitingAuthorizationGroup.addContact(srcContact);
+
+ Object lock = new Object();
+ synchronized(lock){
+ try{ lock.wait(500); }catch(Exception e){}
+ };
+
+ fireSubscriptionMovedEvent(srcContact,
+ parent, theAwaitingAuthorizationGroup);
}
AuthorizationRequest authRequest =
@@ -1602,7 +1798,61 @@ private void updateBuddyyIcon(Screenname screenname, byte[] icon)
ssContactList.findContactByScreenName(screenname.getFormatted());
if(contact != null)
- contact.setImage(icon);
+ contact.setImage(icon);
+ }
+ }
+
+ private class AwaitingAuthorizationContactsPresenceTimer
+ extends TimerTask
+ {
+ public void run()
+ {
+ logger.trace("Running status retreiver for AwaitingAuthorizationContacts");
+
+ ContactGroupIcqImpl theAwaitingAuthorizationGroup =
+ ssContactList.findContactGroup(
+ ssContactList.awaitingAuthorizationGroupName);
+
+ if(theAwaitingAuthorizationGroup == null)
+ return;
+
+ Iterator iter = theAwaitingAuthorizationGroup.contacts();
+ while (iter.hasNext())
+ {
+ ContactIcqImpl sourceContact = (ContactIcqImpl)iter.next();
+
+ PresenceStatus newStatus = queryContactStatus(sourceContact.getAddress());
+
+ PresenceStatus oldStatus
+ = sourceContact.getPresenceStatus();
+
+ if(newStatus.equals(oldStatus))
+ continue;
+
+ sourceContact.updatePresenceStatus(newStatus);
+
+ ContactGroupIcqImpl parent
+ = ssContactList.findContactGroup(sourceContact);
+
+ fireContactPresenceStatusChangeEvent(sourceContact, theAwaitingAuthorizationGroup,
+ oldStatus, newStatus);
+
+ if( !newStatus.equals(IcqStatusEnum.OFFLINE) &&
+ !buddiesSeenAvailable.contains(sourceContact.getAddress()))
+ {
+ buddiesSeenAvailable.add(sourceContact.getAddress());
+ try
+ {
+ AuthorizationRequest req = new AuthorizationRequest();
+ req.setReason("I'm resending my request. Please authorize me!");
+
+ opSetExtendedAuthorizations.reRequestAuthorization(req, sourceContact);
+ } catch (OperationFailedException ex)
+ {
+ logger.error("failed to reRequestAuthorization", ex);
+ }
+ }
+ }
}
}
}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
index ecc842d7c..d140a9843 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/ProtocolProviderServiceIcqImpl.java
@@ -91,6 +91,11 @@ public class ProtocolProviderServiceIcqImpl
private ProtocolIconIcqImpl icqIcon
= new ProtocolIconIcqImpl();
+ /**
+ * Property whether we are using AIM or ICQ service
+ */
+ boolean USING_ICQ = true;
+
/**
* Returns the state of the registration of this protocol provider
* @return the RegistrationState that this provider is
@@ -238,7 +243,7 @@ public void register(SecurityAuthority authority)
// we must trim such passwords to 8 characters
if(password.length() > 8)
password = password.substring(0, 8);
-
+
//init the necessary objects
session = new DefaultAppSession();
aimSession = session.openAimSession(
@@ -247,7 +252,7 @@ public void register(SecurityAuthority authority)
new AimConnectionProperties(
new Screenname(getAccountID().getUserID())
, password));
-
+
String proxyAddress =
(String)getAccountID().getAccountProperties().get(
ProtocolProviderFactory.PROXY_ADDRESS);
@@ -382,6 +387,15 @@ protected void initialize(String screenname,
{
this.accountID = accountID;
+ try
+ {
+ Long.parseLong(accountID.getUserID());
+ } catch (NumberFormatException ex)
+ {
+ // if its icq its number can be parsed
+ USING_ICQ = false;
+ }
+
//initialize the presence operationset
OperationSetPersistentPresence persistentPresence =
new OperationSetPersistentPresenceIcqImpl(this, screenname);
@@ -409,42 +423,45 @@ protected void initialize(String screenname,
supportedOperationSets.put(
OperationSetTypingNotifications.class.getName(),
typingNotifications);
+
+ if(USING_ICQ)
+ {
+ this.infoRetreiver = new InfoRetreiver(this, screenname);
- this.infoRetreiver = new InfoRetreiver(this, screenname);
-
- OperationSetServerStoredContactInfo serverStoredContactInfo =
- new OperationSetServerStoredContactInfoIcqImpl(infoRetreiver);
+ OperationSetServerStoredContactInfo serverStoredContactInfo =
+ new OperationSetServerStoredContactInfoIcqImpl(infoRetreiver);
- supportedOperationSets.put(
- OperationSetServerStoredContactInfo.class.getName(),
- serverStoredContactInfo);
+ supportedOperationSets.put(
+ OperationSetServerStoredContactInfo.class.getName(),
+ serverStoredContactInfo);
- OperationSetServerStoredAccountInfo serverStoredAccountInfo =
- new OperationSetServerStoredAccountInfoIcqImpl
- (infoRetreiver, screenname, this);
-
- supportedOperationSets.put(
- OperationSetServerStoredAccountInfo.class.getName(),
- serverStoredAccountInfo);
+ OperationSetServerStoredAccountInfo serverStoredAccountInfo =
+ new OperationSetServerStoredAccountInfoIcqImpl
+ (infoRetreiver, screenname, this);
- OperationSetWebAccountRegistration webAccountRegistration =
- new OperationSetWebAccountRegistrationIcqImpl();
- supportedOperationSets.put(
- OperationSetWebAccountRegistration.class.getName(),
- webAccountRegistration);
+ supportedOperationSets.put(
+ OperationSetServerStoredAccountInfo.class.getName(),
+ serverStoredAccountInfo);
- OperationSetWebContactInfo webContactInfo =
- new OperationSetWebContactInfoIcqImpl();
- supportedOperationSets.put(
- OperationSetWebContactInfo.class.getName(),
- webContactInfo);
+ OperationSetWebAccountRegistration webAccountRegistration =
+ new OperationSetWebAccountRegistrationIcqImpl();
+ supportedOperationSets.put(
+ OperationSetWebAccountRegistration.class.getName(),
+ webAccountRegistration);
- OperationSetExtendedAuthorizationsIcqImpl extendedAuth =
- new OperationSetExtendedAuthorizationsIcqImpl(this);
- supportedOperationSets.put(
- OperationSetExtendedAuthorizations.class.getName(),
- extendedAuth);
+ OperationSetWebContactInfo webContactInfo =
+ new OperationSetWebContactInfoIcqImpl();
+ supportedOperationSets.put(
+ OperationSetWebContactInfo.class.getName(),
+ webContactInfo);
+
+ OperationSetExtendedAuthorizationsIcqImpl extendedAuth =
+ new OperationSetExtendedAuthorizationsIcqImpl(this);
+ supportedOperationSets.put(
+ OperationSetExtendedAuthorizations.class.getName(),
+ extendedAuth);
+ }
isInitialized = true;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/ServerStoredContactListIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/ServerStoredContactListIcqImpl.java
index 424f47086..c1ca82af6 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/ServerStoredContactListIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/ServerStoredContactListIcqImpl.java
@@ -94,7 +94,12 @@ public class ServerStoredContactListIcqImpl
/**
* Used for retrieveing missing nicks on specified contacts
*/
- private NickRetriever nickRetriever = new NickRetriever();
+ private NickRetriever nickRetriever = null;
+
+ /**
+ * Used for retrieveing missing nicks on specified contacts
+ */
+ static String awaitingAuthorizationGroupName = new String("Awaiting authorization");
/**
* Creates a ServerStoredContactList wrapper for the specified BuddyList.
@@ -119,10 +124,15 @@ public class ServerStoredContactListIcqImpl
// waiting for the first contact to come
// to start retreiving the missing nicknames
- parentOperationSet.addContactPresenceStatusListener(nickRetriever);
+ if(icqProvider.USING_ICQ)
+ {
+ nickRetriever = new NickRetriever();
+
+ parentOperationSet.addContactPresenceStatusListener(nickRetriever);
- // start the nick retreiver thread
- nickRetriever.start();
+ // start the nick retreiver thread
+ nickRetriever.start();
+ }
}
/**
@@ -169,7 +179,7 @@ void removeGroupListener(ServerStoredGroupListener listener)
* @param group the ContactGroup that has been created/modified/removed
* @param eventID the id of the event to generate.
*/
- private void fireGroupEvent(ContactGroupIcqImpl group, int eventID)
+ void fireGroupEvent(ContactGroupIcqImpl group, int eventID)
{
//bail out if no one's listening
if(parentOperationSet == null){
@@ -462,6 +472,7 @@ public void addContact(String screenname)
*/
ContactIcqImpl createVolatileContact(Screenname screenname)
{
+ logger.trace("createVolatileContact " + screenname);
//First create the new volatile contact;
Buddy volatileBuddy = new VolatileBuddy(screenname);
@@ -512,6 +523,7 @@ ContactIcqImpl createVolatileContact(Screenname screenname)
ContactIcqImpl createUnresolvedContact(ContactGroupIcqImpl parentGroup,
Screenname screenname)
{
+ logger.trace("createUnresolvedContact " + screenname);
//First create the new volatile contact;
Buddy volatileBuddy = new VolatileBuddy(screenname);
@@ -704,7 +716,8 @@ private ContactGroupIcqImpl getNonPersistentGroup()
ContactGroupIcqImpl gr =
(ContactGroupIcqImpl)getRootGroup().getGroup(i);
- if(!gr.isPersistent())
+ if(!gr.isPersistent() &&
+ !gr.getGroupName().equals(awaitingAuthorizationGroupName))
return gr;
}
@@ -721,7 +734,115 @@ private ContactGroupIcqImpl getNonPersistentGroup()
*/
protected void addContactForUpdate(ContactIcqImpl c)
{
- nickRetriever.addContact(c);
+ if(icqProvider.USING_ICQ)
+ nickRetriever.addContact(c);
+ }
+
+ protected void addAwaitingAuthorizationContact(Buddy buddy)
+ {
+ //Check whether a Awaiting authorization group already exists and if not create
+ //one
+ ContactGroupIcqImpl theAwaitingAuthorizationGroup =
+ findContactGroup(awaitingAuthorizationGroupName);
+
+ if(theAwaitingAuthorizationGroup == null)
+ {
+ List emptyBuddies = new LinkedList();
+ theAwaitingAuthorizationGroup = new ContactGroupIcqImpl(
+ new VolatileGroup(awaitingAuthorizationGroupName), emptyBuddies, this, false);
+
+ this.rootGroup.addSubGroup(theAwaitingAuthorizationGroup);
+
+ fireGroupEvent(theAwaitingAuthorizationGroup
+ , ServerStoredGroupEvent.GROUP_CREATED_EVENT);
+ }
+
+ ContactGroupIcqImpl oldParentGroup = null;
+ ContactIcqImpl newContact
+ = findContactByScreenName(buddy.getScreenname().getFormatted());
+
+ if(newContact != null)
+ oldParentGroup = (ContactGroupIcqImpl)newContact.getParentContactGroup();
+
+ boolean fireResolvedEvent = false;
+
+ if(newContact == null)
+ {
+ newContact = new ContactIcqImpl(
+ buddy, ServerStoredContactListIcqImpl.this, true, true);
+ }
+ else
+ {
+ oldParentGroup.removeContact(newContact);
+
+ newContact.setJoustSimBuddy(buddy);
+ newContact.setPersistent(true);
+ if(!newContact.isResolved())
+ {
+ newContact.setResolved(true);
+ fireResolvedEvent = true;
+ }
+ }
+
+ theAwaitingAuthorizationGroup.addContact(newContact);
+
+ int index = theAwaitingAuthorizationGroup.findContactIndex(newContact);
+
+ //register a listener for name changes of this buddy
+ buddy.addBuddyListener(jsimBuddyListener);
+
+ //tell listeners about the added group
+ if(oldParentGroup == null)
+ {
+ fireContactAdded(theAwaitingAuthorizationGroup, newContact, index);
+ }
+ else if(oldParentGroup != theAwaitingAuthorizationGroup)
+ {
+ fireContactMoved(oldParentGroup, theAwaitingAuthorizationGroup
+ , newContact, index);
+ }
+
+ //fire an event in case the contact has just been resolved.
+ if(fireResolvedEvent)
+ {
+ fireContactResolved(theAwaitingAuthorizationGroup, newContact);
+ }
+ }
+
+ protected void moveAwaitingAuthorizationContact(ContactIcqImpl contact)
+ {
+ ContactGroupIcqImpl parentGroup = findGroup(contact.getJoustSimBuddy());
+
+ if(parentGroup == null)
+ return;
+
+ findContactGroup(awaitingAuthorizationGroupName).removeContact(contact);
+ parentGroup.addContact(contact);
+
+ fireContactMoved(findContactGroup(awaitingAuthorizationGroupName),
+ parentGroup, contact, parentGroup.findContactIndex(contact));
+ }
+
+ ContactGroupIcqImpl findGroup(Buddy buddy)
+ {
+ Iterator iter = rootGroup.subgroups();
+ while (iter.hasNext())
+ {
+ ContactGroupIcqImpl elem = (ContactGroupIcqImpl) iter.next();
+
+ if(!elem.isPersistent() || !elem.isResolved())
+ continue;
+
+ Iterator bs = elem.getJoustSimSourceGroup().getBuddiesCopy().iterator();
+ while (bs.hasNext())
+ {
+ Buddy b = (Buddy) bs.next();
+ if(b == buddy)
+ return elem;
+ }
+ }
+
+ return null;
}
private class BuddyListListener
@@ -850,6 +971,7 @@ public void groupRemoved(BuddyList list, List oldItems, List newItems,
public void buddyAdded(BuddyList list, Group joustSimGroup, List oldItems,
List newItems, Buddy buddy)
{
+ logger.trace("Received buddyAdded " + buddy);
//it is possible that the buddy being added is already in our
//contact list. For example if they have sent a message to us they
//would have been added to the local contact list as a
@@ -870,6 +992,12 @@ public void buddyAdded(BuddyList list, Group joustSimGroup, List oldItems,
+ joustSimGroup + " found for buddy: " + buddy);
return;
}
+
+ if(buddy.isAwaitingAuthorization())
+ {
+ addAwaitingAuthorizationContact(buddy);
+ return;
+ }
if(newContact == null)
{
@@ -931,11 +1059,38 @@ public void buddyRemoved(BuddyList list, Group group, List oldItems,
ContactGroupIcqImpl parentGroup = findContactGroup(group);
ContactIcqImpl contactToRemove = parentGroup.findContact(buddy);
- parentGroup.removeContact(contactToRemove);
+ if(contactToRemove == null)
+ {
+ // this buddy is not in this group
+ // it can be in awaiting authorization group
+ // will search it there
+
+ ContactGroupIcqImpl theAwaitingAuthorizationGroup =
+ findContactGroup(awaitingAuthorizationGroupName);
+ if(theAwaitingAuthorizationGroup != null)
+ {
+ contactToRemove =
+ theAwaitingAuthorizationGroup.
+ findContact(buddy.getScreenname().getFormatted());
+
+ if(contactToRemove == null)
+ return;
+
+ theAwaitingAuthorizationGroup.removeContact(contactToRemove);
+
+ buddy.removeBuddyListener(jsimBuddyListener);
+
+ fireContactRemoved(theAwaitingAuthorizationGroup, contactToRemove);
+ }
+ }
+ else
+ {
+ parentGroup.removeContact(contactToRemove);
- buddy.removeBuddyListener(jsimBuddyListener);
+ buddy.removeBuddyListener(jsimBuddyListener);
- fireContactRemoved(parentGroup, contactToRemove);
+ fireContactRemoved(parentGroup, contactToRemove);
+ }
}
/**
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/VolatileBuddy.java b/src/net/java/sip/communicator/impl/protocol/icq/VolatileBuddy.java
index aea4cbb6d..f05267fbf 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/VolatileBuddy.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/VolatileBuddy.java
@@ -18,6 +18,12 @@ class VolatileBuddy
implements Buddy
{
private Screenname screenname = null;
+
+ /**
+ * Use when creating unresolved contact during authorization process
+ * to display contact in the group with awaiting authorization contacts
+ */
+ private boolean isAwaitingAuthorization = false;
/**
* Constructs a VolatileBuddy from the specified screenname.
@@ -56,5 +62,10 @@ public void addBuddyListener(BuddyListener listener){}
public BuddyList getBuddyList(){return null;}
public boolean isActive(){return false;}
public void removeBuddyListener(BuddyListener listener){}
- public boolean isAwaitingAuthorization(){return false;}
-}
+ public boolean isAwaitingAuthorization(){return isAwaitingAuthorization;}
+
+ public void setAwaitingAuthorization(boolean value)
+ {
+ this.isAwaitingAuthorization = value;
+ }
+}
\ No newline at end of file
diff --git a/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPersistentPresence.java b/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPersistentPresence.java
index 6f67b7100..d99252905 100644
--- a/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPersistentPresence.java
+++ b/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPersistentPresence.java
@@ -141,7 +141,8 @@ public void testRetrievingServerStoredContactList()
// the sever creates a group NotInContactList,
// beacuse the buddy we are sending message to is not in
// the contactlist. So this group must be ignored
- if(!group.getGroupName().equals("NotInContactList"))
+ // all not persistent groups must be ignored
+ if(group.isPersistent())
{
assertNotNull("Group " + group.getGroupName() +
" was returned by "
diff --git a/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPresence.java b/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPresence.java
index 6ac2e301b..9aa39a5b6 100644
--- a/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPresence.java
+++ b/test/net/java/sip/communicator/slick/protocol/icq/TestOperationSetPresence.java
@@ -575,12 +575,27 @@ public void postTestSubscribe()
//don't want any more events
operationSetPresence.removeSubscriptionListener(subEvtCollector);
}
-
- assertEquals("Subscription event dispatching failed."
- , 1, subEvtCollector.collectedEvents.size());
- EventObject evt =
- (EventObject)subEvtCollector.collectedEvents.get(0);
+ // after adding awaitingAuthorization group here are catched 3 events
+ // 1 - creating unresolved contact
+ // 2 - move of the contact to awaitingAuthorization group
+ // 3 - move of the contact from awaitingAuthorization group to original group
+ assertTrue("Subscription event dispatching failed."
+ , subEvtCollector.collectedEvents.size() > 0);
+
+ EventObject evt = null;
+
+ Iterator events = subEvtCollector.collectedEvents.iterator();
+ while (events.hasNext())
+ {
+ Object elem = events.next();
+ if(elem instanceof SubscriptionEvent)
+ {
+ if(((SubscriptionEvent)elem).getEventID()
+ == SubscriptionEvent.SUBSCRIPTION_CREATED)
+ evt = (SubscriptionEvent)elem;
+ }
+ }
Object source = null;
Contact srcContact = null;