Browse Source

Add support for XEP-0242: Message Retraction

messageRetraction
Paul Schaub 2 months ago
parent
commit
b0b70884e8
13 changed files with 536 additions and 0 deletions
  1. +1
    -0
      documentation/extensions/index.md
  2. +88
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java
  3. +44
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/RetractElement.java
  4. +65
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/RetractedElement.java
  5. +25
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/package-info.java
  6. +25
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/package-info.java
  7. +34
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/RetractElementProvider.java
  8. +52
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/RetractedElementProvider.java
  9. +25
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/package-info.java
  10. +12
    -0
      smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
  11. +55
    -0
      smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManagerTest.java
  12. +49
    -0
      smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/element/RetractElementTest.java
  13. +61
    -0
      smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/element/RetractedElementTest.java

+ 1
- 0
documentation/extensions/index.md View File

@@ -110,6 +110,7 @@ Experimental Smack Extensions and currently supported XEPs of smack-experimental
| [Message Markup](messagemarkup.md) | [XEP-0394](https://xmpp.org/extensions/xep-0394.html) | 0.1.0 | Style message bodies while keeping body and markup information separated. |
| DNS Queries over XMPP (DoX) | [XEP-0418](https://xmpp.org/extensions/xep-0418.html) | 0.1.0 | Send DNS queries and responses over XMPP. |
| Message Fastening | [XEP-0422](https://xmpp.org/extensions/xep-0422.html) | 0.1.1 | Mark payloads on a message to be logistically fastened to a previous message. |
| Message Retraction | [XEP-0424](https://xmpp.org/extensions/xep-0424.html) | 0.2.0 | Mark messages as retracted. |

Unofficial XMPP Extensions
--------------------------


+ 88
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java View File

@@ -0,0 +1,88 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction;

import java.util.Map;
import java.util.WeakHashMap;

import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.message_fastening.MessageFasteningManager;
import org.jivesoftware.smackx.message_fastening.element.FasteningElement;
import org.jivesoftware.smackx.message_retraction.element.RetractElement;
import org.jivesoftware.smackx.sid.element.OriginIdElement;

public final class MessageRetractionManager extends Manager {

private static final Map<XMPPConnection, MessageRetractionManager> INSTANCES = new WeakHashMap<>();

static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection).announceSupport();
}
});
}

private final MessageFasteningManager fasteningManager;

private MessageRetractionManager(XMPPConnection connection) {
super(connection);
fasteningManager = MessageFasteningManager.getInstanceFor(connection);
}

public static synchronized MessageRetractionManager getInstanceFor(XMPPConnection connection) {
MessageRetractionManager manager = INSTANCES.get(connection);
if (manager == null) {
manager = new MessageRetractionManager(connection);
INSTANCES.put(connection, manager);
}
return manager;
}

/**
* Announce support for Message Retraction to the server.
*
* @see <a href="https://xmpp.org/extensions/xep-0424.html#disco">XEP-0424: Message Retraction: §2. Discovering Support</a>
*/
public void announceSupport() {
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(RetractElement.NAMESPACE);
}

/**
* Retract a message by appending a {@link RetractElement} wrapped inside a {@link FasteningElement} which contains
* the {@link OriginIdElement Origin-ID} of the message that will be retracted to a new message.
*
* Note: The provided message is NOT the message that will be retracted. Rather it is the carrier message that will
* transport the retraction to the recipient.
*
* @param retractedMessageId {@link OriginIdElement OriginID} of the message that the user wants to retract
* @param carrierMessage message used to transmit the message retraction to the recipient
*/
public void addRetractionElementToMessage(OriginIdElement retractedMessageId, Message carrierMessage) {
FasteningElement fasteningElement = FasteningElement.builder()
.setOriginId(retractedMessageId)
.addWrappedPayload(new RetractElement())
.build();
fasteningManager.addFasteningElementToStanza(fasteningElement, carrierMessage);
}
}

+ 44
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/RetractElement.java View File

@@ -0,0 +1,44 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.element;

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;

public class RetractElement implements ExtensionElement {

private static final String NAMESPACE_WITHOUT_VERSION = "urn:xmpp:message-retract";
private static final String NAMESPACE_0 = NAMESPACE_WITHOUT_VERSION + ":0";
public static final String NAMESPACE = NAMESPACE_0;
public static final String ELEMENT = "retract";

@Override
public String getNamespace() {
return NAMESPACE;
}

@Override
public String getElementName() {
return ELEMENT;
}

@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this).closeEmptyElement();
}
}

+ 65
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/RetractedElement.java View File

@@ -0,0 +1,65 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.element;

import java.util.Date;

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.sid.element.OriginIdElement;

public class RetractedElement implements ExtensionElement {

public static final String ELEMENT = "retracted";
public static final String ATTR_STAMP = "stamp";

private final Date stamp;
private final OriginIdElement originId;

public RetractedElement(Date stamp, OriginIdElement originId) {
this.stamp = stamp;
this.originId = originId;
}

public Date getStamp() {
return stamp;
}

public OriginIdElement getOriginId() {
return originId;
}

@Override
public String getNamespace() {
return RetractElement.NAMESPACE;
}

@Override
public String getElementName() {
return ELEMENT;
}

@Override
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.attribute(ATTR_STAMP, getStamp())
.rightAngleBracket()
.append(getOriginId())
.closeElement(this);
}
}

+ 25
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/element/package-info.java View File

@@ -0,0 +1,25 @@
/**
*
* Copyright 2019 Paul Schaub
*
* 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.
*/

/**
* XEP-0424: Message Retraction. Element classes.
*
* @see <a href="https://xmpp.org/extensions/xep-0424.html">XEP-0424: Message
* Retraction</a>
*
*/
package org.jivesoftware.smackx.message_retraction.element;

+ 25
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/package-info.java View File

@@ -0,0 +1,25 @@
/**
*
* Copyright 2019 Paul Schaub
*
* 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.
*/

/**
* XEP-0424: Message Retraction.
*
* @see <a href="https://xmpp.org/extensions/xep-0424.html">XEP-0424: Message
* Retraction</a>
*
*/
package org.jivesoftware.smackx.message_retraction;

+ 34
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/RetractElementProvider.java View File

@@ -0,0 +1,34 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.provider;

import java.io.IOException;

import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.message_retraction.element.RetractElement;

public class RetractElementProvider extends ExtensionElementProvider<RetractElement> {

@Override
public RetractElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException {
return new RetractElement();
}
}

+ 52
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/RetractedElementProvider.java View File

@@ -0,0 +1,52 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.provider;

import java.io.IOException;
import java.util.Date;

import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.message_retraction.element.RetractedElement;
import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
import org.jivesoftware.smackx.sid.element.OriginIdElement;
import org.jivesoftware.smackx.sid.provider.OriginIdProvider;

public class RetractedElementProvider extends ExtensionElementProvider<RetractedElement> {

@Override
public RetractedElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
throws XmlPullParserException, IOException, SmackParsingException {
Date date = ParserUtils.getDateFromXep82String(parser.getAttributeValue("", RetractedElement.ATTR_STAMP));

OriginIdElement originIdElement = null;
while (originIdElement == null) {
XmlPullParser.TagEvent tag = parser.nextTag();
if (tag == XmlPullParser.TagEvent.START_ELEMENT
&& OriginIdElement.ELEMENT.equals(parser.getName())
&& StableUniqueStanzaIdManager.NAMESPACE.equals(parser.getNamespace())) {
originIdElement = OriginIdProvider.INSTANCE.parse(parser);
}
}

return new RetractedElement(date, originIdElement);
}
}

+ 25
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/provider/package-info.java View File

@@ -0,0 +1,25 @@
/**
*
* Copyright 2019 Paul Schaub
*
* 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.
*/

/**
* XEP-0424: Message Retraction. Provider classes.
*
* @see <a href="https://xmpp.org/extensions/xep-0424.html">XEP-0424: Message
* Retraction</a>
*
*/
package org.jivesoftware.smackx.message_retraction.provider;

+ 12
- 0
smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers View File

@@ -331,6 +331,18 @@
<className>org.jivesoftware.smackx.message_fastening.provider.FasteningElementProvider</className>
</extensionProvider>

<!-- XEP-0424: Message Retraction -->
<extensionProvider>
<elementName>retract</elementName>
<namespace>urn:xmpp:message-retract:0</namespace>
<className>org.jivesoftware.smackx.message_retraction.provider.RetractElementProvider</className>
</extensionProvider>
<extensionProvider>
<elementName>retracted</elementName>
<namespace>urn:xmpp:message-retract:0</namespace>
<className>org.jivesoftware.smackx.message_retraction.provider.RetractedElementProvider</className>
</extensionProvider>

<!-- XEP-0328: JID Prep -->
<iqProvider>
<elementName>jid</elementName>


+ 55
- 0
smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManagerTest.java View File

@@ -0,0 +1,55 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.jivesoftware.smack.DummyConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.StanzaBuilder;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.message_fastening.MessageFasteningManager;
import org.jivesoftware.smackx.message_fastening.element.FasteningElement;
import org.jivesoftware.smackx.message_retraction.element.RetractElement;
import org.jivesoftware.smackx.sid.element.OriginIdElement;

import org.junit.jupiter.api.Test;

public class MessageRetractionManagerTest extends SmackTestSuite {

@Test
public void addRetractionElementToMessageTest() {
DummyConnection dummyConnection = new DummyConnection();
MessageRetractionManager manager = MessageRetractionManager.getInstanceFor(dummyConnection);

Message transmissionMessage = StanzaBuilder.buildMessage().build();
OriginIdElement idOfRetractedMessage = new OriginIdElement();

assertFalse(FasteningElement.hasFasteningElement(transmissionMessage));
manager.addRetractionElementToMessage(idOfRetractedMessage, transmissionMessage);
assertTrue(FasteningElement.hasFasteningElement(transmissionMessage));

FasteningElement fasteningElement = transmissionMessage.getExtension(FasteningElement.ELEMENT, MessageFasteningManager.NAMESPACE);
assertEquals(idOfRetractedMessage, fasteningElement.getReferencedStanzasOriginId());
assertEquals(1, fasteningElement.getWrappedPayloads().size());
RetractElement retractElement = (RetractElement) fasteningElement.getWrappedPayloads().get(0);
assertNotNull(retractElement);
}
}

+ 49
- 0
smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/element/RetractElementTest.java View File

@@ -0,0 +1,49 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.element;

import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;

import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.message_retraction.provider.RetractElementProvider;

import org.junit.jupiter.api.Test;

public class RetractElementTest {

@Test
public void serializationTest() {
RetractElement retractElement = new RetractElement();
String expectedXml = "<retract xmlns='urn:xmpp:message-retract:0'/>";

assertXmlSimilar(expectedXml, retractElement.toXML());
}

@Test
public void deserializationTest() throws XmlPullParserException, IOException, SmackParsingException {
String xml = "<retract xmlns='urn:xmpp:message-retract:0'/>";
RetractElementProvider provider = new RetractElementProvider();
RetractElement element = provider.parse(TestUtils.getParser(xml));

assertNotNull(element);
}
}

+ 61
- 0
smack-experimental/src/test/java/org/jivesoftware/smackx/message_retraction/element/RetractedElementTest.java View File

@@ -0,0 +1,61 @@
/**
*
* Copyright 2020 Paul Schaub
*
* 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.message_retraction.element;

import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;

import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.message_retraction.provider.RetractedElementProvider;
import org.jivesoftware.smackx.sid.element.OriginIdElement;

import org.junit.jupiter.api.Test;
import org.jxmpp.util.XmppDateTime;

public class RetractedElementTest {

@Test
public void serializationTest() throws ParseException {
Date stamp = XmppDateTime.parseXEP0082Date("2019-09-20T23:08:25.000+00:00");
OriginIdElement originId = new OriginIdElement("origin-id-1");
RetractedElement retractedElement = new RetractedElement(stamp, originId);
String expectedXml = "" +
"<retracted stamp='2019-09-20T23:08:25.000+00:00' xmlns='urn:xmpp:message-retract:0'>\n" +
" <origin-id xmlns='urn:xmpp:sid:0' id='origin-id-1'/>\n" +
"</retracted>";

assertXmlSimilar(expectedXml, retractedElement.toXML());
}

@Test
public void deserializationTest() throws XmlPullParserException, IOException, SmackParsingException {
String xml = "" +
"<retracted stamp='2019-09-20T23:08:25.000+00:00' xmlns='urn:xmpp:message-retract:0'>\n" +
" <origin-id xmlns='urn:xmpp:sid:0' id='origin-id-1'/>\n" +
"</retracted>";
RetractedElementProvider provider = new RetractedElementProvider();

RetractedElement element = provider.parse(TestUtils.getParser(xml));
assertNotNull(element.getOriginId());
}
}

Loading…
Cancel
Save