Add a PEP PubSubManager to PEPManager

This commit is contained in:
Florian Schmaus 2018-08-15 18:07:42 +02:00
parent 5569782113
commit 4b3f757ed9
7 changed files with 72 additions and 39 deletions

View File

@ -89,6 +89,8 @@ public final class PEPManager extends Manager {
private final AsyncButOrdered<EntityBareJid> asyncButOrdered = new AsyncButOrdered<>(); private final AsyncButOrdered<EntityBareJid> asyncButOrdered = new AsyncButOrdered<>();
private final PubSubManager pepPubSubManager;
/** /**
* Creates a new PEP exchange manager. * Creates a new PEP exchange manager.
* *
@ -116,6 +118,12 @@ public final class PEPManager extends Manager {
}; };
// TODO Add filter to check if from supports PubSub as per xep163 2 2.4 // 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); connection.addSyncStanzaListener(packetListener, FROM_BARE_JID_WITH_EVENT_EXTENSION_FILTER);
pepPubSubManager = PubSubManager.getInstance(connection, null);
}
public PubSubManager getPepPubSubManager() {
return pepPubSubManager;
} }
/** /**

View File

@ -114,23 +114,36 @@ public final class PubSubManager extends Manager {
} }
/** /**
* Get the PubSub manager for the given connection and PubSub service. * Get the PubSub manager for the given connection and PubSub service. Use <code>null</code> as argument for
* pubSubService to retrieve a PubSubManager for the users PEP service.
* *
* @param connection the XMPP connection. * @param connection the XMPP connection.
* @param pubSubService the PubSub service. * @param pubSubService the PubSub service, may be <code>null</code>.
* @return a PubSub manager for the connection and service. * @return a PubSub manager for the connection and service.
*/ */
public static synchronized PubSubManager getInstance(XMPPConnection connection, BareJid pubSubService) { public static PubSubManager getInstance(XMPPConnection connection, BareJid pubSubService) {
Map<BareJid, PubSubManager> managers = INSTANCES.get(connection); if (pubSubService != null && connection.isAuthenticated() && connection.getUser().asBareJid().equals(pubSubService)) {
if (managers == null) { // PEP service.
managers = new HashMap<>(); pubSubService = null;
INSTANCES.put(connection, managers);
} }
PubSubManager pubSubManager = managers.get(pubSubService);
if (pubSubManager == null) { PubSubManager pubSubManager;
pubSubManager = new PubSubManager(connection, pubSubService); Map<BareJid, PubSubManager> managers;
managers.put(pubSubService, pubSubManager); synchronized (INSTANCES) {
managers = INSTANCES.get(connection);
if (managers == null) {
managers = new HashMap<>();
INSTANCES.put(connection, managers);
}
} }
synchronized (managers) {
pubSubManager = managers.get(pubSubService);
if (pubSubManager == null) {
pubSubManager = new PubSubManager(connection, pubSubService);
managers.put(pubSubService, pubSubManager);
}
}
return pubSubManager; return pubSubManager;
} }

View File

@ -37,6 +37,10 @@ public abstract class AbstractOpenPgpIntegrationTest extends AbstractSmackIntegr
protected final BareJid bob; protected final BareJid bob;
protected final BareJid chloe; protected final BareJid chloe;
protected final PEPManager alicePepManager;
protected final PEPManager bobPepManager;
protected final PEPManager chloePepManager;
protected AbstractOpenPgpIntegrationTest(SmackIntegrationTestEnvironment environment) protected AbstractOpenPgpIntegrationTest(SmackIntegrationTestEnvironment environment)
throws XMPPException.XMPPErrorException, TestNotPossibleException, SmackException.NotConnectedException, throws XMPPException.XMPPErrorException, TestNotPossibleException, SmackException.NotConnectedException,
InterruptedException, SmackException.NoResponseException { InterruptedException, SmackException.NoResponseException {
@ -54,9 +58,13 @@ public abstract class AbstractOpenPgpIntegrationTest extends AbstractSmackIntegr
this.bob = bobConnection.getUser().asBareJid(); this.bob = bobConnection.getUser().asBareJid();
this.chloe = chloeConnection.getUser().asBareJid(); this.chloe = chloeConnection.getUser().asBareJid();
OpenPgpPubSubUtil.deletePubkeysListNode(aliceConnection); this.alicePepManager = PEPManager.getInstanceFor(aliceConnection);
OpenPgpPubSubUtil.deletePubkeysListNode(bobConnection); this.bobPepManager = PEPManager.getInstanceFor(bobConnection);
OpenPgpPubSubUtil.deletePubkeysListNode(chloeConnection); this.chloePepManager = PEPManager.getInstanceFor(chloeConnection);
OpenPgpPubSubUtil.deletePubkeysListNode(alicePepManager);
OpenPgpPubSubUtil.deletePubkeysListNode(bobPepManager);
OpenPgpPubSubUtil.deletePubkeysListNode(chloePepManager);
} }
private static void throwIfPubSubNotSupported(XMPPConnection connection) private static void throwIfPubSubNotSupported(XMPPConnection connection)

View File

@ -119,7 +119,7 @@ public class OXSecretKeyBackupIntegrationTest extends AbstractOpenPgpIntegration
public void cleanUp() public void cleanUp()
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException {
OpenPgpPubSubUtil.deleteSecretKeyNode(aliceConnection); OpenPgpPubSubUtil.deleteSecretKeyNode(alicePepManager);
if (openPgpManager != null) { if (openPgpManager != null) {
openPgpManager.stopMetadataListener(); openPgpManager.stopMetadataListener();

View File

@ -167,14 +167,14 @@ public class OXInstantMessagingIntegrationTest extends AbstractOpenPgpIntegratio
public void deleteKeyMetadata() public void deleteKeyMetadata()
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException {
OpenPgpPubSubUtil.deletePubkeysListNode(aliceConnection); OpenPgpPubSubUtil.deletePubkeysListNode(alicePepManager);
OpenPgpPubSubUtil.deletePubkeysListNode(bobConnection); OpenPgpPubSubUtil.deletePubkeysListNode(bobPepManager);
if (aliceFingerprint != null) { if (aliceFingerprint != null) {
OpenPgpPubSubUtil.deletePublicKeyNode(aliceConnection, aliceFingerprint); OpenPgpPubSubUtil.deletePublicKeyNode(alicePepManager, aliceFingerprint);
} }
if (bobFingerprint != null) { if (bobFingerprint != null) {
OpenPgpPubSubUtil.deletePublicKeyNode(bobConnection, bobFingerprint); OpenPgpPubSubUtil.deletePublicKeyNode(bobPepManager, bobFingerprint);
} }
if (aliceOpenPgp != null) { if (aliceOpenPgp != null) {

View File

@ -166,6 +166,8 @@ public final class OpenPgpManager extends Manager {
*/ */
private OpenPgpProvider provider; private OpenPgpProvider provider;
private final PEPManager pepManager;
private final Set<SigncryptElementReceivedListener> signcryptElementReceivedListeners = new HashSet<>(); private final Set<SigncryptElementReceivedListener> signcryptElementReceivedListeners = new HashSet<>();
private final Set<SignElementReceivedListener> signElementReceivedListeners = new HashSet<>(); private final Set<SignElementReceivedListener> signElementReceivedListeners = new HashSet<>();
private final Set<CryptElementReceivedListener> cryptElementReceivedListeners = new HashSet<>(); private final Set<CryptElementReceivedListener> cryptElementReceivedListeners = new HashSet<>();
@ -178,6 +180,7 @@ public final class OpenPgpManager extends Manager {
private OpenPgpManager(XMPPConnection connection) { private OpenPgpManager(XMPPConnection connection) {
super(connection); super(connection);
ChatManager.getInstanceFor(connection).addIncomingListener(incomingOpenPgpMessageListener); ChatManager.getInstanceFor(connection).addIncomingListener(incomingOpenPgpMessageListener);
pepManager = PEPManager.getInstanceFor(connection);
} }
/** /**
@ -272,7 +275,7 @@ public final class OpenPgpManager extends Manager {
} }
// publish it // publish it
publishPublicKey(connection(), pubkeyElement, primaryFingerprint); publishPublicKey(pepManager, pubkeyElement, primaryFingerprint);
// Subscribe to public key changes // Subscribe to public key changes
PEPManager.getInstanceFor(connection()).addPEPListener(metadataListener); PEPManager.getInstanceFor(connection()).addPEPListener(metadataListener);
@ -439,7 +442,7 @@ public final class OpenPgpManager extends Manager {
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, SmackException.NotLoggedInException { SmackException.NoResponseException, SmackException.NotLoggedInException {
throwIfNotAuthenticated(); throwIfNotAuthenticated();
OpenPgpPubSubUtil.deleteSecretKeyNode(connection()); OpenPgpPubSubUtil.deleteSecretKeyNode(pepManager);
} }
/** /**
@ -467,7 +470,7 @@ public final class OpenPgpManager extends Manager {
NoBackupFoundException, PGPException { NoBackupFoundException, PGPException {
throwIfNoProviderSet(); throwIfNoProviderSet();
throwIfNotAuthenticated(); throwIfNotAuthenticated();
SecretkeyElement backup = OpenPgpPubSubUtil.fetchSecretKey(connection()); SecretkeyElement backup = OpenPgpPubSubUtil.fetchSecretKey(pepManager);
if (backup == null) { if (backup == null) {
throw new NoBackupFoundException(); throw new NoBackupFoundException();
} }

View File

@ -34,6 +34,7 @@ import org.jivesoftware.smackx.ox.OpenPgpManager;
import org.jivesoftware.smackx.ox.element.PubkeyElement; import org.jivesoftware.smackx.ox.element.PubkeyElement;
import org.jivesoftware.smackx.ox.element.PublicKeysListElement; import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
import org.jivesoftware.smackx.ox.element.SecretkeyElement; import org.jivesoftware.smackx.ox.element.SecretkeyElement;
import org.jivesoftware.smackx.pep.PEPManager;
import org.jivesoftware.smackx.pubsub.AccessModel; import org.jivesoftware.smackx.pubsub.AccessModel;
import org.jivesoftware.smackx.pubsub.ConfigureForm; import org.jivesoftware.smackx.pubsub.ConfigureForm;
import org.jivesoftware.smackx.pubsub.Item; import org.jivesoftware.smackx.pubsub.Item;
@ -111,7 +112,7 @@ public class OpenPgpPubSubUtil {
* *
* @see <a href="https://xmpp.org/extensions/xep-0373.html#annoucning-pubkey">XEP-0373 §4.1</a> * @see <a href="https://xmpp.org/extensions/xep-0373.html#annoucning-pubkey">XEP-0373 §4.1</a>
* *
* @param connection XMPP connection * @param pepManager The PEP manager.
* @param pubkeyElement {@link PubkeyElement} containing the public key * @param pubkeyElement {@link PubkeyElement} containing the public key
* @param fingerprint fingerprint of the public key * @param fingerprint fingerprint of the public key
* *
@ -122,12 +123,12 @@ public class OpenPgpPubSubUtil {
* @throws SmackException.NotConnectedException if we are not connected. * @throws SmackException.NotConnectedException if we are not connected.
* @throws SmackException.NoResponseException if the server doesn't respond. * @throws SmackException.NoResponseException if the server doesn't respond.
*/ */
public static void publishPublicKey(XMPPConnection connection, PubkeyElement pubkeyElement, OpenPgpV4Fingerprint fingerprint) public static void publishPublicKey(PEPManager pepManager, PubkeyElement pubkeyElement, OpenPgpV4Fingerprint fingerprint)
throws InterruptedException, PubSubException.NotALeafNodeException, throws InterruptedException, PubSubException.NotALeafNodeException,
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException { XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException {
String keyNodeName = PEP_NODE_PUBLIC_KEY(fingerprint); String keyNodeName = PEP_NODE_PUBLIC_KEY(fingerprint);
PubSubManager pm = PubSubManager.getInstance(connection, connection.getUser().asBareJid()); PubSubManager pm = pepManager.getPepPubSubManager();
// Check if key available at data node // Check if key available at data node
// If not, publish key to data node // If not, publish key to data node
@ -179,7 +180,7 @@ public class OpenPgpPubSubUtil {
public static PublicKeysListElement fetchPubkeysList(XMPPConnection connection) public static PublicKeysListElement fetchPubkeysList(XMPPConnection connection)
throws InterruptedException, XMPPException.XMPPErrorException, PubSubException.NotAPubSubNodeException, throws InterruptedException, XMPPException.XMPPErrorException, PubSubException.NotAPubSubNodeException,
PubSubException.NotALeafNodeException, SmackException.NotConnectedException, SmackException.NoResponseException { PubSubException.NotALeafNodeException, SmackException.NotConnectedException, SmackException.NoResponseException {
return fetchPubkeysList(connection, connection.getUser().asBareJid()); return fetchPubkeysList(connection, null);
} }
@ -218,7 +219,7 @@ public class OpenPgpPubSubUtil {
/** /**
* Delete our metadata node. * Delete our metadata node.
* *
* @param connection XMPP connection * @param pepManager The PEP manager.
* *
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error. * @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
* @throws SmackException.NotConnectedException if we are not connected. * @throws SmackException.NotConnectedException if we are not connected.
@ -226,17 +227,17 @@ public class OpenPgpPubSubUtil {
* @throws SmackException.NoResponseException if the server doesn't respond. * @throws SmackException.NoResponseException if the server doesn't respond.
* @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist. * @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist.
*/ */
public static boolean deletePubkeysListNode(XMPPConnection connection) public static boolean deletePubkeysListNode(PEPManager pepManager)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException {
PubSubManager pm = PubSubManager.getInstance(connection, connection.getUser().asBareJid()); PubSubManager pm = pepManager.getPepPubSubManager();
return pm.deleteNode(PEP_NODE_PUBLIC_KEYS); return pm.deleteNode(PEP_NODE_PUBLIC_KEYS);
} }
/** /**
* Delete the public key node of the key with fingerprint {@code fingerprint}. * Delete the public key node of the key with fingerprint {@code fingerprint}.
* *
* @param connection XMPP connection * @param pepManager The PEP manager.
* @param fingerprint fingerprint of the key we want to delete * @param fingerprint fingerprint of the key we want to delete
* *
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error. * @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
@ -245,10 +246,10 @@ public class OpenPgpPubSubUtil {
* @throws SmackException.NoResponseException if the server doesn't respond. * @throws SmackException.NoResponseException if the server doesn't respond.
* @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist. * @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist.
*/ */
public static boolean deletePublicKeyNode(XMPPConnection connection, OpenPgpV4Fingerprint fingerprint) public static boolean deletePublicKeyNode(PEPManager pepManager, OpenPgpV4Fingerprint fingerprint)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException {
PubSubManager pm = PubSubManager.getInstance(connection, connection.getUser().asBareJid()); PubSubManager pm = pepManager.getPepPubSubManager();
return pm.deleteNode(PEP_NODE_PUBLIC_KEY(fingerprint)); return pm.deleteNode(PEP_NODE_PUBLIC_KEY(fingerprint));
} }
@ -345,7 +346,7 @@ public class OpenPgpPubSubUtil {
if (!OpenPgpManager.serverSupportsSecretKeyBackups(connection)) { if (!OpenPgpManager.serverSupportsSecretKeyBackups(connection)) {
throw new SmackException.FeatureNotSupportedException("http://jabber.org/protocol/pubsub#access-whitelist"); throw new SmackException.FeatureNotSupportedException("http://jabber.org/protocol/pubsub#access-whitelist");
} }
PubSubManager pm = PubSubManager.getInstance(connection, connection.getUser().asBareJid()); PubSubManager pm = PEPManager.getInstanceFor(connection).getPepPubSubManager();
LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY); LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY);
OpenPgpPubSubUtil.changeAccessModelIfNecessary(secretKeyNode, AccessModel.whitelist); OpenPgpPubSubUtil.changeAccessModelIfNecessary(secretKeyNode, AccessModel.whitelist);
@ -358,7 +359,7 @@ public class OpenPgpPubSubUtil {
* @see <a href="https://xmpp.org/extensions/xep-0373.html#synchro-pep"> * @see <a href="https://xmpp.org/extensions/xep-0373.html#synchro-pep">
* XEP-0373 §5. Synchronizing the Secret Key with a Private PEP Node</a> * XEP-0373 §5. Synchronizing the Secret Key with a Private PEP Node</a>
* *
* @param connection {@link XMPPConnection} of the user. * @param pepManager the PEP manager.
* @return the secret key node or null, if it doesn't exist. * @return the secret key node or null, if it doesn't exist.
* *
* @throws InterruptedException if the thread gets interrupted * @throws InterruptedException if the thread gets interrupted
@ -367,10 +368,10 @@ public class OpenPgpPubSubUtil {
* @throws SmackException.NotConnectedException if we are not connected * @throws SmackException.NotConnectedException if we are not connected
* @throws SmackException.NoResponseException /watch?v=7U0FzQzJzyI * @throws SmackException.NoResponseException /watch?v=7U0FzQzJzyI
*/ */
public static SecretkeyElement fetchSecretKey(XMPPConnection connection) public static SecretkeyElement fetchSecretKey(PEPManager pepManager)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException {
PubSubManager pm = PubSubManager.getInstance(connection, connection.getUser().asBareJid()); PubSubManager pm = pepManager.getPepPubSubManager();
LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY); LeafNode secretKeyNode = pm.getOrCreateLeafNode(PEP_NODE_SECRET_KEY);
List<PayloadItem<SecretkeyElement>> list = secretKeyNode.getItems(1); List<PayloadItem<SecretkeyElement>> list = secretKeyNode.getItems(1);
if (list.size() == 0) { if (list.size() == 0) {
@ -384,7 +385,7 @@ public class OpenPgpPubSubUtil {
/** /**
* Delete the private backup node. * Delete the private backup node.
* *
* @param connection {@link XMPPConnection} of the user. * @param pepManager the PEP manager.
* *
* @throws XMPPException.XMPPErrorException if there is an XMPP protocol related issue * @throws XMPPException.XMPPErrorException if there is an XMPP protocol related issue
* @throws SmackException.NotConnectedException if we are not connected * @throws SmackException.NotConnectedException if we are not connected
@ -392,10 +393,10 @@ public class OpenPgpPubSubUtil {
* @throws SmackException.NoResponseException if the server sends no response * @throws SmackException.NoResponseException if the server sends no response
* @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist. * @return <code>true</code> if the node existed and was deleted, <code>false</code> if the node did not exist.
*/ */
public static boolean deleteSecretKeyNode(XMPPConnection connection) public static boolean deleteSecretKeyNode(PEPManager pepManager)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException {
PubSubManager pm = PubSubManager.getInstance(connection); PubSubManager pm = pepManager.getPepPubSubManager();
return pm.deleteNode(PEP_NODE_SECRET_KEY); return pm.deleteNode(PEP_NODE_SECRET_KEY);
} }