From 340bcb2d12dbd0c7431a4dd112ceaa87ff7d82e3 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Mon, 13 Apr 2020 15:26:46 +0200 Subject: [PATCH] pep: improve API, add PepEventListener The geoloc, mood and usertune PEP users showed a pattern. Instead of repeating this pattern every time, let PepManager do the hard work --- .../smackx/geoloc/GeoLocationManager.java | 73 ++-------- .../smackx/mood/MoodListener.java | 2 +- .../jivesoftware/smackx/mood/MoodManager.java | 51 ++----- .../PepEventListener.java} | 12 +- .../jivesoftware/smackx/pep/PepManager.java | 131 +++++++++++++++++- .../smackx/pubsub/PubSubManager.java | 2 + .../smackx/usertune/UserTuneListener.java | 29 ---- .../smackx/usertune/UserTuneManager.java | 64 ++------- .../GeolocationIntegrationTest.java | 8 +- .../smackx/mood/MoodIntegrationTest.java | 5 +- .../usertune/UserTuneIntegrationTest.java | 5 +- 11 files changed, 178 insertions(+), 204 deletions(-) rename smack-extensions/src/main/java/org/jivesoftware/smackx/{geoloc/GeoLocationListener.java => pep/PepEventListener.java} (70%) delete mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java index 642e7f147..f29306251 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java @@ -16,11 +16,8 @@ */ package org.jivesoftware.smackx.geoloc; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.Manager; @@ -29,30 +26,26 @@ import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; + import org.jivesoftware.smackx.geoloc.packet.GeoLocation; import org.jivesoftware.smackx.geoloc.provider.GeoLocationProvider; -import org.jivesoftware.smackx.pep.PepListener; +import org.jivesoftware.smackx.pep.PepEventListener; import org.jivesoftware.smackx.pep.PepManager; -import org.jivesoftware.smackx.pubsub.EventElement; -import org.jivesoftware.smackx.pubsub.ItemsExtension; import org.jivesoftware.smackx.pubsub.PayloadItem; import org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException; import org.jivesoftware.smackx.xdata.provider.FormFieldChildElementProviderManager; -import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.Jid; /** * Entry point for Smacks API for XEP-0080: User Location. *
- * To publish a UserLocation, please use {@link #sendGeolocation(GeoLocation)} method. This will publish the node. + * To publish a UserLocation, please use {@link #publishGeoLocation(GeoLocation)} method. This will publish the node. *
* To stop publishing a UserLocation, please use {@link #stopPublishingGeolocation()} method. This will send a disble publishing signal. *
- * To add a {@link GeoLocationListener} in order to remain updated with other users GeoLocation, use {@link #addGeoLocationListener(GeoLocationListener)} method. + * To add a {@link PepEventListener} in order to remain updated with other users GeoLocation, use {@link #addGeoLocationListener(PepEventListener)} method. *
* To link a GeoLocation with {@link Message}, use `message.addExtension(geoLocation)`. *
@@ -63,15 +56,10 @@ import org.jxmpp.jid.Jid; */ public final class GeoLocationManager extends Manager { - public static final String GEOLOCATION_NODE = "http://jabber.org/protocol/geoloc"; - public static final String GEOLOCATION_NOTIFY = GEOLOCATION_NODE + "+notify"; + public static final String GEOLOCATION_NODE = GeoLocation.NAMESPACE; private static final Map INSTANCES = new WeakHashMap<>(); - private static boolean ENABLE_USER_LOCATION_NOTIFICATIONS_BY_DEFAULT = true; - - private final Set geoLocationListeners = new CopyOnWriteArraySet<>(); - private final ServiceDiscoveryManager serviceDiscoveryManager; private final PepManager pepManager; static { @@ -105,28 +93,6 @@ public final class GeoLocationManager extends Manager { private GeoLocationManager(XMPPConnection connection) { super(connection); pepManager = PepManager.getInstanceFor(connection); - pepManager.addPepListener(new PepListener() { - - @Override - public void eventReceived(EntityBareJid from, EventElement event, Message message) { - if (!GEOLOCATION_NODE.equals(event.getEvent().getNode())) { - return; - } - - ItemsExtension itemsExtension = (ItemsExtension) event.getEvent(); - List items = itemsExtension.getExtensions(); - @SuppressWarnings("unchecked") - PayloadItem payload = (PayloadItem) items.get(0); - GeoLocation geoLocation = payload.getPayload(); - for (GeoLocationListener listener : geoLocationListeners) { - listener.onGeoLocationUpdated(from, geoLocation, message); - } - } - }); - serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); - if (ENABLE_USER_LOCATION_NOTIFICATIONS_BY_DEFAULT) { - enableUserLocationNotifications(); - } } public void sendGeoLocationToJid(GeoLocation geoLocation, Jid jid) throws InterruptedException, @@ -154,18 +120,18 @@ public final class GeoLocationManager extends Manager { } /** - * Send geolocation through the PubSub node. + * Publish the user's geographic location through the Personal Eventing Protocol (PEP). * - * @param geoLocation TODO javadoc me please + * @param geoLocation the geographic location to publish. * @throws InterruptedException if the calling thread was interrupted. * @throws NotConnectedException if the XMPP connection is not connected. * @throws XMPPErrorException if there was an XMPP error returned. * @throws NoResponseException if there was no response from the remote entity. * @throws NotALeafNodeException if a PubSub leaf node operation was attempted on a non-leaf node. */ - public void sendGeolocation(GeoLocation geoLocation) + public void publishGeoLocation(GeoLocation geoLocation) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotALeafNodeException { - pepManager.publish(GeoLocation.NAMESPACE, new PayloadItem(geoLocation)); + pepManager.publish(GEOLOCATION_NODE, new PayloadItem(geoLocation)); } /** @@ -179,25 +145,14 @@ public final class GeoLocationManager extends Manager { */ public void stopPublishingGeolocation() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotALeafNodeException { - pepManager.publish(GeoLocation.NAMESPACE, new PayloadItem(GeoLocation.EMPTY_GEO_LOCATION)); + pepManager.publish(GEOLOCATION_NODE, new PayloadItem(GeoLocation.EMPTY_GEO_LOCATION)); } - public static void setGeoLocationNotificationsEnabledByDefault(boolean bool) { - ENABLE_USER_LOCATION_NOTIFICATIONS_BY_DEFAULT = bool; + public boolean addGeoLocationListener(PepEventListener listener) { + return pepManager.addPepEventListener(GEOLOCATION_NODE, GeoLocation.class, listener); } - public void enableUserLocationNotifications() { - serviceDiscoveryManager.addFeature(GEOLOCATION_NOTIFY); - } - - public void disableGeoLocationNotifications() { - serviceDiscoveryManager.removeFeature(GEOLOCATION_NOTIFY); - } - - public boolean addGeoLocationListener(GeoLocationListener geoLocationListener) { - return geoLocationListeners.add(geoLocationListener); - } - public boolean removeGeoLocationListener(GeoLocationListener geoLocationListener) { - return geoLocationListeners.remove(geoLocationListener); + public boolean removeGeoLocationListener(PepEventListener listener) { + return pepManager.removePepEventListener(listener); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodListener.java index 243e67032..145aa0b41 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodListener.java @@ -24,6 +24,6 @@ import org.jxmpp.jid.EntityBareJid; public interface MoodListener { - void onMoodUpdated(EntityBareJid from, MoodElement moodElement, Message message); + void onMoodUpdated(EntityBareJid from, MoodElement moodElement, String id, Message message); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodManager.java index 54f50b4ee..5261a45e8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/mood/MoodManager.java @@ -17,9 +17,7 @@ package org.jivesoftware.smackx.mood; import java.util.Map; -import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.SmackException; @@ -28,20 +26,13 @@ import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.mood.element.MoodConcretisation; import org.jivesoftware.smackx.mood.element.MoodElement; import org.jivesoftware.smackx.mood.provider.MoodConcretisationProvider; -import org.jivesoftware.smackx.pep.PepListener; +import org.jivesoftware.smackx.pep.PepEventListener; import org.jivesoftware.smackx.pep.PepManager; -import org.jivesoftware.smackx.pubsub.EventElement; -import org.jivesoftware.smackx.pubsub.ItemsExtension; -import org.jivesoftware.smackx.pubsub.LeafNode; import org.jivesoftware.smackx.pubsub.PayloadItem; import org.jivesoftware.smackx.pubsub.PubSubException; -import org.jivesoftware.smackx.pubsub.PubSubManager; - -import org.jxmpp.jid.EntityBareJid; /** * Entry point for Smacks API for XEP-0107: User Mood. @@ -49,8 +40,8 @@ import org.jxmpp.jid.EntityBareJid; * To set a mood, please use one of the {@link #setMood(Mood)} methods. This will publish the users mood to a pubsub * node.
*
- * In order to get updated about other users moods, register a {@link MoodListener} at - * {@link #addMoodListener(MoodListener)}. That listener will get updated about any incoming mood updates of contacts.
+ * In order to get updated about other users moods, register a {@link PepEventListener} at + * {@link #addMoodListener(PepEventListener)}. That listener will get updated about any incoming mood updates of contacts.
*
* To stop publishing the users mood, refer to {@link #clearMood()}.
*
@@ -66,32 +57,15 @@ import org.jxmpp.jid.EntityBareJid; public final class MoodManager extends Manager { public static final String MOOD_NODE = "http://jabber.org/protocol/mood"; - public static final String MOOD_NOTIFY = MOOD_NODE + "+notify"; private static final Map INSTANCES = new WeakHashMap<>(); - private final Set moodListeners = new CopyOnWriteArraySet<>(); - private PubSubManager pubSubManager; + private final PepManager pepManager; private MoodManager(XMPPConnection connection) { super(connection); - ServiceDiscoveryManager.getInstanceFor(connection).addFeature(MOOD_NOTIFY); - PepManager.getInstanceFor(connection).addPepListener(new PepListener() { - @Override - public void eventReceived(final EntityBareJid from, final EventElement event, final Message message) { - if (!MOOD_NODE.equals(event.getEvent().getNode())) { - return; - } - ItemsExtension items = (ItemsExtension) event.getExtensions().get(0); - PayloadItem payload = (PayloadItem) items.getItems().get(0); - MoodElement mood = (MoodElement) payload.getPayload(); - - for (MoodListener listener : moodListeners) { - listener.onMoodUpdated(from, mood, message); - } - } - }); + pepManager = PepManager.getInstanceFor(connection); } public static synchronized MoodManager getInstanceFor(XMPPConnection connection) { @@ -138,12 +112,7 @@ public final class MoodManager extends Manager { private void publishMood(MoodElement moodElement) throws SmackException.NotLoggedInException, InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException { - if (pubSubManager == null) { - pubSubManager = PubSubManager.getInstanceFor(getAuthenticatedConnectionOrThrow(), connection().getUser().asBareJid()); - } - - LeafNode node = pubSubManager.getOrCreateLeafNode(MOOD_NODE); - node.publish(new PayloadItem<>(moodElement)); + pepManager.publish(MOOD_NODE, new PayloadItem<>(moodElement)); } private static MoodElement buildMood(Mood mood, MoodConcretisation concretisation, String text) { @@ -161,11 +130,11 @@ public final class MoodManager extends Manager { message.addExtension(element); } - public void addMoodListener(MoodListener listener) { - moodListeners.add(listener); + public boolean addMoodListener(PepEventListener listener) { + return pepManager.addPepEventListener(MOOD_NODE, MoodElement.class, listener); } - public void removeMoodListener(MoodListener listener) { - moodListeners.remove(listener); + public boolean removeMoodListener(PepEventListener listener) { + return pepManager.removePepEventListener(listener); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepEventListener.java similarity index 70% rename from smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationListener.java rename to smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepEventListener.java index 25b6bb4d6..6abf2e77f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepEventListener.java @@ -1,6 +1,6 @@ /** * - * Copyright 2020 Aditya Borikar. + * Copyright 2020 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.geoloc; +package org.jivesoftware.smackx.pep; +import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.geoloc.packet.GeoLocation; import org.jxmpp.jid.EntityBareJid; -public interface GeoLocationListener { - void onGeoLocationUpdated(EntityBareJid jid, GeoLocation geoLocation, Message message); +public interface PepEventListener { + + void onPepEvent(EntityBareJid from, E event, String id, Message carrierMessage); + } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepManager.java index b31a3d3e2..7a480503e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/PepManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2015-2019 Florian Schmaus + * Copyright 2003-2007 Jive Software, 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,10 +17,13 @@ package org.jivesoftware.smackx.pep; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.logging.Logger; import org.jivesoftware.smack.AsyncButOrdered; import org.jivesoftware.smack.Manager; @@ -33,13 +36,19 @@ import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.StanzaFilter; import org.jivesoftware.smack.filter.jidtype.AbstractJidTypeFilter.JidType; import org.jivesoftware.smack.filter.jidtype.FromJidTypeFilter; +import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.NamedElement; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.util.CollectionUtil; +import org.jivesoftware.smack.util.MultiMap; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.pubsub.EventElement; import org.jivesoftware.smackx.pubsub.Item; +import org.jivesoftware.smackx.pubsub.ItemsExtension; import org.jivesoftware.smackx.pubsub.LeafNode; +import org.jivesoftware.smackx.pubsub.PayloadItem; import org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException; import org.jivesoftware.smackx.pubsub.PubSubFeature; import org.jivesoftware.smackx.pubsub.PubSubManager; @@ -70,6 +79,8 @@ import org.jxmpp.jid.EntityBareJid; */ public final class PepManager extends Manager { + private static final Logger LOGGER = Logger.getLogger(PepManager.class.getName()); + private static final Map INSTANCES = new WeakHashMap<>(); public static synchronized PepManager getInstanceFor(XMPPConnection connection) { @@ -81,6 +92,7 @@ public final class PepManager extends Manager { return pepManager; } + // TODO: Filter only for event extensions with as child. private static final StanzaFilter FROM_BARE_JID_WITH_EVENT_EXTENSION_FILTER = new AndFilter( new FromJidTypeFilter(JidType.BareJid), EventExtensionFilter.INSTANCE); @@ -89,8 +101,14 @@ public final class PepManager extends Manager { private final AsyncButOrdered asyncButOrdered = new AsyncButOrdered<>(); + private final ServiceDiscoveryManager serviceDiscoveryManager; + private final PubSubManager pepPubSubManager; + private final MultiMap> pepEventListeners = new MultiMap<>(); + + private final Map, PepEventListenerCoupling> listenerToCouplingMap = new HashMap<>(); + /** * Creates a new PEP exchange manager. * @@ -98,6 +116,10 @@ public final class PepManager extends Manager { */ private PepManager(XMPPConnection connection) { super(connection); + + serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); + pepPubSubManager = PubSubManager.getInstanceFor(connection, null); + StanzaListener packetListener = new StanzaListener() { @Override public void processStanza(Stanza stanza) { @@ -106,20 +128,118 @@ public final class PepManager extends Manager { assert event != null; final EntityBareJid from = message.getFrom().asEntityBareJidIfPossible(); assert from != null; + asyncButOrdered.performAsyncButOrdered(from, new Runnable() { @Override public void run() { + ItemsExtension itemsExtension = (ItemsExtension) event.getEvent(); + String node = itemsExtension.getNode(); + for (PepListener listener : pepListeners) { listener.eventReceived(from, event, message); } + + List> nodeListeners; + synchronized (pepEventListeners) { + nodeListeners = pepEventListeners.getAll(node); + if (nodeListeners.isEmpty()) { + return; + } + + // Make a copy of the list. Note that it is important to do this within the synchronized + // block. + nodeListeners = CollectionUtil.newListWith(nodeListeners); + } + + for (PepEventListenerCoupling listener : nodeListeners) { + // TODO: Can there be more than one item? + List items = itemsExtension.getItems(); + for (NamedElement namedElementItem : items) { + Item item = (Item) namedElementItem; + String id = item.getId(); + @SuppressWarnings("unchecked") + PayloadItem payloadItem = (PayloadItem) item; + ExtensionElement payload = payloadItem.getPayload(); + + listener.invoke(from, payload, id, message); + } + } } }); } }; // TODO Add filter to check if from supports PubSub as per xep163 2 2.4 connection.addSyncStanzaListener(packetListener, FROM_BARE_JID_WITH_EVENT_EXTENSION_FILTER); + } - pepPubSubManager = PubSubManager.getInstanceFor(connection, null); + private static final class PepEventListenerCoupling { + private final String node; + private final Class extensionElementType; + private final PepEventListener pepEventListener; + + private PepEventListenerCoupling(String node, Class extensionElementType, + PepEventListener pepEventListener) { + this.node = node; + this.extensionElementType = extensionElementType; + this.pepEventListener = pepEventListener; + } + + private void invoke(EntityBareJid from, ExtensionElement payload, String id, Message carrierMessage) { + if (!extensionElementType.isInstance(payload)) { + LOGGER.warning("Ignoring " + payload + " from " + carrierMessage + " as it is not of type " + + extensionElementType); + return; + } + + E extensionElementPayload = extensionElementType.cast(payload); + pepEventListener.onPepEvent(from, extensionElementPayload, id, carrierMessage); + } + } + + public boolean addPepEventListener(String node, Class extensionElementType, + PepEventListener pepEventListener) { + PepEventListenerCoupling pepEventListenerCoupling = new PepEventListenerCoupling<>(node, + extensionElementType, pepEventListener); + + synchronized (pepEventListeners) { + if (listenerToCouplingMap.containsKey(pepEventListener)) { + return false; + } + listenerToCouplingMap.put(pepEventListener, pepEventListenerCoupling); + /* + * TODO: Replace the above with the below using putIfAbsent() if Smack's minimum required Android SDK level + * is 24 or higher. PepEventListenerCoupling currentPepEventListenerCoupling = + * listenerToCouplingMap.putIfAbsent(pepEventListener, pepEventListenerCoupling); if + * (currentPepEventListenerCoupling != null) { return false; } + */ + + boolean listenerForNodeExisted = pepEventListeners.put(node, pepEventListenerCoupling); + if (!listenerForNodeExisted) { + serviceDiscoveryManager.addFeature(node + PubSubManager.PLUS_NOTIFY); + } + } + return true; + } + + public boolean removePepEventListener(PepEventListener pepEventListener) { + synchronized (pepEventListeners) { + PepEventListenerCoupling pepEventListenerCoupling = listenerToCouplingMap.remove(pepEventListener); + if (pepEventListenerCoupling == null) { + return false; + } + + String node = pepEventListenerCoupling.node; + + boolean mappingExisted = pepEventListeners.removeOne(node, pepEventListenerCoupling); + assert mappingExisted; + + if (!pepEventListeners.containsKey(pepEventListenerCoupling.node)) { + // This was the last listener for the node. Remove the +notify feature. + serviceDiscoveryManager.removeFeature(node + PubSubManager.PLUS_NOTIFY); + } + } + + return true; } public PubSubManager getPepPubSubManager() { @@ -127,8 +247,7 @@ public final class PepManager extends Manager { } /** - * Adds a listener to PEPs. The listener will be fired anytime PEP events - * are received from remote XMPP clients. + * Adds a listener to PEPs. The listener will be fired anytime PEP events are received from remote XMPP clients. * * @param pepListener a roster exchange listener. * @return true if pepListener was added. @@ -176,8 +295,8 @@ public final class PepManager extends Manager { // @formatter:on }; - public boolean isSupported() throws NoResponseException, XMPPErrorException, - NotConnectedException, InterruptedException { + public boolean isSupported() + throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { XMPPConnection connection = connection(); ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); BareJid localBareJid = connection.getUser().asBareJid(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java index 7d91e41ca..1b9b28a55 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java @@ -69,6 +69,8 @@ import org.jxmpp.stringprep.XmppStringprepException; */ public final class PubSubManager extends Manager { + public static final String PLUS_NOTIFY = "+notify"; + public static final String AUTO_CREATE_FEATURE = "http://jabber.org/protocol/pubsub#auto-create"; private static final Logger LOGGER = Logger.getLogger(PubSubManager.class.getName()); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java deleted file mode 100644 index 3e053776b..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * - * Copyright 2019 Aditya Borikar, 2020 Florian Schmaus. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jivesoftware.smackx.usertune; - -import org.jivesoftware.smack.packet.Message; - -import org.jivesoftware.smackx.usertune.element.UserTuneElement; - -import org.jxmpp.jid.EntityBareJid; - -public interface UserTuneListener { - - void onUserTuneUpdated(EntityBareJid jid, UserTuneElement userTuneElement, Message message); - -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java index 9b1a131af..7264b7227 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/usertune/UserTuneManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019 Aditya Borikar. + * Copyright 2019 Aditya Borikar, 2020 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,8 @@ */ package org.jivesoftware.smackx.usertune; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.CopyOnWriteArraySet; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.SmackException.NoResponseException; @@ -28,20 +25,14 @@ import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.pep.PepListener; +import org.jivesoftware.smackx.pep.PepEventListener; import org.jivesoftware.smackx.pep.PepManager; -import org.jivesoftware.smackx.pubsub.EventElement; -import org.jivesoftware.smackx.pubsub.ItemsExtension; import org.jivesoftware.smackx.pubsub.PayloadItem; import org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException; import org.jivesoftware.smackx.usertune.element.UserTuneElement; -import org.jxmpp.jid.EntityBareJid; - /** * Entry point for Smacks API for XEP-0118: User Tune. *
@@ -49,7 +40,7 @@ import org.jxmpp.jid.EntityBareJid; *
* To stop publishing a UserTune, please use {@link #clearUserTune()} method. This will send a disabling publish signal. *
- * To add a UserTune listener in order to remain updated with other users UserTune, use {@link #addUserTuneListener(UserTuneListener)} method. + * To add a UserTune listener in order to remain updated with other users UserTune, use {@link #addUserTuneListener(PepEventListener)} method. *
* To link a UserTuneElement with {@link Message}, use 'message.addExtension(userTuneElement)'. *
@@ -61,14 +52,9 @@ import org.jxmpp.jid.EntityBareJid; public final class UserTuneManager extends Manager { public static final String USERTUNE_NODE = "http://jabber.org/protocol/tune"; - public static final String USERTUNE_NOTIFY = USERTUNE_NODE + "+notify"; private static final Map INSTANCES = new WeakHashMap<>(); - private static boolean ENABLE_USER_TUNE_NOTIFICATIONS_BY_DEFAULT = true; - - private final Set userTuneListeners = new CopyOnWriteArraySet<>(); - private final ServiceDiscoveryManager serviceDiscoveryManager; private final PepManager pepManager; public static synchronized UserTuneManager getInstanceFor(XMPPConnection connection) throws NotLoggedInException { @@ -80,43 +66,9 @@ public final class UserTuneManager extends Manager { return manager; } - private UserTuneManager(XMPPConnection connection) throws NotLoggedInException { + private UserTuneManager(XMPPConnection connection) { super(connection); pepManager = PepManager.getInstanceFor(connection); - pepManager.addPepListener(new PepListener() { - @Override - public void eventReceived(EntityBareJid from, EventElement event, Message message) { - if (!USERTUNE_NODE.equals(event.getEvent().getNode())) { - return; - } - - ItemsExtension itemsExtension = (ItemsExtension) event.getEvent(); - List items = itemsExtension.getExtensions(); - @SuppressWarnings("unchecked") - PayloadItem payload = (PayloadItem) items.get(0); - UserTuneElement tune = payload.getPayload(); - - for (UserTuneListener listener : userTuneListeners) { - listener.onUserTuneUpdated(from, tune, message); - } - } - }); - serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); - if (ENABLE_USER_TUNE_NOTIFICATIONS_BY_DEFAULT) { - enableUserTuneNotifications(); - } - } - - public static void setUserTuneNotificationsEnabledByDefault(boolean bool) { - ENABLE_USER_TUNE_NOTIFICATIONS_BY_DEFAULT = bool; - } - - public void enableUserTuneNotifications() { - serviceDiscoveryManager.addFeature(USERTUNE_NOTIFY); - } - - public void disableUserTuneNotifications() { - serviceDiscoveryManager.removeFeature(USERTUNE_NOTIFY); } public void clearUserTune() throws NotLoggedInException, NotALeafNodeException, NoResponseException, NotConnectedException, XMPPErrorException, InterruptedException { @@ -128,11 +80,11 @@ public final class UserTuneManager extends Manager { pepManager.publish(USERTUNE_NODE, new PayloadItem<>(userTuneElement)); } - public boolean addUserTuneListener(UserTuneListener listener) { - return userTuneListeners.add(listener); + public boolean addUserTuneListener(PepEventListener listener) { + return pepManager.addPepEventListener(USERTUNE_NODE, UserTuneElement.class, listener); } - public boolean removeUserTuneListener(UserTuneListener listener) { - return userTuneListeners.remove(listener); + public boolean removeUserTuneListener(PepEventListener listener) { + return pepManager.removePepEventListener(listener); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java index f6db34dae..af86bb996 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java @@ -25,9 +25,9 @@ import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smackx.geoloc.GeoLocationListener; import org.jivesoftware.smackx.geoloc.GeoLocationManager; import org.jivesoftware.smackx.geoloc.packet.GeoLocation; +import org.jivesoftware.smackx.pep.PepEventListener; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; @@ -79,10 +79,10 @@ public class GeolocationIntegrationTest extends AbstractSmackIntegrationTest { IntegrationTestRosterUtil.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout); final SimpleResultSyncPoint geoLocationReceived = new SimpleResultSyncPoint(); - final GeoLocationListener geoLocationListener = new GeoLocationListener() { + final PepEventListener geoLocationListener = new PepEventListener() { @Override - public void onGeoLocationUpdated(EntityBareJid jid, GeoLocation geoLocation, Message message) { + public void onPepEvent(EntityBareJid jid, GeoLocation geoLocation, String id, Message message) { if (geoLocation.equals(geoLocation1)) { geoLocationReceived.signal(); } @@ -92,7 +92,7 @@ public class GeolocationIntegrationTest extends AbstractSmackIntegrationTest { glm2.addGeoLocationListener(geoLocationListener); try { - glm1.sendGeolocation(geoLocation1); + glm1.publishGeoLocation(geoLocation1); geoLocationReceived.waitForResult(timeout); } finally { glm2.removeGeoLocationListener(geoLocationListener); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java index faccc9a83..d2eff1080 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java @@ -19,6 +19,9 @@ package org.jivesoftware.smackx.mood; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.mood.element.MoodElement; +import org.jivesoftware.smackx.pep.PepEventListener; + import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; @@ -43,7 +46,7 @@ public class MoodIntegrationTest extends AbstractSmackIntegrationTest { final SimpleResultSyncPoint moodReceived = new SimpleResultSyncPoint(); - final MoodListener moodListener = (jid, moodElement, message) -> { + final PepEventListener moodListener = (jid, moodElement, id, message) -> { if (moodElement.getMood() == Mood.satisfied) { moodReceived.signal(); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java index 45ddec6f0..0309f9af0 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java @@ -23,6 +23,7 @@ import org.jivesoftware.smack.SmackException.NotLoggedInException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.pep.PepEventListener; import org.jivesoftware.smackx.usertune.element.UserTuneElement; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; @@ -61,9 +62,9 @@ public class UserTuneIntegrationTest extends AbstractSmackIntegrationTest { final SimpleResultSyncPoint userTuneReceived = new SimpleResultSyncPoint(); - final UserTuneListener userTuneListener = new UserTuneListener() { + final PepEventListener userTuneListener = new PepEventListener() { @Override - public void onUserTuneUpdated(EntityBareJid jid, UserTuneElement userTuneElement, Message message) { + public void onPepEvent(EntityBareJid jid, UserTuneElement userTuneElement, String id, Message message) { if (userTuneElement.equals(userTuneElement1)) { userTuneReceived.signal(); }