From 0d8d715096b01205db2214ac757997aec046a137 Mon Sep 17 00:00:00 2001 From: Emil Ivov Date: Mon, 14 May 2007 14:09:47 +0000 Subject: [PATCH] Committing geolocation for Jabber from Guillaume Schreiner - Louis Pasteur University, France The implementation of OperationSetGeolocation for jabber (by Guillaume Schreiner, Louis Pasteur University, France). --- .../OperationSetGeolocationJabberImpl.java | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/OperationSetGeolocationJabberImpl.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetGeolocationJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetGeolocationJabberImpl.java new file mode 100644 index 000000000..5b877ee7b --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetGeolocationJabberImpl.java @@ -0,0 +1,289 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.jabber; + +import java.util.*; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.provider.*; +import org.jivesoftware.smack.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.geolocation.*; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; + +/** + * The Jabber implementation of an OperationSetGeolocation done with the + * XEP-0080: User Geolocation. This class broadcast our own geolocation and + * manage the geolocation status of our buddies. + * + * Currently, we send geolocation message in presence. We passively listen + * to buddies geolocation when their presence are updated. + * + * @author Guillaume Schreiner + */ +public class OperationSetGeolocationJabberImpl + implements OperationSetGeolocation +{ + + private static final Logger logger = + Logger.getLogger(OperationSetGeolocationJabberImpl.class); + + /** + * The list of Geolocation status listeners interested in receiving presence + * notifications of changes in geolocation of contacts in our contact list. + */ + private Vector geolocationContactsListeners = new Vector(); + + /** + * A callback to the provider + */ + private ProtocolProviderServiceJabberImpl jabberProvider; + + /** + * A callback to the persistent presence operation set. + */ + private OperationSetPersistentPresence opsetprez = null; + + /** + * Constuctor + * + * @param provider ProtocolProviderServiceJabberImpl + */ + public OperationSetGeolocationJabberImpl( + ProtocolProviderServiceJabberImpl provider) + { + + this.jabberProvider = provider; + + this.opsetprez = (OperationSetPersistentPresence) + provider.getOperationSet(OperationSetPersistentPresence.class); + + this.jabberProvider.addRegistrationStateChangeListener( + new RegistrationStateListener()); + + // Add the custom GeolocationExtension to the Smack library + ProviderManager pManager = ProviderManager.getInstance(); + pManager.addExtensionProvider( + GeolocationPacketExtensionProvider.ELEMENT_NAME + , GeolocationPacketExtensionProvider.NAMESPACE + , new GeolocationPacketExtensionProvider()); + + } + + /** + * Broadcast our current Geolocation trough this provider using a Jabber + * presence message. + * + * @param geolocation our current Geolocation ready to be sent + */ + public void publishGeolocation(Map geolocation) + { + + GeolocationPresence myGeolocPrez = new GeolocationPresence(opsetprez); + + GeolocationPacketExtension geolocExt = GeolocationJabberUtils + .convertMapToExtension(geolocation); + + myGeolocPrez.setGeolocationExtention(geolocExt); + + this.jabberProvider.getConnection() + .sendPacket(myGeolocPrez.getGeolocPresence()); + + } + + /** + * Retrieve the geolocation of the given contact. + *

+ * Note: Currently not implemented because we can not actively poll the + * server for the presence of a given contact ? + *

+ * @param contactIdentifier the Contact we want to retrieve its + * geolocation by its identifier. + * @return the Geolocation of the contact. + */ + public Map queryContactGeolocation(String contactIdentifier) + { + /** @todo implement queryContactGeolocation() */ + return null; + } + + /** + * Registers a listener that would get notifications any time a contact + * refreshed its geolocation via Presence. + * + * @param listener the ContactGeolocationPresenceListener to + * register + */ + public void addGeolocationListener(GeolocationListener listener) + { + synchronized (geolocationContactsListeners) + { + geolocationContactsListeners.add(listener); + } + } + + /** + * Remove a listener that would get notifications any time a contact + * refreshed its geolocation via Presence. + * + * @param listener the ContactGeolocationPresenceListener to + * register + */ + public void removeGeolocationListener(GeolocationListener listener) + { + synchronized (geolocationContactsListeners) + { + geolocationContactsListeners.remove(listener); + } + + } + + /** + * Our listener that will tell us when we're registered to server + * and we are ready to launch the listener for GeolocationPacketExtension + * packets + */ + private class RegistrationStateListener + implements RegistrationStateChangeListener + { + /** + * The method is called by a ProtocolProvider implementation whenver + * a change in the registration state of the corresponding provider had + * occurred. + * @param evt ProviderStatusChangeEvent the event describing the status + * change. + */ + public void registrationStateChanged(RegistrationStateChangeEvent evt) + { + logger.debug("The Jabber provider changed state from: " + + evt.getOldState() + + " to: " + evt.getNewState()); + + if (evt.getNewState() == RegistrationState.REGISTERED) + { + + PacketExtensionFilter filterGeoloc = + new PacketExtensionFilter( + GeolocationPacketExtensionProvider.ELEMENT_NAME, + GeolocationPacketExtensionProvider.NAMESPACE + ); + + // launch the listener + try + { + jabberProvider.getConnection().addPacketListener( + new GeolocationPresencePacketListener() + , filterGeoloc + ); + } + catch (Exception e) + { + logger.error(e); + } + + } + else if (evt.getNewState() == RegistrationState.UNREGISTERED + || evt.getNewState() + == RegistrationState.AUTHENTICATION_FAILED + || evt.getNewState() + == RegistrationState.CONNECTION_FAILED) + { + + } + } + } + + /** + * This class listen to GeolocationExtension into Presence Packet. + * If GeolocationExtension is found, an event is sent. + * + * @author Guillaume Schreiner + */ + private class GeolocationPresencePacketListener + implements PacketListener + { + /** + * Match incoming packets with geolocation Extension tags for + * dispatching a new event. + * + * @param packet matching Geolocation Extension tags. + */ + public void processPacket(Packet packet) + { + String from = StringUtils.parseBareAddress(packet.getFrom()); + + GeolocationPacketExtension geolocExt = + (GeolocationPacketExtension) packet.getExtension( + GeolocationPacketExtensionProvider.ELEMENT_NAME, + GeolocationPacketExtensionProvider.NAMESPACE); + + if (geolocExt != null) + { + logger.debug("GeolocationExtension found from " + from + ":" + + geolocExt.toXML()); + + Map newGeolocation = GeolocationJabberUtils + .convertExtensionToMap(geolocExt); + + this.fireGeolocationContactChangeEvent( + from, + newGeolocation); + } + } + + /** + * Notify registred listeners for a new incoming GeolocationExtension. + * + * @param sourceContact which send a new Geolocation. + * @param newGeolocation the new given Geolocation. + */ + public void fireGeolocationContactChangeEvent(String sourceContact, + Map newGeolocation) + { + + logger.debug("Trying to dispatch geolocation contact update for " + + sourceContact); + + Contact source = opsetprez.findContactByID(sourceContact); + + GeolocationEvent evt = + new GeolocationEvent( + source + , jabberProvider + , newGeolocation + , OperationSetGeolocationJabberImpl.this); + + logger.debug("Dispatching geolocation contact update. Listeners=" + + geolocationContactsListeners.size() + + " evt=" + evt); + + Iterator listeners = null; + + synchronized (geolocationContactsListeners) + { + listeners = new ArrayList + (geolocationContactsListeners).iterator(); + } + + while (listeners.hasNext()) + { + GeolocationListener listener = + (GeolocationListener) listeners.next(); + + listener.contactGeolocationChanged(evt); + } + + } + + } + +}