Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a colibri2 conference-notification IQ. #64

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Copyright @ 2022 - present 8x8, Inc.
*
* 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.jitsi.xmpp.extensions.colibri2;

import org.jetbrains.annotations.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.parsing.*;
import org.jivesoftware.smack.provider.*;
import org.jivesoftware.smack.xml.*;

import javax.xml.namespace.*;
import java.io.*;
import java.util.*;

public class ConferenceNotificationIQ extends IQ
{
/**
* The XML element name of the Colibri2 <tt>conference-notification</tt> IQ.
*/
public static final String ELEMENT = "conference-notification";

/**
* The Colibri2 XML namespace.
*/
public static final String NAMESPACE = AbstractConferenceModificationIQ.NAMESPACE;

/**
* The qualified name of the element.
*/
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

/**
* The XML name of the <tt>meeting-id</tt> attribute.
*/
public static final String MEETING_ID_ATTR_NAME = "meeting-id";


@Contract("_ -> new")
public static @NotNull ConferenceNotificationIQ.Builder builder(IqData iqData)
{
return new ConferenceNotificationIQ.Builder(iqData);
}

@Contract("_ -> new")
public static @NotNull ConferenceNotificationIQ.Builder builder(String stanzaId)
{
return new ConferenceNotificationIQ.Builder(stanzaId);
}

@Contract("_ -> new")
public static @NotNull ConferenceNotificationIQ.Builder builder(XMPPConnection connection)
{
return new ConferenceNotificationIQ.Builder(connection);
}

/**
* The id of the conference
*/
private final @NotNull String meetingId;

/** Initializes a new {@link ConferenceModifyIQ} instance. */
protected ConferenceNotificationIQ(ConferenceNotificationIQ.Builder b)
{
super(b, ELEMENT, NAMESPACE);

if (b.meetingId == null)
{
throw new IllegalArgumentException("meeting-id must be set for " + ELEMENT + " IQ");
}
meetingId = b.meetingId;

for (Colibri2Endpoint endpoint: b.endpoints)
{
addExtension(endpoint);
}
}

/**
* Get endpoints described by the message
*/
public @NotNull List<Colibri2Endpoint> getEndpoints()
{
return getExtensions(Colibri2Endpoint.class);
}

/**
* Get the ID of the conference.
*/
public @NotNull String getMeetingId()
{
return meetingId;
}

@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml)
{
xml.attribute(MEETING_ID_ATTR_NAME, meetingId);

/* All our elements are extensions, so we just need to return empty here. */
xml.setEmptyElement();

return xml;
}


public static class Builder
extends IqBuilder<Builder, ConferenceNotificationIQ>
{
private final List<Colibri2Endpoint> endpoints = new ArrayList<>();
private String meetingId;

private Builder(IqData iqCommon)
{
super(iqCommon);
}

private Builder(XMPPConnection connection)
{
super(connection);
}

private Builder(String stanzaId)
{
super(stanzaId);
}

public Builder addEndpoint(Colibri2Endpoint endpoint)
{
endpoints.add(endpoint);
return this;
}

public Builder setMeetingId(String meetingId)
{
this.meetingId = meetingId;
return this;
}

@Override
@Contract(" -> new")
public ConferenceNotificationIQ build()
{
return new ConferenceNotificationIQ(this);
}

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

public static class Provider extends IqProvider<ConferenceNotificationIQ>
{
@Override
public ConferenceNotificationIQ parse(
XmlPullParser parser,
int initialDepth,
IqData iqData,
XmlEnvironment xmlEnvironment)
throws XmlPullParserException, IOException, SmackParsingException
{
ConferenceNotificationIQ.Builder builder = ConferenceNotificationIQ.builder(iqData);
String meetingId = parser.getAttributeValue(MEETING_ID_ATTR_NAME);
if (meetingId == null)
{
throw new SmackParsingException.RequiredAttributeMissingException(MEETING_ID_ATTR_NAME);
}
builder.setMeetingId(meetingId);

ConferenceNotificationIQ iq = builder.build();
IqProviderUtils.parseExtensions(parser, initialDepth, iq);
return iq;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ public static void registerProviders()
new ConferenceModifyIQProvider());
ProviderManager.addIQProvider(ConferenceModifiedIQ.ELEMENT, ConferenceModifiedIQ.NAMESPACE,
new ConferenceModifiedIQProvider());
ProviderManager.addIQProvider(ConferenceNotificationIQ.ELEMENT, ConferenceNotificationIQ.NAMESPACE,
new ConferenceNotificationIQ.Provider());

ProviderManager.addExtensionProvider(Colibri2Endpoint.ELEMENT, Colibri2Endpoint.NAMESPACE,
new Colibri2Endpoint.Provider());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright @ 2022 - present 8x8, Inc.
*
* 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.jitsi.xmpp.extensions.colibri2;

import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.util.*;
import org.jivesoftware.smack.xml.*;
import org.junit.jupiter.api.*;
import org.xmlunit.builder.*;
import org.xmlunit.diff.*;

import static org.junit.jupiter.api.Assertions.*;

public class ConferenceNotificationIQTest
{
private static final String MEETING_ID = "88ff288c-5eeb-4ea9-bc2f-93ea38c43b78";
private static final String IQ_ID = "iq-id";
private static final String ENDPOINT_ID = "bd9b6765";

private static final String expectedXml =
"<iq xmlns='jabber:client' id='" + IQ_ID + "' type='get'>"
+ "<conference-notification xmlns='jitsi:colibri2' meeting-id='" + MEETING_ID + "'>"
+ "<endpoint id='" + ENDPOINT_ID + "' expire='true'/>"
+ "</conference-notification>"
+ "</iq>";

@BeforeAll
static void registerProviders()
{
IqProviderUtils.registerProviders();
}

@Test
public void buildColibriConferenceModifyTest()
{
ConferenceNotificationIQ.Builder iqBuilder = ConferenceNotificationIQ.builder(IQ_ID);

iqBuilder.setMeetingId(MEETING_ID);

Colibri2Endpoint.Builder endpointBuilder = Colibri2Endpoint.getBuilder();
endpointBuilder.setId(ENDPOINT_ID);
endpointBuilder.setExpire(true);

iqBuilder.addEndpoint(endpointBuilder.build());

ConferenceNotificationIQ iq = iqBuilder.build();

assertEquals(MEETING_ID, iq.getMeetingId(), "The meeting-id should be correctly set.");

Colibri2Endpoint endpoint = iq.getEndpoints().get(0);
assertNotNull(endpoint);
assertEquals(ENDPOINT_ID, endpoint.getId());
assertTrue(endpoint.getExpire());

Diff diff = DiffBuilder.compare(expectedXml).
withTest(iq.toXML().toString()).
checkForIdentical().build();

assertFalse(diff.hasDifferences(), diff.toString());
}

@Test
public void parseColibriConferenceModifyTest()
throws Exception
{
XmlPullParser parser = PacketParserUtils.getParserFor(expectedXml);
IQ parsedIq = PacketParserUtils.parseIQ(parser);

assertInstanceOf(ConferenceNotificationIQ.class, parsedIq);

ConferenceNotificationIQ iq = (ConferenceNotificationIQ) parsedIq;

assertEquals(MEETING_ID, iq.getMeetingId(), "The meeting-id should be correctly parsed");

Colibri2Endpoint endpoint = iq.getEndpoints().get(0);
assertNotNull(endpoint);
assertEquals(ENDPOINT_ID, endpoint.getId());
assertTrue(endpoint.getExpire());
}
}