From 0dac2cc68c40b65a3ca976e7d64e1bc5af68c949 Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Thu, 12 Apr 2007 11:28:48 +0000 Subject: [PATCH] Improve jabber image retreiving --- .../protocol/jabber/ContactJabberImpl.java | 41 ++----- ...rationSetPersistentPresenceJabberImpl.java | 40 ++++++ .../ProtocolProviderServiceJabberImpl.java | 6 +- .../ServerStoredContactListJabberImpl.java | 116 +++++++++++++++++- .../event/ContactPropertyChangeEvent.java | 6 + 5 files changed, 174 insertions(+), 35 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java index beaf0562f..46ab8bdd1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java @@ -7,7 +7,6 @@ package net.java.sip.communicator.impl.protocol.jabber; import org.jivesoftware.smack.*; -import org.jivesoftware.smackx.packet.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.service.protocol.jabberconstants.*; @@ -89,13 +88,24 @@ public boolean isLocal() return isLocal; } + /** + * Returns the image of the contact or null if absent + */ public byte[] getImage() { if(image == null) - image = getAvatar(); + ssclCallback.addContactForImageUpdate(this); return image; } + + /** + * Set the image of the contact + */ + void setImage(byte[] imgBytes) + { + this.image = imgBytes; + } /** * Returns a hashCode for this contact. The returned hashcode is actually @@ -292,31 +302,4 @@ RosterEntry getSourceEntry() { return rosterEntry; } - - private byte[] getAvatar() - { - try - { - XMPPConnection connection = - ssclCallback.getParentProvider().getConnection(); - - if(connection == null || !connection.isAuthenticated()) - return null; - - VCard card = new VCard(); - card.load( - connection, - getAddress()); - - return card.getAvatar(); - } - catch (Exception exc) - { - logger.error("Cannot load image for contact " - + this + " : " + exc.getMessage() - , exc); - } - - return null; - } } \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java index 4b26bcfd7..90cde8ea4 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java @@ -998,6 +998,46 @@ private void fireContactPresenceStatusChangeEvent( listener.contactPresenceStatusChanged(evt); } } + + /** + * Notify all subscription listeners of the corresponding contact property + * change event. + * + * @param eventID the String ID of the event to dispatch + * @param sourceContact the ContactJabberImpl instance that this event is + * pertaining to. + * @param oldValue the value that the changed property had before the change + * occurred. + * @param newValue the value that the changed property currently has (after + * the change has occurred). + */ + void fireContactPropertyChangeEvent( String eventID, + ContactJabberImpl sourceContact, + Object oldValue, + Object newValue) + { + ContactPropertyChangeEvent evt = + new ContactPropertyChangeEvent(sourceContact, eventID + , oldValue, newValue); + + logger.debug("Dispatching a Contact Property Change Event to" + +subscriptionListeners.size() + " listeners. Evt="+evt); + + Iterator listeners = null; + + synchronized (subscriptionListeners) + { + listeners = new ArrayList(subscriptionListeners).iterator(); + } + + while (listeners.hasNext()) + { + SubscriptionListener listener + = (SubscriptionListener) listeners.next(); + + listener.contactModified(evt); + } + } /** * diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 78074b240..ddb910133 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -298,11 +298,7 @@ private void connectAndLogin(SecurityAuthority authority) { logger.error("Failed to establish a Jabber connection for " + getAccountID().getAccountUniqueID(), exc); - fireRegistrationStateChanged( - getRegistrationState() - , RegistrationState.CONNECTION_FAILED - , OperationFailedException.NETWORK_FAILURE - , null); + throw new OperationFailedException( "Failed to establish a Jabber connection for " + getAccountID().getAccountUniqueID() diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java index 5d427f91d..7060fc4f6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java @@ -10,6 +10,7 @@ import org.jivesoftware.smack.*; import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smackx.packet.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; @@ -58,6 +59,11 @@ public class ServerStoredContactListJabberImpl * names or other properties, removal or creation of groups. */ private Vector serverStoredGroupListeners = new Vector(); + + /** + * Thread retreiving images for contacts + */ + private ImageRetriever imageRetriever = null; /** * Creates a ServerStoredContactList wrapper for the specified BuddyList. @@ -746,6 +752,23 @@ void fireContactResolved( ContactGroupJabberImpl parentGroup, parentOperationSet.fireSubscriptionEvent( SubscriptionEvent.SUBSCRIPTION_RESOLVED, contact, parentGroup); } + + /** + * when there is no image for contact we must retreive it + * add contacts for image update + * + * @param c ContactJabberImpl + */ + protected void addContactForImageUpdate(ContactJabberImpl c) + { + if(imageRetriever == null) + { + imageRetriever = new ImageRetriever(); + imageRetriever.start(); + } + + imageRetriever.addContact(c); + } private class ChangeListener implements RosterListener @@ -938,4 +961,95 @@ else if(group instanceof RootContactGroupJabberImpl) public void presenceChanged(Presence presence) {} } -} + + private class ImageRetriever + extends Thread + { + /** + * list with the accounts with missing image + */ + private Vector contactsForUpdate = new Vector(); + + public void run() + { + try + { + Collection copyContactsForUpdate = null; + while (true) + { + synchronized(contactsForUpdate){ + + if(contactsForUpdate.isEmpty()) + contactsForUpdate.wait(); + + copyContactsForUpdate = new Vector(contactsForUpdate); + contactsForUpdate.clear(); + } + + Iterator iter = copyContactsForUpdate.iterator(); + while (iter.hasNext()) + { + ContactJabberImpl contact = (ContactJabberImpl) iter.next(); + + byte[] imgBytes = getAvatar(contact); + + if(imgBytes != null) + { + contact.setImage(imgBytes); + + parentOperationSet.fireContactPropertyChangeEvent( + ContactPropertyChangeEvent.PROPERTY_IMAGE, + contact, null, imgBytes); + } + } + } + } + catch (InterruptedException ex) + { + logger.error("NickRetriever error waiting will stop now!", ex); + } + } + + /** + * Add contact for retreiving + * if the provider is register notify the retreiver to get the nicks + * if we are not registered add a listener to wiat for registering + * + * @param contact ContactJabberImpl + */ + synchronized void addContact(ContactJabberImpl contact) + { + synchronized(contactsForUpdate){ + if (!contactsForUpdate.contains(contact)) + { + contactsForUpdate.add(contact); + contactsForUpdate.notifyAll(); + } + } + } + + private byte[] getAvatar(ContactJabberImpl contact) + { + try + { + XMPPConnection connection = jabberProvider.getConnection(); + + if(connection == null || !connection.isAuthenticated()) + return null; + + VCard card = new VCard(); + card.load(connection, contact.getAddress()); + + return card.getAvatar(); + } + catch (Exception exc) + { + logger.error("Cannot load image for contact " + + this + " : " + exc.getMessage() + , exc); + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/service/protocol/event/ContactPropertyChangeEvent.java b/src/net/java/sip/communicator/service/protocol/event/ContactPropertyChangeEvent.java index 3a608b7b6..44b1ca4d3 100644 --- a/src/net/java/sip/communicator/service/protocol/event/ContactPropertyChangeEvent.java +++ b/src/net/java/sip/communicator/service/protocol/event/ContactPropertyChangeEvent.java @@ -17,6 +17,12 @@ public class ContactPropertyChangeEvent * contact. */ public static final String PROPERTY_DISPLAY_NAME = "DisplayName"; + + /** + * Indicates that a change has occurred in the image of the source + * contact. + */ + public static final String PROPERTY_IMAGE = "Image"; /** * Creates a ContactPropertyChangeEvent indicating that a change has