Skip to content

Commit

Permalink
Merge branch 'master' into ramabit.tbr.opt2
Browse files Browse the repository at this point in the history
  • Loading branch information
ramabit committed Aug 4, 2016
2 parents df79818 + d37d265 commit 96c05dc
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 135 deletions.
45 changes: 29 additions & 16 deletions documentation/extensions/muc.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ text-based conference rooms.

**XEP related:** [XEP-45](http://www.xmpp.org/extensions/xep-0045.html)

For all examples in this document, assume that the following variables exists:

```java
// Create the XMPP address (JID) of the MUC.
EntityBareJid mucJid = JidCreate.bareFrom("[email protected]");

// Create the nickname.
Resourcepart nickname = Resourcepart.from("testbot");

// A other use (we may invite him to a MUC).
FullJid otherJid = JidCreate.fullFromm("[email protected]/Smack");
```

Create a new Room
-----------------

Expand Down Expand Up @@ -52,10 +65,10 @@ In this example we can see how to create an instant room:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Get a MultiUserChat using MultiUserChatManager
MultiUserChat muc = manager.getMultiUserChat("[email protected]");
MultiUserChat muc = manager.getMultiUserChat(mucJid);

// Create the room and send an empty configuration form to make this an instant room
muc.create("testbot").makeInstant();
muc.create(nickname).makeInstant();
```

In this example we can see how to create a reserved room. The form is
Expand All @@ -66,13 +79,13 @@ completed with default values:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc = = manager.getMultiUserChat("[email protected]");
MultiUserChat muc = = manager.getMultiUserChat(mucJid);

// Prepare a list of owners of the new room
Set<Jid> owners = JidUtil.jidSetFrom(new String[] { "[email protected]", "[email protected]" });

// Create the room
muc.create("testbot")
muc.create(nickname)
.getConfigFormManger()
.setRoomOwners(owners)
.submitConfigurationForm();
Expand Down Expand Up @@ -116,11 +129,11 @@ In this example we can see how to join a room with a given nickname:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc2 = manager.getMultiUserChat("[email protected]");
MultiUserChat muc2 = manager.getMultiUserChat(mucJid);

// User2 joins the new room
// The room service will decide the amount of history to send
muc2.join("testbot2");
muc2.join(nickname);
```

In this example we can see how to join a room with a given nickname and
Expand All @@ -131,11 +144,11 @@ password:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc2 = manager.getMultiUserChat("[email protected]");
MultiUserChat muc2 = manager.getMultiUserChat(mucJid);

// User2 joins the new room using a password
// The room service will decide the amount of history to send
muc2.join("testbot2", "password");
muc2.join(nickname, "password");
```

In this example we can see how to join a room with a given nickname specifying
Expand All @@ -146,13 +159,13 @@ the amount of history to receive:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc2 = manager.getMultiUserChat("[email protected]");
MultiUserChat muc2 = manager.getMultiUserChat(mucJid);

// User2 joins the new room using a password and specifying
// the amount of history to receive. In this example we are requesting the last 5 messages.
DiscussionHistory history = new DiscussionHistory();
history.setMaxStanzas(5);
muc2.join("testbot2", "password", history, conn1.getPacketReplyTimeout());
muc2.join(nickname, "password", history, conn1.getPacketReplyTimeout());
```

Manage room invitations
Expand Down Expand Up @@ -193,17 +206,17 @@ for possible rejections:
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);

// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc2 = manager.getMultiUserChat("[email protected]");
MultiUserChat muc2 = manager.getMultiUserChat(mucJid);

muc2.join("testbot2");
muc2.join(nickname);
// User2 listens for invitation rejections
muc2.addInvitationRejectionListener(new InvitationRejectionListener() {
public void invitationDeclined(String invitee, String reason) {
// Do whatever you need here...
}
});
// User2 invites user3 to join to the room
muc2.invite("[email protected]/Smack", "Meet me in this excellent room");
muc2.invite(otherJid, "Meet me in this excellent room");
```

In this example we can see how to listen for room invitations and decline
Expand All @@ -212,9 +225,9 @@ invitations:
```java
// User3 listens for MUC invitations
MultiUserChatManager.getInstanceFor(connection).addInvitationListener(new InvitationListener() {
public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) {
public void invitationReceived(XMPPConnection conn, String room, EntityFullJid inviter, String reason, String password) {
// Reject the invitation
MultiUserChat.decline(conn, room, inviter, "I'm busy right now");
MultiUserChat.decline(conn, room, inviter.asBareJid()s, "I'm busy right now");
}
});
```
Expand All @@ -241,7 +254,7 @@ In this example we can see how to discover support of MUC:

```java
// Discover whether [email protected] supports MUC or not
boolean supports = MultiUserChatManager.getInstanceFor(connection).isServiceEnabled("[email protected]/Smack");
boolean supports = MultiUserChatManager.getInstanceFor(connection).isServiceEnabled(otherJid);
```

Discover joined rooms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,31 +192,55 @@ public <P extends Stanza> P nextResult(long timeout) throws InterruptedException
}

/**
* Returns the next available packet. The method call will block until a stanza(/packet) is available or
* the connections reply timeout has elapsed. If the timeout elapses without a result,
* <tt>null</tt> will be returned. This method does also cancel the PacketCollector.
* Returns the next available stanza. The method in equivalent to
* {@link #nextResultOrThrow(long)} where the timeout argument is the default reply timeout of
* the connection associated with this collector.
*
* @return the next available packet.
* @throws XMPPErrorException in case an error response.
* @return the next available stanza.
* @throws XMPPErrorException in case an error response was received.
* @throws NoResponseException if there was no response from the server.
* @throws InterruptedException
* @throws NotConnectedException
* @throws InterruptedException
* @throws NotConnectedException
* @see #nextResultOrThrow(long)
*/
public <P extends Stanza> P nextResultOrThrow() throws NoResponseException, XMPPErrorException,
InterruptedException, NotConnectedException {
return nextResultOrThrow(connection.getPacketReplyTimeout());
}

/**
* Returns the next available packet. The method call will block until a stanza(/packet) is available or
* the <tt>timeout</tt> has elapsed. This method does also cancel the PacketCollector.
*
* @param timeout the amount of time to wait for the next stanza(/packet) (in milleseconds).
* @return the next available packet.
* Returns the next available stanza. The method call will block until a stanza is
* available or the <tt>timeout</tt> has elapsed. This method does also cancel the
* collector in every case.
* <p>
* Three things can happen when waiting for an response:
* </p>
* <ol>
* <li>A result response arrives.</li>
* <li>An error response arrives.</li>
* <li>An timeout occurs.</li>
* <li>The thread is interrupted</li>
* </ol>
* <p>
* in which this method will
* </p>
* <ol>
* <li>return with the result.</li>
* <li>throw an {@link XMPPErrorException}.</li>
* <li>throw an {@link NoResponseException}.</li>
* <li>throw an {@link InterruptedException}.</li>
* </ol>
* <p>
* Additionally the method will throw a {@link NotConnectedException} if no response was
* received and the connection got disconnected.
* </p>
*
* @param timeout the amount of time to wait for the next stanza in milliseconds.
* @return the next available stanza.
* @throws NoResponseException if there was no response from the server.
* @throws XMPPErrorException in case an error response.
* @throws InterruptedException
* @throws NotConnectedException
* @throws XMPPErrorException in case an error response was received.
* @throws InterruptedException if the calling thread was interrupted.
* @throws NotConnectedException if there was no response and the connection got disconnected.
*/
public <P extends Stanza> P nextResultOrThrow(long timeout) throws NoResponseException,
XMPPErrorException, InterruptedException, NotConnectedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.jivesoftware.smack.SmackException;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
Expand Down Expand Up @@ -85,6 +86,18 @@ public static EntityBareJid getBareJidAttribute(XmlPullParser parser, String nam
return JidCreate.entityBareFrom(jidString);
}

public static EntityFullJid getFullJidAttribute(XmlPullParser parser) throws XmppStringprepException {
return getFullJidAttribute(parser, JID);
}

public static EntityFullJid getFullJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
final String jidString = parser.getAttributeValue("", name);
if (jidString == null) {
return null;
}
return JidCreate.entityFullFrom(jidString);
}

public static Resourcepart getResourcepartAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
final String resourcepartString = parser.getAttributeValue("", name);
if (resourcepartString == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityFullJid;

/**
* A listener that is fired anytime an invitation to join a MUC room is received.
Expand All @@ -39,8 +41,9 @@ public interface InvitationListener {
* @param reason the reason why the inviter sent the invitation.
* @param password the password to use when joining the room.
* @param message the message used by the inviter to send the invitation.
* @param invitation the raw invitation received with the message.
*/
public abstract void invitationReceived(XMPPConnection conn, MultiUserChat room, String inviter, String reason,
String password, Message message);
public abstract void invitationReceived(XMPPConnection conn, MultiUserChat room, EntityFullJid inviter, String reason,
String password, Message message, MUCUser.Invite invitation);

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

package org.jivesoftware.smackx.muc;

import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityBareJid;

/**
* A listener that is fired anytime an invitee declines or rejects an invitation.
*
Expand All @@ -29,7 +33,9 @@ public interface InvitationRejectionListener {
*
* @param invitee the invitee that declined the invitation. (e.g. [email protected]).
* @param reason the reason why the invitee declined the invitation.
* @param message the message used to decline the invitation.
* @param rejection the raw decline found in the message.
*/
public abstract void invitationDeclined(String invitee, String reason);
public abstract void invitationDeclined(EntityBareJid invitee, String reason, Message message, MUCUser.Decline rejection);

}
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,16 @@ public void processPacket(Stanza packet) {
// rejection listeners if the message includes an invitation rejection.
declinesListener = new StanzaListener() {
public void processPacket(Stanza packet) {
Message message = (Message) packet;
// Get the MUC User extension
MUCUser mucUser = MUCUser.from(packet);
MUCUser.Decline rejection = mucUser.getDecline();
// Check if the MUCUser informs that the invitee has declined the invitation
if (mucUser.getDecline() == null) {
if (rejection == null) {
return;
}
// Fire event for invitation rejection listeners
fireInvitationRejectionListeners(mucUser.getDecline().getFrom(), mucUser.getDecline().getReason());
fireInvitationRejectionListeners(message, rejection);
}
};

Expand Down Expand Up @@ -874,7 +876,7 @@ public void destroy(String reason, EntityBareJid alternateJID) throws NoResponse
* @throws NotConnectedException
* @throws InterruptedException
*/
public void invite(String user, String reason) throws NotConnectedException, InterruptedException {
public void invite(EntityBareJid user, String reason) throws NotConnectedException, InterruptedException {
invite(new Message(), user, reason);
}

Expand All @@ -891,15 +893,13 @@ public void invite(String user, String reason) throws NotConnectedException, Int
* @throws NotConnectedException
* @throws InterruptedException
*/
public void invite(Message message, String user, String reason) throws NotConnectedException, InterruptedException {
public void invite(Message message, EntityBareJid user, String reason) throws NotConnectedException, InterruptedException {
// TODO listen for 404 error code when inviter supplies a non-existent JID
message.setTo(room);

// Create the MUCUser packet that will include the invitation
MUCUser mucUser = new MUCUser();
MUCUser.Invite invite = new MUCUser.Invite();
invite.setTo(user);
invite.setReason(reason);
MUCUser.Invite invite = new MUCUser.Invite(reason, user);
mucUser.setInvite(invite);
// Add the MUCUser packet that includes the invitation to the message
message.addExtension(mucUser);
Expand Down Expand Up @@ -935,14 +935,16 @@ public boolean removeInvitationRejectionListener(InvitationRejectionListener lis
* @param invitee the user being invited.
* @param reason the reason for the rejection
*/
private void fireInvitationRejectionListeners(String invitee, String reason) {
private void fireInvitationRejectionListeners(Message message, MUCUser.Decline rejection) {
EntityBareJid invitee = rejection.getFrom();
String reason = rejection.getReason();
InvitationRejectionListener[] listeners;
synchronized (invitationRejectionListeners) {
listeners = new InvitationRejectionListener[invitationRejectionListeners.size()];
invitationRejectionListeners.toArray(listeners);
}
for (InvitationRejectionListener listener : listeners) {
listener.invitationDeclined(invitee, reason);
listener.invitationDeclined(invitee, reason, message, rejection);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright © 2014 Florian Schmaus
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -52,6 +52,7 @@
import org.jivesoftware.smackx.muc.packet.MUCInitialPresence;
import org.jivesoftware.smackx.muc.packet.MUCUser;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.EntityJid;
Expand Down Expand Up @@ -139,9 +140,13 @@ public void processPacket(Stanza packet) {
}
// Fire event for invitation listeners
final MultiUserChat muc = getMultiUserChat(mucJid);
final XMPPConnection connection = connection();
final MUCUser.Invite invite = mucUser.getInvite();
final EntityFullJid from = invite.getFrom();
final String reason = invite.getReason();
final String password = mucUser.getPassword();
for (final InvitationListener listener : invitationsListeners) {
listener.invitationReceived(connection(), muc, mucUser.getInvite().getFrom(),
mucUser.getInvite().getReason(), mucUser.getPassword(), message);
listener.invitationReceived(connection, muc, from, reason, password, message, invite);
}
}
}
Expand Down Expand Up @@ -318,14 +323,12 @@ public List<HostedRoom> getHostedRooms(DomainBareJid serviceName) throws NoRespo
* @throws NotConnectedException
* @throws InterruptedException
*/
public void decline(EntityBareJid room, String inviter, String reason) throws NotConnectedException, InterruptedException {
public void decline(EntityBareJid room, EntityBareJid inviter, String reason) throws NotConnectedException, InterruptedException {
Message message = new Message(room);

// Create the MUCUser packet that will include the rejection
MUCUser mucUser = new MUCUser();
MUCUser.Decline decline = new MUCUser.Decline();
decline.setTo(inviter);
decline.setReason(reason);
MUCUser.Decline decline = new MUCUser.Decline(reason, inviter);
mucUser.setDecline(decline);
// Add the MUCUser packet that includes the rejection
message.addExtension(mucUser);
Expand Down
Loading

0 comments on commit 96c05dc

Please sign in to comment.