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 extends ExtensionElement> listener : nodeListeners) {
+ // TODO: Can there be more than one item?
+ List extends NamedElement> 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();
}