diff --git a/resources/images/protocol/jabber/jabber48x48.png b/resources/images/protocol/jabber/logo48x48.png similarity index 100% rename from resources/images/protocol/jabber/jabber48x48.png rename to resources/images/protocol/jabber/logo48x48.png diff --git a/resources/images/protocol/jabber/jabber16x16-away.png b/resources/images/protocol/jabber/status16x16-away.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-away.png rename to resources/images/protocol/jabber/status16x16-away.png diff --git a/resources/images/protocol/jabber/jabber16x16-connecting.gif b/resources/images/protocol/jabber/status16x16-connecting.gif similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-connecting.gif rename to resources/images/protocol/jabber/status16x16-connecting.gif diff --git a/resources/images/protocol/jabber/jabber16x16-dnd.png b/resources/images/protocol/jabber/status16x16-dnd.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-dnd.png rename to resources/images/protocol/jabber/status16x16-dnd.png diff --git a/resources/images/protocol/jabber/jabber16x16-ffc.png b/resources/images/protocol/jabber/status16x16-ffc.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-ffc.png rename to resources/images/protocol/jabber/status16x16-ffc.png diff --git a/resources/images/protocol/jabber/jabber16x16-invisible.png b/resources/images/protocol/jabber/status16x16-invisible.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-invisible.png rename to resources/images/protocol/jabber/status16x16-invisible.png diff --git a/resources/images/protocol/jabber/jabber16x16-na.png b/resources/images/protocol/jabber/status16x16-na.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-na.png rename to resources/images/protocol/jabber/status16x16-na.png diff --git a/resources/images/protocol/jabber/jabber16x16-offline.png b/resources/images/protocol/jabber/status16x16-offline.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-offline.png rename to resources/images/protocol/jabber/status16x16-offline.png diff --git a/resources/images/protocol/jabber/jabber16x16-online.png b/resources/images/protocol/jabber/status16x16-online.png similarity index 100% rename from resources/images/protocol/jabber/jabber16x16-online.png rename to resources/images/protocol/jabber/status16x16-online.png 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 f29bf9ca3..af555ed35 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java @@ -14,6 +14,7 @@ /** * The Jabber implementation of the service.protocol.Contact interface. * @author Damian Minkov + * @author Lubomir Marinov */ public class ContactJabberImpl implements Contact @@ -24,7 +25,7 @@ public class ContactJabberImpl private RosterEntry rosterEntry = null; private boolean isLocal = false; private byte[] image = null; - private PresenceStatus status = JabberStatusEnum.OFFLINE; + private PresenceStatus status; private ServerStoredContactListJabberImpl ssclCallback = null; private boolean isPersistent = false; private boolean isResolved = false; @@ -51,6 +52,10 @@ public class ContactJabberImpl this.ssclCallback = ssclCallback; this.isPersistent = isPersistent; this.isResolved = isResolved; + + this.status = + ((ProtocolProviderServiceJabberImpl) getProtocolProvider()) + .getJabberStatusEnum().getStatus(JabberStatusEnum.OFFLINE); } ContactJabberImpl(String id, @@ -62,6 +67,10 @@ public class ContactJabberImpl this.ssclCallback = ssclCallback; this.isPersistent = isPersistent; this.isResolved = false; + + this.status = + ((ProtocolProviderServiceJabberImpl) getProtocolProvider()) + .getJabberStatusEnum().getStatus(JabberStatusEnum.OFFLINE); } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java index b977225fc..3da178102 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java @@ -558,8 +558,8 @@ void fireUnregisterd() RegistrationStateChangeEvent.REASON_INTERNAL_ERROR, null); opSetPersPresence.fireProviderPresenceStatusChangeEvent( - opSetPersPresence.getPresenceStatus(), - JabberStatusEnum.OFFLINE); + opSetPersPresence.getPresenceStatus(), jabberProvider + .getJabberStatusEnum().getStatus(JabberStatusEnum.OFFLINE)); } } 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 1c0e180cc..57f418266 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java @@ -26,6 +26,7 @@ * the buddy contact list and adding listeners for changes in its layout. * * @author Damian Minkov + * @author Lubomir Marinov */ public class OperationSetPersistentPresenceJabberImpl implements OperationSetPersistentPresence @@ -49,7 +50,7 @@ public class OperationSetPersistentPresenceJabberImpl * The presence status that we were last notified of etnering. * The initial one is OFFLINE */ - private PresenceStatus currentStatus = JabberStatusEnum.OFFLINE; + private PresenceStatus currentStatus; /** * The list of listeners interested in receiving changes in our local @@ -69,19 +70,6 @@ public class OperationSetPersistentPresenceJabberImpl */ private Vector contactPresenceStatusListeners = new Vector(); - /** - * The array list we use when returning from the getSupportedStatusSet() - * method. - */ - private static final ArrayList supportedPresenceStatusSet = new ArrayList(); - static{ - supportedPresenceStatusSet.add(JabberStatusEnum.AWAY); - supportedPresenceStatusSet.add(JabberStatusEnum.DO_NOT_DISTURB); - supportedPresenceStatusSet.add(JabberStatusEnum.FREE_FOR_CHAT); - supportedPresenceStatusSet.add(JabberStatusEnum.OFFLINE); - supportedPresenceStatusSet.add(JabberStatusEnum.AVAILABLE); - } - /** * A map containing bindings between SIP Communicator's jabber presence status * instances and Jabber status codes @@ -113,6 +101,10 @@ public OperationSetPersistentPresenceJabberImpl( { this.jabberProvider = provider; + currentStatus = + this.jabberProvider.getJabberStatusEnum().getStatus( + JabberStatusEnum.OFFLINE); + ssContactList = new ServerStoredContactListJabberImpl( this , provider); this.jabberProvider.addRegistrationStateChangeListener( @@ -353,7 +345,7 @@ public ContactGroup getServerStoredContactListRoot() */ public Iterator getSupportedStatusSet() { - return supportedPresenceStatusSet.iterator(); + return jabberProvider.getJabberStatusEnum().getSupportedStatusSet(); } /** @@ -403,12 +395,25 @@ public void publishPresenceStatus(PresenceStatus status, { assertConnected(); - if (!(status instanceof JabberStatusEnum)) - throw new IllegalArgumentException( - status + " is not a valid Jabber status"); + JabberStatusEnum jabberStatusEnum = + jabberProvider.getJabberStatusEnum(); + boolean isValidStatus = false; + for (Iterator supportedStatusIter = + jabberStatusEnum.getSupportedStatusSet(); supportedStatusIter + .hasNext();) + { + if (supportedStatusIter.next().equals(status)) + { + isValidStatus = true; + break; + } + } + if (!isValidStatus) + throw new IllegalArgumentException(status + + " is not a valid Jabber status"); Presence presence = null; - if(((JabberStatusEnum)status).equals(JabberStatusEnum.OFFLINE)) + if (status.equals(jabberStatusEnum.getStatus(JabberStatusEnum.OFFLINE))) { presence = new Presence(Presence.Type.unavailable); jabberProvider.unregister(); @@ -416,7 +421,7 @@ public void publishPresenceStatus(PresenceStatus status, else { presence = new Presence(Presence.Type.available); - presence.setMode(presenceStatusToJabberMode((JabberStatusEnum)status)); + presence.setMode(presenceStatusToJabberMode(status)); presence.setPriority(resourcePriority); presence.setStatus(statusMessage); presence.addExtension(new Version()); @@ -458,9 +463,10 @@ public PresenceStatus queryContactStatus(String contactIdentifier) throws getPresence(contactIdentifier); if(presence != null) - return jabberStatusToPresenceStatus(presence); + return jabberStatusToPresenceStatus(presence, jabberProvider); else - return JabberStatusEnum.OFFLINE; + return jabberProvider.getJabberStatusEnum().getStatus( + JabberStatusEnum.OFFLINE); } /** @@ -659,28 +665,32 @@ public void unsubscribe(Contact contact) throws IllegalArgumentException, * @return a PresenceStatus instance representation of the Jabber Status * parameter. The returned result is one of the JabberStatusEnum fields. */ - public static JabberStatusEnum jabberStatusToPresenceStatus(Presence presence) + public static PresenceStatus jabberStatusToPresenceStatus( + Presence presence, ProtocolProviderServiceJabberImpl jabberProvider) { + JabberStatusEnum jabberStatusEnum = + jabberProvider.getJabberStatusEnum(); // fixing issue: 336 // from the smack api : // A null presence mode value is interpreted to be the same thing // as Presence.Mode.available. if(presence.getMode() == null && presence.isAvailable()) - return JabberStatusEnum.AVAILABLE; + return jabberStatusEnum.getStatus(JabberStatusEnum.AVAILABLE); else if(presence.getMode() == null && !presence.isAvailable()) - return JabberStatusEnum.OFFLINE; + return jabberStatusEnum.getStatus(JabberStatusEnum.OFFLINE); Presence.Mode mode = presence.getMode(); if(mode.equals(Presence.Mode.available)) - return JabberStatusEnum.AVAILABLE; + return jabberStatusEnum.getStatus(JabberStatusEnum.AVAILABLE); else if(mode.equals(Presence.Mode.away)) - return JabberStatusEnum.AWAY; + return jabberStatusEnum.getStatus(JabberStatusEnum.AWAY); else if(mode.equals(Presence.Mode.chat)) - return JabberStatusEnum.FREE_FOR_CHAT; + return jabberStatusEnum.getStatus(JabberStatusEnum.FREE_FOR_CHAT); else if(mode.equals(Presence.Mode.dnd)) - return JabberStatusEnum.DO_NOT_DISTURB; - else return JabberStatusEnum.OFFLINE; + return jabberStatusEnum.getStatus(JabberStatusEnum.DO_NOT_DISTURB); + else + return jabberStatusEnum.getStatus(JabberStatusEnum.OFFLINE); } /** @@ -690,10 +700,10 @@ else if(mode.equals(Presence.Mode.dnd)) * @param status the jabberStatus * @return a PresenceStatus instance */ - public static Presence.Mode presenceStatusToJabberMode( - JabberStatusEnum status) + public static Presence.Mode presenceStatusToJabberMode(PresenceStatus status) { - return (Presence.Mode)scToJabberModesMappings.get(status); + return (Presence.Mode) scToJabberModesMappings.get(status + .getStatusName()); } /** @@ -813,7 +823,8 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt) new ContactChangesListener()); fireProviderPresenceStatusChangeEvent(currentStatus, - JabberStatusEnum.AVAILABLE); + jabberProvider.getJabberStatusEnum().getStatus( + JabberStatusEnum.AVAILABLE)); // init ssList ssContactList.init(); @@ -827,7 +838,10 @@ else if(evt.getNewState() == RegistrationState.UNREGISTERED //well as set to offline all contacts in our contact list that //were online PresenceStatus oldStatus = currentStatus; - currentStatus = JabberStatusEnum.OFFLINE; + PresenceStatus offlineStatus = + jabberProvider.getJabberStatusEnum().getStatus( + JabberStatusEnum.OFFLINE); + currentStatus = offlineStatus; fireProviderPresenceStatusChangeEvent(oldStatus, currentStatus); @@ -856,12 +870,12 @@ else if(evt.getNewState() == RegistrationState.UNREGISTERED if(!oldContactStatus.isOnline()) continue; - contact.updatePresenceStatus(JabberStatusEnum.OFFLINE); + contact.updatePresenceStatus(offlineStatus); fireContactPresenceStatusChangeEvent( contact , contact.getParentContactGroup() - , oldContactStatus, JabberStatusEnum.OFFLINE); + , oldContactStatus, offlineStatus); } } @@ -880,12 +894,12 @@ else if(evt.getNewState() == RegistrationState.UNREGISTERED if (!oldContactStatus.isOnline()) continue; - contact.updatePresenceStatus(JabberStatusEnum.OFFLINE); + contact.updatePresenceStatus(offlineStatus); fireContactPresenceStatusChangeEvent( contact , contact.getParentContactGroup() - , oldContactStatus, JabberStatusEnum.OFFLINE); + , oldContactStatus, offlineStatus); } } @@ -1082,7 +1096,8 @@ public void presenceChanged(Presence presence) PresenceStatus oldStatus = sourceContact.getPresenceStatus(); - PresenceStatus newStatus = jabberStatusToPresenceStatus(presence); + PresenceStatus newStatus = + jabberStatusToPresenceStatus(presence, jabberProvider); // when old and new status are the same do nothing // no change diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolIconJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolIconJabberImpl.java index 5882b994a..5480b3ffe 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolIconJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolIconJabberImpl.java @@ -10,6 +10,7 @@ import java.util.*; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.jabberconstants.*; import net.java.sip.communicator.util.*; /** @@ -17,22 +18,38 @@ * interface in order to provide a jabber icon image in two different sizes. * * @author Yana Stamcheva + * @author Lubomir Marinov */ public class ProtocolIconJabberImpl implements ProtocolIcon { private static Logger logger = Logger.getLogger(ProtocolIconJabberImpl.class); + + /** + * The path where all protocol icons are placed. + */ + private final String iconPath; /** * A hash table containing the protocol icon in different sizes. */ - private static Hashtable iconsTable = new Hashtable(); - static { - iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, - loadIcon("resources/images/protocol/jabber/jabber16x16-online.png")); + private final Hashtable iconsTable = new Hashtable(); - iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, - loadIcon("resources/images/protocol/jabber/jabber48x48.png")); + /** + * Creates an instance of this class by passing to it the path, where all + * protocol icons are placed. + * + * @param iconPath the protocol icon path + */ + public ProtocolIconJabberImpl(String iconPath) + { + this.iconPath = iconPath; + + iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, loadIcon(iconPath + + "/status16x16-online.png")); + + iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, loadIcon(iconPath + + "/logo48x48.png")); } /** @@ -68,7 +85,7 @@ public byte[] getIcon(String iconSize) */ public byte[] getConnectingIcon() { - return loadIcon("resources/images/protocol/jabber/jabber16x16-connecting.gif"); + return loadIcon(iconPath + "/status16x16-connecting.gif"); } /** @@ -76,17 +93,9 @@ public byte[] getConnectingIcon() * @param imagePath The identifier of the image. * @return The image for the given identifier. */ - public static byte[] loadIcon(String imagePath) { - InputStream is = ProtocolIconJabberImpl.class - .getClassLoader().getResourceAsStream(imagePath); - - byte[] icon = null; - try { - icon = new byte[is.available()]; - is.read(icon); - } catch (IOException e) { - logger.error("Failed to load icon: " + imagePath, e); - } - return icon; + public static byte[] loadIcon(String imagePath) + { + return JabberStatusEnum.loadIcon(imagePath, + ProtocolIconJabberImpl.class); } } 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 1fbb5dafa..6fc4d1b4a 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -24,6 +24,7 @@ * * @author Damian Minkov * @author Symphorien Wanko + * @author Lubomir Marinov */ public class ProtocolProviderServiceJabberImpl extends AbstractProtocolProviderService @@ -72,8 +73,7 @@ public class ProtocolProviderServiceJabberImpl /** * The icon corresponding to the jabber protocol. */ - private ProtocolIconJabberImpl jabberIcon - = new ProtocolIconJabberImpl(); + private ProtocolIconJabberImpl jabberIcon; /** * A set of features supported by our Jabber implementation. @@ -101,6 +101,8 @@ public class ProtocolProviderServiceJabberImpl */ private ServiceDiscoveryManager discoveryManager = null; + private JabberStatusEnum jabberStatusEnum; + /** * Returns the state of the registration of this protocol provider * @return the RegistrationState that this provider is @@ -500,6 +502,18 @@ protected void initialize(String screenname, { this.accountID = accountID; + String protocolIconPath = + (String) accountID.getAccountProperties().get( + ProtocolProviderFactory.PROTOCOL_ICON_PATH); + if (protocolIconPath == null) + { + protocolIconPath = "resources/images/protocol/jabber"; + } + + jabberIcon = new ProtocolIconJabberImpl(protocolIconPath); + + jabberStatusEnum = new JabberStatusEnum(protocolIconPath); + //this feature is mandatory to be compliant with Service Discovery supportedFeatures.add("http://jabber.org/protocol/disco#info"); @@ -690,8 +704,8 @@ public void connectionClosed() .get(OperationSetPersistentPresence.class.getName()); opSetPersPresence.fireProviderPresenceStatusChangeEvent( - opSetPersPresence.getPresenceStatus(), - JabberStatusEnum.OFFLINE); + opSetPersPresence.getPresenceStatus(), getJabberStatusEnum() + .getStatus(JabberStatusEnum.OFFLINE)); } /** @@ -749,4 +763,14 @@ public ProtocolIcon getProtocolIcon() { return jabberIcon; } + + /** + * Returns the current instance of JabberStatusEnum. + * + * @return the current instance of JabberStatusEnum. + */ + JabberStatusEnum getJabberStatusEnum() + { + return jabberStatusEnum; + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/geolocation/GeolocationPresence.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/geolocation/GeolocationPresence.java index 8c71d6d72..5277e4c55 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/geolocation/GeolocationPresence.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/geolocation/GeolocationPresence.java @@ -41,7 +41,7 @@ public GeolocationPresence(OperationSetPresence persistentPresence) // set the presence mode (available, NA, free for chat) this.prez.setMode( OperationSetPersistentPresenceJabberImpl.presenceStatusToJabberMode( - (JabberStatusEnum) persistentPresence + persistentPresence .getPresenceStatus())); } diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/resources.properties b/src/net/java/sip/communicator/plugin/jabberaccregwizz/resources.properties index d69c04540..b76d79887 100755 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/resources.properties +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/resources.properties @@ -1,4 +1,4 @@ commentsFile=net/java/sip/communicator/plugin/jabberaccregwizz/resources/servercomments.xml -protocolIcon=resources/images/protocol/jabber/jabber16x16-online.png -pageImage=resources/images/protocol/jabber/jabber48x48.png +protocolIcon=resources/images/protocol/jabber/status16x16-online.png +pageImage=resources/images/protocol/jabber/logo48x48.png diff --git a/src/net/java/sip/communicator/service/protocol/jabberconstants/JabberStatusEnum.java b/src/net/java/sip/communicator/service/protocol/jabberconstants/JabberStatusEnum.java index cac9a782a..333db6be4 100644 --- a/src/net/java/sip/communicator/service/protocol/jabberconstants/JabberStatusEnum.java +++ b/src/net/java/sip/communicator/service/protocol/jabberconstants/JabberStatusEnum.java @@ -1,112 +1,266 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.service.protocol.jabberconstants; import java.io.*; +import java.net.*; import java.util.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; /** - * An enumeration containing all status instances that MUST be supported by - * an implementation of the Jabber protocol. Implementations may - * support other forms of PresenceStatus but they MUST ALL support those - * enumerated here. - *

- * For testing purposes, this class also provides a List containing - * all of the status fields. - * - * @author Damian Minkov + * The JabberStatusEnum gives access to presence states for the Sip + * protocol. All status icons corresponding to presence states are located with + * the help of the imagePath parameter + * + * @author Emil Ivov + * @author Yana Stamcheva + * @author Lubomir Marinov */ public class JabberStatusEnum - extends PresenceStatus { - private static Logger logger = Logger.getLogger(JabberStatusEnum.class); + private static final Logger logger = + Logger.getLogger(JabberStatusEnum.class); + + /** + * The Online status. Indicate that the user is able and willing to + * communicate. + */ + public static final String AVAILABLE = "Available"; + + /** + * The Away status. Indicates that the user has connectivity but might not + * be able to immediately act upon initiation of communication. + */ + public static final String AWAY = "Away"; + + /** + * The DND status. Indicates that the user has connectivity but prefers not + * to be contacted. + */ + public static final String DO_NOT_DISTURB = "Do Not Disturb"; /** * The Free For Chat status. Indicates that the user is eager to * communicate. */ - public static final JabberStatusEnum FREE_FOR_CHAT - = new JabberStatusEnum(85, "Free For Chat", - loadIcon("resources/images/protocol/jabber/jabber16x16-ffc.png")); + public static final String FREE_FOR_CHAT = "Free For Chat"; + + /** + * Indicates an Offline status or status with 0 connectivity. + */ + public static final String OFFLINE = "Offline"; + + /** + * The Unknown status. Indicate that we don't know if the user is present or + * not. + */ + public static final String UNKNOWN = "Unknown"; /** * The Online status. Indicate that the user is able and willing to * communicate. */ - public static final JabberStatusEnum AVAILABLE - = new JabberStatusEnum(65, "Available", - loadIcon("resources/images/protocol/jabber/jabber16x16-online.png")); + private JabberPresenceStatus availableStatus; + + /** + * The Away status. Indicates that the user has connectivity but might not + * be able to immediately act upon initiation of communication. + */ + private JabberPresenceStatus awayStatus; + + /** + * The DND status. Indicates that the user has connectivity but prefers not + * to be contacted. + */ + private JabberPresenceStatus doNotDisturbStatus; /** - * The Away status. Indicates that the user has connectivity but might - * not be able to immediately act upon initiation of communication. + * The Free For Chat status. Indicates that the user is eager to + * communicate. */ - public static final JabberStatusEnum AWAY - = new JabberStatusEnum(40, "Away", - loadIcon("resources/images/protocol/jabber/jabber16x16-away.png")); + private JabberPresenceStatus freeForChatStatus; /** - * The DND status. Indicates that the user has connectivity but prefers - * not to be contacted. + * Indicates an Offline status or status with 0 connectivity. */ - public static final JabberStatusEnum DO_NOT_DISTURB - = new JabberStatusEnum(30, "Do Not Disturb", - loadIcon("resources/images/protocol/jabber/jabber16x16-dnd.png")); + private JabberPresenceStatus offlineStatus; /** - * The Offline status. Indicates the user does not seem to be connected - * to the network or at least does not want us to know she is + * The supported status set stores all statuses supported by this protocol + * implementation. */ - public static final JabberStatusEnum OFFLINE - = new JabberStatusEnum(0, "Offline", - loadIcon("resources/images/protocol/jabber/jabber16x16-offline.png")); + public List supportedStatusSet = + new LinkedList(); /** - * The minimal set of states that any implementation must support. + * The Unknown status. Indicate that we don't know if the user is present or + * not. */ - public static final ArrayList jabberStatusSet =new ArrayList(); - static{ - jabberStatusSet.add(FREE_FOR_CHAT); - jabberStatusSet.add(AVAILABLE); - jabberStatusSet.add(AWAY); - jabberStatusSet.add(DO_NOT_DISTURB); - jabberStatusSet.add(OFFLINE); + private JabberPresenceStatus unknownStatus; + + public JabberStatusEnum(String iconPath) + { + this.offlineStatus = + new JabberPresenceStatus(0, OFFLINE, loadIcon(iconPath + + "/status16x16-offline.png")); + + this.doNotDisturbStatus = + new JabberPresenceStatus(30, DO_NOT_DISTURB, loadIcon(iconPath + + "/status16x16-dnd.png")); + + this.awayStatus = + new JabberPresenceStatus(40, AWAY, loadIcon(iconPath + + "/status16x16-away.png")); + + this.availableStatus = + new JabberPresenceStatus(65, AVAILABLE, loadIcon(iconPath + + "/status16x16-online.png")); + + this.freeForChatStatus = + new JabberPresenceStatus(85, FREE_FOR_CHAT, loadIcon(iconPath + + "/status16x16-ffc.png")); + + this.unknownStatus = + new JabberPresenceStatus(1, UNKNOWN, loadIcon(iconPath + + "/status16x16-offline.png")); + + // Initialize the list of supported status states. + supportedStatusSet.add(freeForChatStatus); + supportedStatusSet.add(availableStatus); + supportedStatusSet.add(awayStatus); + supportedStatusSet.add(doNotDisturbStatus); + supportedStatusSet.add(offlineStatus); + } + + /** + * Returns the offline Jabber status. + * + * @param statusName the name of the status. + * @return the offline Jabber status. + */ + public JabberPresenceStatus getStatus(String statusName) + { + if (statusName.equals(AVAILABLE)) + return availableStatus; + else if (statusName.equals(OFFLINE)) + return offlineStatus; + else if (statusName.equals(FREE_FOR_CHAT)) + return freeForChatStatus; + else if (statusName.equals(DO_NOT_DISTURB)) + return doNotDisturbStatus; + else if (statusName.equals(AWAY)) + return awayStatus; + else + return unknownStatus; } /** - * Creates a status with the specified connectivity coeff, name and icon. - * @param status the connectivity coefficient for the specified status - * @param statusName String - * @param statusIcon the icon associated with this status + * Returns an iterator over all status instances supported by the sip + * provider. + * + * @return an Iterator over all status instances supported by the + * sip provider. */ - protected JabberStatusEnum(int status, String statusName, byte[] statusIcon) + public Iterator getSupportedStatusSet() { - super(status, statusName, statusIcon); + return supportedStatusSet.iterator(); + } + + public static String[] getStatusNames() + { + return new String[] + { OFFLINE, DO_NOT_DISTURB, AWAY, AVAILABLE, FREE_FOR_CHAT }; } /** * Loads an image from a given image path. - * @param imagePath The identifier of the image. - * @return The image for the given identifier. + * + * @param imagePath The path to the image resource. + * @return The image extracted from the resource at the specified path. */ - public static byte[] loadIcon(String imagePath) { - InputStream is = JabberStatusEnum.class.getClassLoader() - .getResourceAsStream(imagePath); + public static byte[] loadIcon(String imagePath) + { + return loadIcon(imagePath, JabberStatusEnum.class); + } + + public static byte[] loadIcon(String imagePath, Class clazz) + { + InputStream is = getResourceAsStream(imagePath, clazz); byte[] icon = null; - try { + try + { icon = new byte[is.available()]; is.read(icon); - } catch (IOException exc) { + } + catch (IOException exc) + { logger.error("Failed to load icon: " + imagePath, exc); } + finally { + try + { + is.close(); + } + catch (IOException ex) + { + /* + * We're closing an InputStream so there shouldn't be data loss + * because of it (in contrast to an OutputStream) and a warning + * in the log should be enough. + */ + logger.warn("Failed to close the InputStream of icon: " + + imagePath, ex); + } + } return icon; } + + private static InputStream getResourceAsStream(String name, Class clazz) + { + if (name.indexOf("://") != -1) + { + try + { + return new URL(name).openStream(); + } + catch (IOException ex) + { + /* + * Well, we didn't really know whether the specified name + * represented an URL so we just tried. We'll resort to + * Class#getResourceAsStream then. + */ + } + } + return clazz.getClassLoader().getResourceAsStream(name); + } + + /** + * An implementation of PresenceStatus that enumerates all states + * that a Jabber contact can currently have. + */ + private class JabberPresenceStatus + extends PresenceStatus + { + /** + * Creates an instance of JabberPresenceStatus with the + * specified parameters. + * + * @param status the connectivity level of the new presence status + * instance + * @param statusName the name of the presence status. + * @param statusIcon the icon associated with this status + */ + private JabberPresenceStatus(int status, String statusName, + byte[] statusIcon) + { + super(status, statusName, statusIcon); + } + } } diff --git a/test/net/java/sip/communicator/slick/protocol/jabber/TestOperationSetPresence.java b/test/net/java/sip/communicator/slick/protocol/jabber/TestOperationSetPresence.java index 14b3209bd..fda0eea45 100644 --- a/test/net/java/sip/communicator/slick/protocol/jabber/TestOperationSetPresence.java +++ b/test/net/java/sip/communicator/slick/protocol/jabber/TestOperationSetPresence.java @@ -27,6 +27,7 @@ * postTestUnsubscribe(). *

* @author Damian Minkov + * @author Lubomir Marinov */ public class TestOperationSetPresence extends TestCase @@ -36,7 +37,9 @@ public class TestOperationSetPresence private JabberSlickFixture fixture = new JabberSlickFixture(); private OperationSetPresence operationSetPresence1 = null; + private final Map supportedStatusSet1 = new HashMap(); private OperationSetPresence operationSetPresence2 = null; + private final Map supportedStatusSet2 = new HashMap(); private String statusMessageRoot = new String("Our status is now: "); private static AuthEventCollector authEventCollector1 = new AuthEventCollector(); @@ -101,6 +104,30 @@ protected void setUp() throws Exception + "Operation Sets"); } + /* + * Retrieve the supported PresenceStatus values because the instances + * are specific to the ProtocolProviderService implementations. + */ + // operationSetPresence1 + for (Iterator supportedStatusIt = + operationSetPresence1.getSupportedStatusSet(); supportedStatusIt + .hasNext();) + { + PresenceStatus supportedStatus = + (PresenceStatus) supportedStatusIt.next(); + supportedStatusSet1.put(supportedStatus.getStatusName(), + supportedStatus); + } + // operationSetPresence2 + for (Iterator supportedStatusIt = + operationSetPresence2.getSupportedStatusSet(); supportedStatusIt + .hasNext();) + { + PresenceStatus supportedStatus = + (PresenceStatus) supportedStatusIt.next(); + supportedStatusSet2.put(supportedStatus.getStatusName(), + supportedStatus); + } } protected void tearDown() throws Exception @@ -158,22 +185,24 @@ public void testSupportedStatusSetForCompleteness() Iterator supportedStatusSetIter = operationSetPresence1.getSupportedStatusSet(); - List supportedStatusSet = new LinkedList(); - while (supportedStatusSetIter.hasNext()){ - supportedStatusSet.add(supportedStatusSetIter.next()); + List supportedStatusNames = new LinkedList(); + while (supportedStatusSetIter.hasNext()) + { + supportedStatusNames.add(((PresenceStatus) supportedStatusSetIter + .next()).getStatusName()); } //create a copy of the MUST status set and remove any matching status //that is also present in the supported set. - List requiredStatusSetCopy = (List)JabberStatusEnum.jabberStatusSet.clone(); + List requiredStatusNames = + Arrays.asList(JabberStatusEnum.getStatusNames()); - requiredStatusSetCopy.removeAll(supportedStatusSet); + requiredStatusNames.removeAll(supportedStatusNames); //if we have anything left then the implementation is wrong. - int unsupported = requiredStatusSetCopy.size(); + int unsupported = requiredStatusNames.size(); assertTrue( "There are " + unsupported + " statuses as follows:" - + requiredStatusSetCopy, - unsupported == 0); + + requiredStatusNames, unsupported == 0); } /** @@ -228,11 +257,13 @@ public void testChangingStateToOnline() throws Exception * * @throws Exception in case changing the state causes an exception */ - public void subtestStateTransition( JabberStatusEnum newStatus) - throws Exception + private void subtestStateTransition(String newStatusName) throws Exception { logger.trace(" --=== beginning state transition test ===--"); + PresenceStatus newStatus = + getPresenceStatus(supportedStatusSet1, newStatusName); + PresenceStatus oldStatus = operationSetPresence1.getPresenceStatus(); String oldStatusMessage = operationSetPresence1.getCurrentStatusMessage(); String newStatusMessage = statusMessageRoot + newStatus; @@ -276,7 +307,7 @@ public void subtestStateTransition( JabberStatusEnum newStatus) newStatus, operationSetPresence1.getPresenceStatus()); - JabberStatusEnum actualStatus = (JabberStatusEnum) + PresenceStatus actualStatus = operationSetPresence2.queryContactStatus(fixture.userID1); assertEquals("The underlying implementation did not switch to the " @@ -361,20 +392,21 @@ public void testQueryContactStatus() * * @throws java.lang.Exception if querying the status causes some exception. */ - public void subtestQueryContactStatus(PresenceStatus status, - PresenceStatus expectedReturn) + private void subtestQueryContactStatus(String status, String expectedReturn) throws Exception { - operationSetPresence2.publishPresenceStatus(status, "status message"); + operationSetPresence2.publishPresenceStatus(getPresenceStatus( + supportedStatusSet2, status), "status message"); pauseAfterStateChanges(); PresenceStatus actualReturn = operationSetPresence1.queryContactStatus(fixture.userID2); assertEquals("Querying a " - + expectedReturn.getStatusName() + + expectedReturn + " state did not return as expected" - , expectedReturn, actualReturn); + , getPresenceStatus(supportedStatusSet1, expectedReturn) + , actualReturn); } /** @@ -503,16 +535,19 @@ public void postTestSubscribe() // make the user agent tester change its states and make sure we are // notified logger.debug("Testing presence notifications."); - JabberStatusEnum oldStatus - = (JabberStatusEnum)operationSetPresence2.getPresenceStatus(); - + PresenceStatus oldStatus + = operationSetPresence2.getPresenceStatus(); - JabberStatusEnum newStatus = JabberStatusEnum.FREE_FOR_CHAT; + PresenceStatus newStatus = + getPresenceStatus(supportedStatusSet2, + JabberStatusEnum.FREE_FOR_CHAT); //in case we are by any chance already in a FREE_FOR_CHAT status, we'll //be changing to something else if(oldStatus.equals(newStatus)){ - newStatus = JabberStatusEnum.DO_NOT_DISTURB; + newStatus = + getPresenceStatus(supportedStatusSet2, + JabberStatusEnum.DO_NOT_DISTURB); } //now do the actual status notification testing @@ -610,14 +645,18 @@ public void postTestUnsubscribe() // make the user agent tester change its states and make sure we don't // get notifications as we're now unsubscribed. logger.debug("Testing (lack of) presence notifications."); - JabberStatusEnum oldStatus - = (JabberStatusEnum)operationSetPresence2.getPresenceStatus(); - JabberStatusEnum newStatus = JabberStatusEnum.FREE_FOR_CHAT; + PresenceStatus oldStatus + = operationSetPresence2.getPresenceStatus(); + PresenceStatus newStatus = + getPresenceStatus(supportedStatusSet2, + JabberStatusEnum.FREE_FOR_CHAT); //in case we are by any chance already in a FREE_FOR_CHAT status, we'll //be changing to something else if(oldStatus.equals(newStatus)){ - newStatus = JabberStatusEnum.DO_NOT_DISTURB; + newStatus = + getPresenceStatus(supportedStatusSet2, + JabberStatusEnum.DO_NOT_DISTURB); } //now do the actual status notification testing @@ -885,10 +924,10 @@ private class ContactPresenceEventCollector { public ArrayList collectedEvents = new ArrayList(); private String trackedScreenName = null; - private JabberStatusEnum status = null; + private PresenceStatus status = null; ContactPresenceEventCollector(String screenname, - JabberStatusEnum wantedStatus) + PresenceStatus wantedStatus) { this.trackedScreenName = screenname; this.status = wantedStatus; @@ -946,6 +985,12 @@ public void contactPresenceStatusChanged( } } + private PresenceStatus getPresenceStatus(Map supportedStatusSet, + String statusName) + { + return (PresenceStatus) supportedStatusSet.get(statusName); + } + /** * Authorization handler for the implementation tests *