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 ca5bb629d..ca0a582b2 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 @@ -39,6 +39,7 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.pubsub.EventElement; import org.jivesoftware.smackx.pubsub.Item; import org.jivesoftware.smackx.pubsub.LeafNode; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import org.jivesoftware.smackx.pubsub.PubSubFeature; import org.jivesoftware.smackx.pubsub.PubSubManager; import org.jivesoftware.smackx.pubsub.filter.EventExtensionFilter; @@ -137,9 +138,10 @@ public final class PEPManager extends Manager { * @throws InterruptedException * @throws XMPPErrorException * @throws NoResponseException + * @throws NotAPubSubNodeException */ public void publish(Item item, String node) throws NotConnectedException, InterruptedException, - NoResponseException, XMPPErrorException { + NoResponseException, XMPPErrorException, NotAPubSubNodeException { XMPPConnection connection = connection(); PubSubManager pubSubManager = PubSubManager.getInstance(connection, connection.getUser().asEntityBareJid()); LeafNode pubSubNode = pubSubManager.getNode(node); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubAssertionError.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubAssertionError.java deleted file mode 100644 index 50bb26383..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubAssertionError.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * - * Copyright 2017 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.pubsub; - -import org.jxmpp.jid.BareJid; - -public abstract class PubSubAssertionError extends AssertionError { - - /** - * - */ - private static final long serialVersionUID = 1L; - - protected PubSubAssertionError(String message) { - super(message); - } - - public static class DiscoInfoNodeAssertionError extends PubSubAssertionError { - - /** - * - */ - private static final long serialVersionUID = 1L; - - DiscoInfoNodeAssertionError(BareJid pubSubService, String nodeId) { - super("PubSub service '" + pubSubService + "' returned disco info result for node '" + nodeId - + "', but it did not contain an Identity of type 'leaf' or 'collection' (and category 'pubsub'), which is not allowed according to XEP-60 5.3."); - } - - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubException.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubException.java index cb65d8278..5deac4931 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubException.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubException.java @@ -18,6 +18,8 @@ package org.jivesoftware.smackx.pubsub; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smackx.disco.packet.DiscoverInfo; + import org.jxmpp.jid.BareJid; public abstract class PubSubException extends SmackException { @@ -27,6 +29,16 @@ public abstract class PubSubException extends SmackException { */ private static final long serialVersionUID = 1L; + private final String nodeId; + + protected PubSubException(String nodeId) { + this.nodeId = nodeId; + } + + public String getNodeId() { + return nodeId; + } + public static class NotALeafNodeException extends PubSubException { /** @@ -34,21 +46,35 @@ public abstract class PubSubException extends SmackException { */ private static final long serialVersionUID = 1L; - private final String nodeId; private final BareJid pubSubService; NotALeafNodeException(String nodeId, BareJid pubSubService) { - this.nodeId = nodeId; + super(nodeId); this.pubSubService = pubSubService; } - public String getNodeId() { - return nodeId; - } - public BareJid getPubSubService() { return pubSubService; } } + + public static class NotAPubSubNodeException extends PubSubException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private final DiscoverInfo discoverInfo; + + NotAPubSubNodeException(String nodeId, DiscoverInfo discoverInfo) { + super(nodeId); + this.discoverInfo = discoverInfo; + } + + public DiscoverInfo getDiscoverInfo() { + return discoverInfo; + } + } } 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 c16ce3073..4a364c5a7 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 @@ -42,6 +42,7 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverItems; import org.jivesoftware.smackx.pubsub.PubSubException.NotALeafNodeException; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import org.jivesoftware.smackx.pubsub.packet.PubSub; import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace; import org.jivesoftware.smackx.pubsub.util.NodeUtils; @@ -229,8 +230,9 @@ public final class PubSubManager extends Manager { * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException * @throws InterruptedException + * @throws NotAPubSubNodeException */ - public T getNode(String id) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException + public T getNode(String id) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotAPubSubNodeException { Node node = nodeMap.get(id); @@ -249,10 +251,7 @@ public final class PubSubManager extends Manager { node = new CollectionNode(this, id); } else { - // XEP-60 5.3 states that - // "The 'disco#info' result MUST include an identity with a category of 'pubsub' and a type of either 'leaf' or 'collection'." - // If this is not the case, then we are dealing with an PubSub implementation that doesn't follow the specification. - throw new PubSubAssertionError.DiscoInfoNodeAssertionError(pubSubService, id); + throw new PubSubException.NotAPubSubNodeException(id, infoReply); } nodeMap.put(id, node); } @@ -278,6 +277,9 @@ public final class PubSubManager extends Manager { try { return getNode(id); } + catch (NotAPubSubNodeException e) { + return createNode(id); + } catch (XMPPErrorException e1) { if (e1.getXMPPError().getCondition() == Condition.item_not_found) { try { @@ -286,7 +288,13 @@ public final class PubSubManager extends Manager { catch (XMPPErrorException e2) { if (e2.getXMPPError().getCondition() == Condition.conflict) { // The node was created in the meantime, re-try getNode(). Note that this case should be rare. - return getNode(id); + try { + return getNode(id); + } + catch (NotAPubSubNodeException e) { + // Should not happen + throw new IllegalStateException(e); + } } throw e2; } @@ -313,10 +321,11 @@ public final class PubSubManager extends Manager { * @throws NotConnectedException * @throws InterruptedException * @throws XMPPErrorException + * @throws NotAPubSubNodeException * @since 4.2.1 */ public LeafNode getLeafNode(String id) throws NotALeafNodeException, NoResponseException, NotConnectedException, - InterruptedException, XMPPErrorException { + InterruptedException, XMPPErrorException, NotAPubSubNodeException { Node node; try { node = getNode(id); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoInitializationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoInitializationTest.java index 155b9ca3a..e019dce82 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoInitializationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoInitializationTest.java @@ -30,6 +30,7 @@ import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.util.OmemoConstants; import org.jivesoftware.smackx.pubsub.PubSubException; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import org.igniterealtime.smack.inttest.SmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; @@ -52,9 +53,10 @@ public class OmemoInitializationTest extends AbstractOmemoIntegrationTest { /** * Tests, if the initialization is done properly. + * @throws NotAPubSubNodeException */ @SmackIntegrationTest - public void initializationTest() throws XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.NotLoggedInException, CorruptedOmemoKeyException { + public void initializationTest() throws XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.NotLoggedInException, CorruptedOmemoKeyException, NotAPubSubNodeException { //test keys. setUpOmemoManager(alice); assertNotNull("IdentityKey must not be null after initialization.", store.loadOmemoIdentityKeyPair(alice)); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoIntegrationTestHelper.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoIntegrationTestHelper.java index 08b9b356b..78895cf08 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoIntegrationTestHelper.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoIntegrationTestHelper.java @@ -34,8 +34,8 @@ import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionExcep import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.internal.CachedDeviceList; import org.jivesoftware.smackx.omemo.util.OmemoConstants; -import org.jivesoftware.smackx.pubsub.PubSubAssertionError; import org.jivesoftware.smackx.pubsub.PubSubException; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import org.jivesoftware.smackx.pubsub.PubSubManager; /** @@ -70,26 +70,26 @@ final class OmemoIntegrationTestHelper { for (int id : deviceList.getAllDevices()) { try { pm.getLeafNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id)).deleteAllItems(); - } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | PubSubAssertionError.DiscoInfoNodeAssertionError e) { + } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) { //Silent } try { pm.deleteNode(OmemoConstants.PEP_NODE_BUNDLE_FROM_DEVICE_ID(id)); - } catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | PubSubAssertionError e) { + } catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) { //Silent } } try { pm.getLeafNode(OmemoConstants.PEP_NODE_DEVICE_LIST).deleteAllItems(); - } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | PubSubAssertionError.DiscoInfoNodeAssertionError e) { + } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | PubSubException.NotALeafNodeException | XMPPException.XMPPErrorException | NotAPubSubNodeException e) { //Silent } try { pm.deleteNode(OmemoConstants.PEP_NODE_DEVICE_LIST); - } catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException | PubSubAssertionError e) { + } catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) { //Silent } } @@ -147,7 +147,7 @@ final class OmemoIntegrationTestHelper { } - static void setUpOmemoManager(OmemoManager omemoManager) throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NotLoggedInException, PubSubException.NotALeafNodeException { + static void setUpOmemoManager(OmemoManager omemoManager) throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NotLoggedInException, PubSubException.NotALeafNodeException, NotAPubSubNodeException { omemoManager.initialize(); OmemoBundleElement bundle = OmemoService.fetchBundle(omemoManager, omemoManager.getOwnDevice()); assertNotNull("Bundle must not be null.", bundle); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessageSendingTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessageSendingTest.java index 690c19b81..bcdc29ed3 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessageSendingTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessageSendingTest.java @@ -40,6 +40,7 @@ import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag; import org.jivesoftware.smackx.omemo.internal.OmemoMessageInformation; import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener; import org.jivesoftware.smackx.pubsub.PubSubException; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import junit.framework.TestCase; import org.igniterealtime.smack.inttest.SmackIntegrationTest; @@ -85,9 +86,15 @@ public class OmemoMessageSendingTest extends AbstractOmemoIntegrationTest { * @throws UndecidedOmemoIdentityException * @throws NoSuchAlgorithmException * @throws CryptoFailedException + * @throws NotAPubSubNodeException */ @SmackIntegrationTest - public void messageSendingTest() throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NotLoggedInException, PubSubException.NotALeafNodeException, CannotEstablishOmemoSessionException, UndecidedOmemoIdentityException, NoSuchAlgorithmException, CryptoFailedException { + public void messageSendingTest() + throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, + SmackException.NotConnectedException, XMPPException.XMPPErrorException, + SmackException.NotLoggedInException, PubSubException.NotALeafNodeException, + CannotEstablishOmemoSessionException, UndecidedOmemoIdentityException, NoSuchAlgorithmException, + CryptoFailedException, PubSubException.NotAPubSubNodeException { final String alicesSecret = "Hey Bob! I love you!"; final String bobsSecret = "I love you too, Alice."; //aww <3 diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java index 9138ca15f..093767166 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java @@ -82,8 +82,8 @@ import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder; import org.jivesoftware.smackx.pep.PEPManager; import org.jivesoftware.smackx.pubsub.LeafNode; import org.jivesoftware.smackx.pubsub.PayloadItem; -import org.jivesoftware.smackx.pubsub.PubSubAssertionError; import org.jivesoftware.smackx.pubsub.PubSubException; +import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException; import org.jivesoftware.smackx.pubsub.PubSubManager; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -428,11 +428,11 @@ public abstract class OmemoService