Browse Source

Attempt implementing first IQs

mix
Paul Schaub 3 months ago
parent
commit
c9efa5581d
No known key found for this signature in database GPG Key ID: 62BEE9264BF17311
9 changed files with 255 additions and 11 deletions
  1. +8
    -3
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/MixManager.java
  2. +33
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQ.java
  3. +78
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQBuilder.java
  4. +7
    -0
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/exception/NotAMixChannelOrNoPermissionToSubscribeException.java
  5. +35
    -3
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/misc/element/RegisterElement.java
  6. +1
    -1
      smack-experimental/src/main/java/org/jivesoftware/smackx/mix/misc/provider/RegisterElementProvider.java
  7. +25
    -0
      smack-experimental/src/test/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQTest.java
  8. +14
    -4
      smack-experimental/src/test/java/org/jivesoftware/smackx/mix/misc/element/RegisterElementTest.java
  9. +54
    -0
      smack-experimental/src/test/java/org/jivesoftware/smackx/mix/misc/provider/RegisterElementProviderTest.java

+ 8
- 3
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/MixManager.java View File

@@ -32,12 +32,12 @@ import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
import org.jivesoftware.smackx.mam.MamManager;
import org.jivesoftware.smackx.mam.element.MamElements;
import org.jivesoftware.smackx.mix.core.element.iq.ClientJoinIQ;
import org.jivesoftware.smackx.mix.core.element.iq.ClientJoinIQBuilder;
import org.jivesoftware.smackx.mix.core.exception.NotAMixChannelOrNoPermissionToSubscribeException;
import org.jivesoftware.smackx.mix.core.exception.NotAMixServiceException;
import org.jivesoftware.smackx.pubsub.packet.PubSub;
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;

import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityBareJid;
@@ -172,7 +172,12 @@ public final class MixManager extends Manager {
throws XMPPException.XMPPErrorException, NotAMixChannelOrNoPermissionToSubscribeException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
MixChannel channel = discoverMixChannelInformation(channelAddress);

ClientJoinIQ iq = new ClientJoinIQBuilder(connection())
.setNickname(nick)
.setChannelAddress(channelAddress)
.addMixNodeSubscription(MixNodes.NODE_MESSAGES)
.addMixNodeSubscription(MixNodes.NODE_PRESENCE)
.build();
return null;
}
}

+ 33
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQ.java View File

@@ -0,0 +1,33 @@
package org.jivesoftware.smackx.mix.core.element.iq;

import java.util.ArrayList;
import java.util.List;

import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.mix.core.element.JoinElement;
import org.jivesoftware.smackx.mix.core.element.NickElement;
import org.jivesoftware.smackx.mix.core.element.SubscribeElement;
import org.jivesoftware.smackx.mix.pam.element.ClientJoinElement;

import org.jxmpp.jid.EntityBareJid;

public class ClientJoinIQ extends IQ {

private final EntityBareJid channelJid;
private final NickElement nickElement;
private final List<SubscribeElement> subscriptions;

public ClientJoinIQ(ClientJoinIQBuilder builder) {
super(builder, ClientJoinElement.V2.ELEMENT, null);
this.channelJid = builder.getChannelAddress();
this.nickElement = builder.getNickElement();
this.subscriptions = new ArrayList<>(builder.getSubscriptions());
}

@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
JoinElement.V1 joinElement = new JoinElement.V1(subscriptions, nickElement);
xml.append(new ClientJoinElement.V2(channelJid, joinElement));
return xml;
}
}

+ 78
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQBuilder.java View File

@@ -0,0 +1,78 @@
package org.jivesoftware.smackx.mix.core.element.iq;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.AbstractIqBuilder;
import org.jivesoftware.smack.packet.IqBuilder;
import org.jivesoftware.smackx.mix.core.element.NickElement;
import org.jivesoftware.smackx.mix.core.element.SubscribeElement;

import org.jxmpp.jid.EntityBareJid;

public class ClientJoinIQBuilder extends IqBuilder<ClientJoinIQBuilder, ClientJoinIQ> {

private EntityBareJid channelAddress;
private NickElement nickElement;
private final Set<SubscribeElement> subscriptions = new HashSet<>();

protected ClientJoinIQBuilder(AbstractIqBuilder<?> other) {
super(other);
}

public ClientJoinIQBuilder(XMPPConnection connection) {
super(connection);
}

protected ClientJoinIQBuilder(String stanzaId) {
super(stanzaId);
}

@Override
public ClientJoinIQBuilder getThis() {
return this;
}

@Override
public ClientJoinIQ build() {
return new ClientJoinIQ(this);
}

public ClientJoinIQBuilder setChannelAddress(EntityBareJid channelAddress) {
this.channelAddress = channelAddress;
return getThis();
}

public ClientJoinIQBuilder addMixNodeSubscription(String nodeName) {
return addMixNodeSubscription(new SubscribeElement(nodeName));
}

public ClientJoinIQBuilder addMixNodeSubscription(SubscribeElement subscription) {
return addMixNodeSubscriptions(Collections.singleton(subscription));
}

public ClientJoinIQBuilder addMixNodeSubscriptions(Collection<SubscribeElement> subscriptions) {
this.subscriptions.addAll(subscriptions);
return getThis();
}

public ClientJoinIQBuilder setNickname(String nick) {
this.nickElement = nick != null ? new NickElement(nick) : null;
return getThis();
}

public EntityBareJid getChannelAddress() {
return channelAddress;
}

public NickElement getNickElement() {
return nickElement;
}

public Set<SubscribeElement> getSubscriptions() {
return subscriptions;
}
}

+ 7
- 0
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/core/exception/NotAMixChannelOrNoPermissionToSubscribeException.java View File

@@ -1,5 +1,12 @@
package org.jivesoftware.smackx.mix.core.exception;

/**
* Exception that is thrown when the user tries to interact with an entity which is either not a MIX channel,
* or is one but the user doesn't have the permission to subscribe to it.
*
* @see <a href="https://xmpp.org/extensions/xep-0369.html#disco-channel-info">
* XEP-0369: §6.3 about discovering channel information</a>
*/
public class NotAMixChannelOrNoPermissionToSubscribeException extends Exception {

private static final long serialVersionUID = 1L;


+ 35
- 3
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/misc/element/RegisterElement.java View File

@@ -4,18 +4,46 @@ import static org.jivesoftware.smackx.mix.misc.MixMiscConstants.NAMESPACE_MISC_0

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.mix.core.element.NickElement;

/**
* Element for registering a nick name with the MIX channel.
*
* see <a href="https://xmpp.org/extensions/xep-0407.html#usecase-user-register">
* XEP-0407: MIX Miscellaneous Capabilities - §3. Registering a Nick</a>
*/
public abstract class RegisterElement implements ExtensionElement {

public static final String ELEMENT = "register";

private final NickElement nick;

/**
* Create an empty register element.
* A MIX service must assign a nick name if the request does not contain a nick child element.
*/
public RegisterElement() {
this(null);
}

/**
* Create a register element with a desired nick name.
*
* @param nickElement nick element containing the nick name.
*/
public RegisterElement(NickElement nickElement) {
this.nick = Objects.requireNonNull(nickElement, "Nick element MUST NOT be null.");
this.nick = nickElement;
}

/**
* Return the nick child element.
* For a request, this is the requested nick name and for a response, this is the assigned nick name (might differ).
*
* @return nick element
*/
public NickElement getNick() {
return nick;
}

@Override
@@ -27,12 +55,16 @@ public abstract class RegisterElement implements ExtensionElement {
public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this)
.rightAngleBracket()
.append(nick)
.optAppend(nick)
.closeElement(this);
}

public static class V0 extends RegisterElement {

public V0() {
super();
}

public V0(NickElement nickElement) {
super(nickElement);
}


+ 1
- 1
smack-experimental/src/main/java/org/jivesoftware/smackx/mix/misc/provider/RegisterElementProvider.java View File

@@ -27,7 +27,7 @@ public abstract class RegisterElementProvider<E extends RegisterElement> extends
nickElement = new NickElement(parser.nextText());
}
} else if (tagEvent == XmlPullParser.TagEvent.END_ELEMENT) {
if (SetNickElement.ELEMENT.equals(name)) {
if (RegisterElement.ELEMENT.equals(name)) {
return new RegisterElement.V0(nickElement);
}
}


+ 25
- 0
smack-experimental/src/test/java/org/jivesoftware/smackx/mix/core/element/iq/ClientJoinIQTest.java View File

@@ -0,0 +1,25 @@
package org.jivesoftware.smackx.mix.core.element.iq;

import org.jivesoftware.smack.DummyConnection;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.test.util.SmackTestSuite;
import org.jivesoftware.smackx.mix.core.MixNodes;

import org.junit.jupiter.api.Test;
import org.jxmpp.jid.impl.JidCreate;

public class ClientJoinIQTest extends SmackTestSuite {

@Test
public void serializationTest() {
ClientJoinIQ iq = new ClientJoinIQBuilder(DummyConnection.newConnectedDummyConnection())
.ofType(IQ.Type.set)
.setNickname("alice")
.setChannelAddress(JidCreate.entityBareFromOrThrowUnchecked("rabbithole@mix.wonderland.lit"))
.addMixNodeSubscription(MixNodes.NODE_MESSAGES)
.addMixNodeSubscription(MixNodes.NODE_PRESENCE)
.build();

System.out.println(iq.toXML());
}
}

+ 14
- 4
smack-experimental/src/test/java/org/jivesoftware/smackx/mix/misc/element/RegisterElementTest.java View File

@@ -9,12 +9,22 @@ import org.junit.jupiter.api.Test;
public class RegisterElementTest {

@Test
public void v0testSerialization() {
public void testV0Serialization() {
RegisterElement register = new RegisterElement.V0(new NickElement("thirdwitch"));
String expectedXml = "" +
"<register xmlns='urn:xmpp:mix:misc:0'>\n" +
" <nick>thirdwitch</nick>\n" +
"</register>\n";
"<register xmlns='urn:xmpp:mix:misc:0'>" +
" <nick>thirdwitch</nick>" +
"</register>";

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

@Test
public void testV0NoNickSerialization() {
RegisterElement register = new RegisterElement.V0();
String expectedXml = "" +
"<register xmlns='urn:xmpp:mix:misc:0'>" +
"</register>";

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


+ 54
- 0
smack-experimental/src/test/java/org/jivesoftware/smackx/mix/misc/provider/RegisterElementProviderTest.java View File

@@ -0,0 +1,54 @@
package org.jivesoftware.smackx.mix.misc.provider;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.io.IOException;

import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.mix.misc.element.RegisterElement;

import org.junit.jupiter.api.Test;

public class RegisterElementProviderTest {

private final RegisterElementProvider.V0 provider = new RegisterElementProvider.V0();

@Test
public void testV0Parsing() throws XmlPullParserException, IOException, SmackParsingException {
final String xml = "" +
"<register xmlns='urn:xmpp:mix:misc:0'>" +
" <nick>thirdwitch</nick>" +
"</register>";
final String nick = "thirdwitch";
XmlPullParser parser = TestUtils.getParser(xml);

RegisterElement parsed = provider.parse(parser);
assertEquals(nick, parsed.getNick().getValue());
}

@Test
public void testV0NoNickElementParsing() throws XmlPullParserException, IOException, SmackParsingException {
final String noChildElementXml = "<register xmlns='urn:xmpp:mix:misc:0'></register>";
XmlPullParser noChildElementParser = TestUtils.getParser(noChildElementXml);

RegisterElement noChildElementParsed = provider.parse(noChildElementParser);

assertNull(noChildElementParsed.getNick());
}

@Test
public void testV0EmptyParsing() throws XmlPullParserException, IOException, SmackParsingException {
final String emptyElementXml = "<register xmlns='urn:xmpp:mix:misc:0'/>";
XmlPullParser emptyElementParser = TestUtils.getParser(emptyElementXml);

RegisterElement emptyElementParsed = provider.parse(emptyElementParser);

assertNull(emptyElementParsed.getNick());
}


}

Loading…
Cancel
Save