1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx.muc; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.ref.WeakReference; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.InvocationTargetException; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.Method; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.ArrayList; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collection; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Iterator; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.WeakHashMap; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.ConcurrentHashMap; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Chat; 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.ConnectionCreationListener; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.ConnectionListener; 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.MessageListener; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketCollector; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketInterceptor; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketListener; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.SmackConfiguration; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection; 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.AndFilter; 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.FromMatchesFilter; 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.MessageTypeFilter; 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketExtensionFilter; 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketFilter; 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketIDFilter; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketTypeFilter; 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ; 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Message; 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.PacketExtension; 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Presence; 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Registration; 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.Form; 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.NodeInformationProvider; 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.ServiceDiscoveryManager; 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.DiscoverInfo; 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.DiscoverItems; 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.MUCAdmin; 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.MUCInitialPresence; 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.MUCOwner; 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.MUCUser; 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A MultiUserChat is a conversation that takes place among many users in a virtual 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * room. A room could have many occupants with different affiliation and roles. 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Possible affiliatons are "owner", "admin", "member", and "outcast". Possible roles 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * are "moderator", "participant", and "visitor". Each role and affiliation guarantees 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * different privileges (e.g. Send messages to all occupants, Kick participants and visitors, 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grant voice, Edit member list, etc.). 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak, Larry Kirschner 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class MultiUserChat { 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final static String discoNamespace = "http://jabber.org/protocol/muc"; 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final static String discoNode = "http://jabber.org/protocol/muc#rooms"; 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static Map<Connection, List<String>> joinedRooms = 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new WeakHashMap<Connection, List<String>>(); 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Connection connection; 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String room; 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String subject; 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String nickname = null; 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean joined = false; 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Map<String, Presence> occupantsMap = new ConcurrentHashMap<String, Presence>(); 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<InvitationRejectionListener> invitationRejectionListeners = 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new ArrayList<InvitationRejectionListener>(); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<SubjectUpdatedListener> subjectUpdatedListeners = 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new ArrayList<SubjectUpdatedListener>(); 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<UserStatusListener> userStatusListeners = 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new ArrayList<UserStatusListener>(); 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<ParticipantStatusListener> participantStatusListeners = 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new ArrayList<ParticipantStatusListener>(); 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PacketFilter presenceFilter; 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private List<PacketInterceptor> presenceInterceptors = new ArrayList<PacketInterceptor>(); 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PacketFilter messageFilter; 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private RoomListenerMultiplexor roomListenerMultiplexor; 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private ConnectionDetachedPacketCollector messageCollector; 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private List<PacketListener> connectionListeners = new ArrayList<PacketListener>(); 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen static { 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Connection.addConnectionCreationListener(new ConnectionCreationListener() { 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionCreated(final Connection connection) { 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set on every established connection that this client supports the Multi-User 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Chat protocol. This information will be used when another client tries to 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // discover whether this client supports MUC or not. 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager.getInstanceFor(connection).addFeature(discoNamespace); 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the NodeInformationProvider that will provide information about the 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // joined rooms whenever a disco request is received 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen discoNode, 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new NodeInformationProvider() { 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public List<DiscoverItems.Item> getNodeItems() { 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<DiscoverItems.Item> answer = new ArrayList<DiscoverItems.Item>(); 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator<String> rooms=MultiUserChat.getJoinedRooms(connection); 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (rooms.hasNext()) { 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen answer.add(new DiscoverItems.Item(rooms.next())); 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return answer; 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public List<String> getNodeFeatures() { 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public List<DiscoverInfo.Identity> getNodeIdentities() { 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen @Override 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public List<PacketExtension> getNodePacketExtensions() { 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new multi user chat with the specified connection and room name. Note: no 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * information is sent to or received from the server until you attempt to 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * {@link #join(String) join} the chat room. On some server implementations, 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room will not be created until the first person joins it.<p> 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Most XMPP servers use a sub-domain for the chat service (eg chat.example.com 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * for the XMPP server example.com). You must ensure that the room address you're 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * trying to connect to includes the proper chat sub-domain. 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the XMPP connection. 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param room the name of the room in the form "roomName@service", where 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * "service" is the hostname at which the multi-user chat 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * service is running. Make sure to provide a valid JID. 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public MultiUserChat(Connection connection, String room) { 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.connection = connection; 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.room = room.toLowerCase(); 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns true if the specified user supports the Multi-User Chat protocol. 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the connection to use to perform the service discovery. 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the user to check. A fully qualified xmpp ID, e.g. jdoe@example.com. 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a boolean indicating whether the specified user supports the MUC protocol. 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static boolean isServiceEnabled(Connection connection, String user) { 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo result = 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(user); 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return result.containsFeature(discoNamespace); 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (XMPPException e) { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an Iterator on the rooms where the user has joined using a given connection. 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The Iterator will contain Strings where each String represents a room 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. room@muc.jabber.org). 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the connection used to join the rooms. 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return an Iterator on the rooms where the user has joined using a given connection. 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static Iterator<String> getJoinedRooms(Connection connection) { 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> rooms = joinedRooms.get(connection); 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rooms != null) { 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rooms.iterator(); 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Return an iterator on an empty collection (i.e. the user never joined a room) 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ArrayList<String>().iterator(); 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an Iterator on the rooms where the requested user has joined. The Iterator will 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * contain Strings where each String represents a room (e.g. room@muc.jabber.org). 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the connection to use to perform the service discovery. 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the user to check. A fully qualified xmpp ID, e.g. jdoe@example.com. 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return an Iterator on the rooms where the requested user has joined. 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static Iterator<String> getJoinedRooms(Connection connection, String user) { 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ArrayList<String> answer = new ArrayList<String>(); 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the disco packet to the user 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverItems result = 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(user, discoNode); 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Collect the entityID for each returned item 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<DiscoverItems.Item> items=result.getItems(); items.hasNext();) { 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen answer.add(items.next().getEntityID()); 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return answer.iterator(); 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (XMPPException e) { 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Return an iterator on an empty collection 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new ArrayList<String>().iterator(); 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the discovered information of a given room without actually having to join the room. 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The server will provide information only for rooms that are public. 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the XMPP connection to use for discovering information about the room. 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param room the name of the room in the form "roomName@service" of which we want to discover 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * its information. 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the discovered information of a given room without actually having to join the room. 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while trying to discover information of a room. 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static RoomInfo getRoomInfo(Connection connection, String room) 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(room); 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new RoomInfo(info); 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection with the XMPP addresses of the Multi-User Chat services. 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the XMPP connection to use for discovering Multi-User Chat services. 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection with the XMPP addresses of the Multi-User Chat services. 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while trying to discover MUC services. 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static Collection<String> getServiceNames(Connection connection) throws XMPPException { 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final List<String> answer = new ArrayList<String>(); 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverItems items = discoManager.discoverItems(connection.getServiceName()); 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) { 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverItems.Item item = it.next(); 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo info = discoManager.discoverInfo(item.getEntityID()); 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (info.containsFeature("http://jabber.org/protocol/muc")) { 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen answer.add(item.getEntityID()); 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (XMPPException e) { 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Trouble finding info in some cases. This is a workaround for 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // discovering info on remote servers. 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return answer; 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of HostedRooms where each HostedRoom has the XMPP address of the room 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and the room's name. Once discovered the rooms hosted by a chat service it is possible to 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * discover more detailed room information or join the room. 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the XMPP connection to use for discovering hosted rooms by the MUC service. 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param serviceName the service that is hosting the rooms to discover. 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of HostedRooms. 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while trying to discover the information. 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static Collection<HostedRoom> getHostedRooms(Connection connection, String serviceName) 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<HostedRoom> answer = new ArrayList<HostedRoom>(); 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverItems items = discoManager.discoverItems(serviceName); 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) { 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen answer.add(new HostedRoom(it.next())); 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return answer; 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the name of the room this MultiUserChat object represents. 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the multi user chat room name. 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getRoom() { 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return room; 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates the room according to some default configuration, assign the requesting user 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * as the room owner, and add the owner to the room but not allow anyone else to enter 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room (effectively "locking" the room). The requesting user will join the room 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * under the specified nickname as soon as the room has been created.<p> 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To create an "Instant Room", that means a room with some default configuration that is 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * available for immediate access, the room's owner should send an empty form after creating 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room. {@link #sendConfigurationForm(Form)}<p> 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To create a "Reserved Room", that means a room manually configured by the room creator 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * before anyone is allowed to enter, the room's owner should complete and send a form after 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * creating the room. Once the completed configutation form is sent to the server, the server 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will unlock the room. {@link #sendConfigurationForm(Form)} 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname to use. 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if the room couldn't be created for some reason 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. room already exists; user already joined to an existant room or 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error if the user is not allowed to create the room) 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public synchronized void create(String nickname) throws XMPPException { 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nickname == null || nickname.equals("")) { 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Nickname must not be null or blank."); 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If we've already joined the room, leave it before joining under a new 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // nickname. 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (joined) { 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Creation failed - User already joined the room."); 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We create a room by sending a presence packet to room@service/nick 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // and signal support for MUC. The owner will be automatically logged into the room. 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence joinPresence = new Presence(Presence.Type.available); 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setTo(room + "/" + nickname); 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Indicate the the client supports MUC 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.addExtension(new MUCInitialPresence()); 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke presence interceptors so that extra information can be dynamically added 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketInterceptor packetInterceptor : presenceInterceptors) { 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packetInterceptor.interceptPacket(joinPresence); 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a presence packet back from the server. 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter( 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new FromMatchesFilter(room + "/" + nickname), 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketTypeFilter(Presence.class)); 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send create & join packet. 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(joinPresence); 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence presence = 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (presence == null) { 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (presence.getError() != null) { 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(presence.getError()); 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Whether the room existed before or was created, the user has joined the room 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.nickname = nickname; 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = true; 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasJoined(); 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Look for confirmation of room creation from the server 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = getMUCUserExtension(presence); 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (mucUser != null && mucUser.getStatus() != null) { 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ("201".equals(mucUser.getStatus().getCode())) { 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Room was created and the user has joined the room 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We need to leave the room since it seems that the room already existed 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen leave(); 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("Creation failed - Missing acknowledge of room creation."); 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Joins the chat room using the specified nickname. If already joined 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * using another nickname, this method will first leave the room and then 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * re-join using the new nickname. The default timeout of Smack for a reply 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * from the group chat server that the join succeeded will be used. After 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * joining the room, the room will decide the amount of history to send. 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname to use. 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs joining the room. In particular, a 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 401 error can occur if no password was provided and one is required; or a 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the user is banned; or a 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 404 error can occur if the room does not exist or is locked; or a 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 407 error can occur if user is not on the member list; or a 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 409 error can occur if someone is already in the group chat with the same nickname. 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void join(String nickname) throws XMPPException { 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen join(nickname, null, null, SmackConfiguration.getPacketReplyTimeout()); 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Joins the chat room using the specified nickname and password. If already joined 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * using another nickname, this method will first leave the room and then 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * re-join using the new nickname. The default timeout of Smack for a reply 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * from the group chat server that the join succeeded will be used. After 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * joining the room, the room will decide the amount of history to send.<p> 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A password is required when joining password protected rooms. If the room does 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * not require a password there is no need to provide one. 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname to use. 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param password the password to use. 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs joining the room. In particular, a 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 401 error can occur if no password was provided and one is required; or a 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the user is banned; or a 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 404 error can occur if the room does not exist or is locked; or a 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 407 error can occur if user is not on the member list; or a 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 409 error can occur if someone is already in the group chat with the same nickname. 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void join(String nickname, String password) throws XMPPException { 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen join(nickname, password, null, SmackConfiguration.getPacketReplyTimeout()); 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Joins the chat room using the specified nickname and password. If already joined 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * using another nickname, this method will first leave the room and then 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * re-join using the new nickname.<p> 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To control the amount of history to receive while joining a room you will need to provide 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a configured DiscussionHistory object.<p> 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A password is required when joining password protected rooms. If the room does 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * not require a password there is no need to provide one.<p> 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the room does not already exist when the user seeks to enter it, the server will 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * decide to create a new room or not. 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname to use. 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param password the password to use. 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param history the amount of discussion history to receive while joining a room. 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param timeout the amount of time to wait for a reply from the MUC service(in milleseconds). 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs joining the room. In particular, a 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 401 error can occur if no password was provided and one is required; or a 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the user is banned; or a 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 404 error can occur if the room does not exist or is locked; or a 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 407 error can occur if user is not on the member list; or a 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 409 error can occur if someone is already in the group chat with the same nickname. 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public synchronized void join( 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String nickname, 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String password, 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscussionHistory history, 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long timeout) 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nickname == null || nickname.equals("")) { 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Nickname must not be null or blank."); 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If we've already joined the room, leave it before joining under a new 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // nickname. 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (joined) { 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen leave(); 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We join a room by sending a presence packet where the "to" 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // field is in the form "roomName@service/nickname" 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence joinPresence = new Presence(Presence.Type.available); 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setTo(room + "/" + nickname); 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Indicate the the client supports MUC 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCInitialPresence mucInitialPresence = new MUCInitialPresence(); 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (password != null) { 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucInitialPresence.setPassword(password); 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (history != null) { 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucInitialPresence.setHistory(history.getMUCHistory()); 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.addExtension(mucInitialPresence); 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke presence interceptors so that extra information can be dynamically added 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketInterceptor packetInterceptor : presenceInterceptors) { 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packetInterceptor.interceptPacket(joinPresence); 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a presence packet back from the server. 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter( 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new FromMatchesFilter(room + "/" + nickname), 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketTypeFilter(Presence.class)); 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = null; 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence presence; 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response = connection.createPacketCollector(responseFilter); 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send join packet. 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(joinPresence); 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen presence = (Presence) response.nextResult(timeout); 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen finally { 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (response != null) { 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (presence == null) { 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (presence.getError() != null) { 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(presence.getError()); 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.nickname = nickname; 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = true; 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasJoined(); 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns true if currently in the multi user chat (after calling the {@link 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * #join(String)} method). 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if currently in the multi user chat room. 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isJoined() { 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return joined; 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Leave the chat room. 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public synchronized void leave() { 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If not joined already, do nothing. 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!joined) { 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We leave a room by sending a presence packet where the "to" 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // field is in the form "roomName@service/nickname" 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence leavePresence = new Presence(Presence.Type.unavailable); 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen leavePresence.setTo(room + "/" + nickname); 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke presence interceptors so that extra information can be dynamically added 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketInterceptor packetInterceptor : presenceInterceptors) { 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packetInterceptor.interceptPacket(leavePresence); 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(leavePresence); 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset occupant information. 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.clear(); 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nickname = null; 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = false; 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasLeft(); 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the room's configuration form that the room's owner can use or <tt>null</tt> if 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * no configuration is possible. The configuration form allows to set the room's language, 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * enable logging, specify room's type, etc.. 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the Form that contains the fields to complete together with the instrucions or 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tt>null</tt> if no configuration is possible. 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs asking the configuration form for the room. 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Form getConfigurationForm() throws XMPPException { 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.GET); 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Filter packets looking for an answer from the server. 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Request the configuration form to the server. 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Form.getFormFrom(answer); 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends the completed configuration form to the server. The room will be configured 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * with the new settings defined in the form. If the form is empty then the server 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will create an instant room (will use default configuration). 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param form the form with the new settings. 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs setting the new rooms' configuration. 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void sendConfigurationForm(Form form) throws XMPPException { 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addExtension(form.getDataFormToSend()); 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Filter packets looking for an answer from the server. 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the completed configuration form to the server. 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the room's registration form that an unaffiliated user, can use to become a member 615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of the room or <tt>null</tt> if no registration is possible. Some rooms may restrict the 616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privilege to register members and allow only room admins to add new members.<p> 617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the user requesting registration requirements is not allowed to register with the room 619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. because that privilege has been restricted), the room will return a "Not Allowed" 620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * error to the user (error code 405). 621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the registration Form that contains the fields to complete together with the 623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * instrucions or <tt>null</tt> if no registration is possible. 624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs asking the registration form for the room or a 625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error if the user is not allowed to register with the room. 626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Form getRegistrationForm() throws XMPPException { 628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Registration reg = new Registration(); 629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reg.setType(IQ.Type.GET); 630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reg.setTo(room); 631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter filter = 633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); 634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector collector = connection.createPacketCollector(filter); 635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(reg); 636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collector.cancel(); 638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (result == null) { 639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (result.getType() == IQ.Type.ERROR) { 642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(result.getError()); 643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Form.getFormFrom(result); 645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends the completed registration form to the server. After the user successfully submits 649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the form, the room may queue the request for review by the room admins or may immediately 650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * add the user to the member list by changing the user's affiliation from "none" to "member.<p> 651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the desired room nickname is already reserved for that room, the room will return a 653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * "Conflict" error to the user (error code 409). If the room does not support registration, 654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * it will return a "Service Unavailable" error to the user (error code 503). 655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param form the completed registration form. 657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs submitting the registration form. In particular, a 658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 409 error can occur if the desired room nickname is already reserved for that room; 659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or a 503 error can occur if the room does not support registration. 660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void sendRegistrationForm(Form form) throws XMPPException { 662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Registration reg = new Registration(); 663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reg.setType(IQ.Type.SET); 664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reg.setTo(room); 665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reg.addExtension(form.getDataFormToSend()); 666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter filter = 668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter(new PacketIDFilter(reg.getPacketID()), new PacketTypeFilter(IQ.class)); 669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector collector = connection.createPacketCollector(filter); 670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(reg); 671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); 672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collector.cancel(); 673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (result == null) { 674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (result.getType() == IQ.Type.ERROR) { 677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(result.getError()); 678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends a request to the server to destroy the room. The sender of the request 683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * should be the room's owner. If the sender of the destroy request is not the room's owner 684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * then the server will answer a "Forbidden" error (403). 685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason for the room destruction. 687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param alternateJID the JID of an alternate location. 688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs while trying to destroy the room. 689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An error can occur which will be wrapped by an XMPPException -- 690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * XMPP error code 403. The error code can be used to present more 691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * appropiate error messages to end-users. 692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void destroy(String reason, String alternateJID) throws XMPPException { 694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create the reason for the room destruction 699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner.Destroy destroy = new MUCOwner.Destroy(); 700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen destroy.setReason(reason); 701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen destroy.setJid(alternateJID); 702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setDestroy(destroy); 703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a presence packet back from the server. 705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the room destruction request. 708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset occupant information. 721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.clear(); 722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nickname = null; 723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = false; 724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasLeft(); 725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Invites another user to the room in which one is an occupant. The invitation 729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will be sent to the room which in turn will forward the invitation to the invitee.<p> 730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the room is password-protected, the invitee will receive a password to use to join 732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room. If the room is members-only, the the invitee may be added to the member list. 733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the user to invite to the room.(e.g. hecate@shakespeare.lit) 735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason why the user is being invited. 736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void invite(String user, String reason) { 738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invite(new Message(), user, reason); 739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Invites another user to the room in which one is an occupant using a given Message. The invitation 743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will be sent to the room which in turn will forward the invitation to the invitee.<p> 744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the room is password-protected, the invitee will receive a password to use to join 746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room. If the room is members-only, the the invitee may be added to the member list. 747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param message the message to use for sending the invitation. 749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the user to invite to the room.(e.g. hecate@shakespeare.lit) 750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason why the user is being invited. 751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void invite(Message message, String user, String reason) { 753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // TODO listen for 404 error code when inviter supplies a non-existent JID 754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen message.setTo(room); 755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create the MUCUser packet that will include the invitation 757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = new MUCUser(); 758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser.Invite invite = new MUCUser.Invite(); 759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invite.setTo(user); 760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invite.setReason(reason); 761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.setInvite(invite); 762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add the MUCUser packet that includes the invitation to the message 763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen message.addExtension(mucUser); 764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(message); 766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Informs the sender of an invitation that the invitee declines the invitation. The rejection 770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will be sent to the room which in turn will forward the rejection to the inviter. 771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param conn the connection to use for sending the rejection. 773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param room the room that sent the original invitation. 774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param inviter the inviter of the declined invitation. 775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason why the invitee is declining the invitation. 776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static void decline(Connection conn, String room, String inviter, String reason) { 778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message message = new Message(room); 779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 780d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create the MUCUser packet that will include the rejection 781d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = new MUCUser(); 782d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser.Decline decline = new MUCUser.Decline(); 783d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen decline.setTo(inviter); 784d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen decline.setReason(reason); 785d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.setDecline(decline); 786d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add the MUCUser packet that includes the rejection 787d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen message.addExtension(mucUser); 788d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 789d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen conn.sendPacket(message); 790d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 791d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 792d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 793d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener to invitation notifications. The listener will be fired anytime 794d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an invitation is received. 795d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 796d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param conn the connection where the listener will be applied. 797d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation listener. 798d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 799d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static void addInvitationListener(Connection conn, InvitationListener listener) { 800d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InvitationsMonitor.getInvitationsMonitor(conn).addInvitationListener(listener); 801d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 802d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 803d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 804d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener to invitation notifications. The listener will be fired anytime 805d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an invitation is received. 806d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 807d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param conn the connection where the listener was applied. 808d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation listener. 809d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 810d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static void removeInvitationListener(Connection conn, InvitationListener listener) { 811d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InvitationsMonitor.getInvitationsMonitor(conn).removeInvitationListener(listener); 812d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 813d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 814d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 815d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener to invitation rejections notifications. The listener will be fired anytime 816d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an invitation is declined. 817d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 818d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation rejection listener. 819d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 820d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addInvitationRejectionListener(InvitationRejectionListener listener) { 821d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationRejectionListeners) { 822d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!invitationRejectionListeners.contains(listener)) { 823d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationRejectionListeners.add(listener); 824d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 825d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 826d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 827d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 828d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 829d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener from invitation rejections notifications. The listener will be fired 830d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * anytime an invitation is declined. 831d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 832d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation rejection listener. 833d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 834d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeInvitationRejectionListener(InvitationRejectionListener listener) { 835d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationRejectionListeners) { 836d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationRejectionListeners.remove(listener); 837d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 838d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 839d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 840d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 841d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires invitation rejection listeners. 842d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 843d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param invitee the user being invited. 844d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason for the rejection 845d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 846d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void fireInvitationRejectionListeners(String invitee, String reason) { 847d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InvitationRejectionListener[] listeners; 848d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationRejectionListeners) { 849d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listeners = new InvitationRejectionListener[invitationRejectionListeners.size()]; 850d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationRejectionListeners.toArray(listeners); 851d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 852d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (InvitationRejectionListener listener : listeners) { 853d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.invitationDeclined(invitee, reason); 854d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 855d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 856d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 857d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 858d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener to subject change notifications. The listener will be fired anytime 859d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room's subject changes. 860d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 861d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a subject updated listener. 862d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 863d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addSubjectUpdatedListener(SubjectUpdatedListener listener) { 864d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (subjectUpdatedListeners) { 865d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!subjectUpdatedListeners.contains(listener)) { 866d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen subjectUpdatedListeners.add(listener); 867d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 868d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 869d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 870d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 871d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 872d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener from subject change notifications. The listener will be fired 873d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * anytime the room's subject changes. 874d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 875d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a subject updated listener. 876d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 877d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeSubjectUpdatedListener(SubjectUpdatedListener listener) { 878d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (subjectUpdatedListeners) { 879d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen subjectUpdatedListeners.remove(listener); 880d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 881d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 882d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 883d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 884d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires subject updated listeners. 885d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 886d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void fireSubjectUpdatedListeners(String subject, String from) { 887d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen SubjectUpdatedListener[] listeners; 888d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (subjectUpdatedListeners) { 889d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listeners = new SubjectUpdatedListener[subjectUpdatedListeners.size()]; 890d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen subjectUpdatedListeners.toArray(listeners); 891d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 892d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (SubjectUpdatedListener listener : listeners) { 893d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.subjectUpdated(subject, from); 894d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 895d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 896d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 897d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 898d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a new {@link PacketInterceptor} that will be invoked every time a new presence 899d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is going to be sent by this MultiUserChat to the server. Packet interceptors may 900d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * add new extensions to the presence that is going to be sent to the MUC service. 901d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 902d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param presenceInterceptor the new packet interceptor that will intercept presence packets. 903d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 904d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addPresenceInterceptor(PacketInterceptor presenceInterceptor) { 905d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen presenceInterceptors.add(presenceInterceptor); 906d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 907d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 908d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 909d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a {@link PacketInterceptor} that was being invoked every time a new presence 910d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was being sent by this MultiUserChat to the server. Packet interceptors may 911d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * add new extensions to the presence that is going to be sent to the MUC service. 912d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 913d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param presenceInterceptor the packet interceptor to remove. 914d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 915d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removePresenceInterceptor(PacketInterceptor presenceInterceptor) { 916d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen presenceInterceptors.remove(presenceInterceptor); 917d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 918d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 919d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 920d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the last known room's subject or <tt>null</tt> if the user hasn't joined the room 921d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or the room does not have a subject yet. In case the room has a subject, as soon as the 922d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * user joins the room a message with the current room's subject will be received.<p> 923d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 924d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To be notified every time the room's subject change you should add a listener 925d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to this room. {@link #addSubjectUpdatedListener(SubjectUpdatedListener)}<p> 926d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 927d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To change the room's subject use {@link #changeSubject(String)}. 928d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 929d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the room's subject or <tt>null</tt> if the user hasn't joined the room or the 930d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * room does not have a subject yet. 931d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 932d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getSubject() { 933d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return subject; 934d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 935d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 936d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 937d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the reserved room nickname for the user in the room. A user may have a reserved 938d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * nickname, for example through explicit room registration or database integration. In such 939d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * cases it may be desirable for the user to discover the reserved nickname before attempting 940d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to enter the room. 941d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 942d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the reserved room nickname or <tt>null</tt> if none. 943d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 944d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getReservedNickname() { 945d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 946d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo result = 947d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo( 948d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen room, 949d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "x-roomuser-item"); 950d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Look for an Identity that holds the reserved nickname and return its name 951d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<DiscoverInfo.Identity> identities = result.getIdentities(); 952d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen identities.hasNext();) { 953d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DiscoverInfo.Identity identity = identities.next(); 954d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return identity.getName(); 955d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 956d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If no Identity was found then the user does not have a reserved room nickname 957d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 958d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 959d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (XMPPException e) { 960d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 961d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 962d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 963d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 964d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 965d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 966d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the nickname that was used to join the room, or <tt>null</tt> if not 967d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * currently joined. 968d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 969d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the nickname currently being used. 970d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 971d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getNickname() { 972d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return nickname; 973d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 974d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 975d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 976d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Changes the occupant's nickname to a new nickname within the room. Each room occupant 977d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will receive two presence packets. One of type "unavailable" for the old nickname and one 978d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * indicating availability for the new nickname. The unavailable presence will contain the new 979d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * nickname and an appropriate status code (namely 303) as extended presence information. The 980d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * status code 303 indicates that the occupant is changing his/her nickname. 981d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 982d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the new nickname within the room. 983d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if the new nickname is already in use by another occupant. 984d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 985d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void changeNickname(String nickname) throws XMPPException { 986d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nickname == null || nickname.equals("")) { 987d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Nickname must not be null or blank."); 988d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 989d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check that we already have joined the room before attempting to change the 990d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // nickname. 991d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!joined) { 992d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("Must be logged into the room to change nickname."); 993d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 994d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We change the nickname by sending a presence packet where the "to" 995d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // field is in the form "roomName@service/nickname" 996d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We don't have to signal the MUC support again 997d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence joinPresence = new Presence(Presence.Type.available); 998d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setTo(room + "/" + nickname); 999d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke presence interceptors so that extra information can be dynamically added 1000d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketInterceptor packetInterceptor : presenceInterceptors) { 1001d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packetInterceptor.interceptPacket(joinPresence); 1002d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1003d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1004d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a presence packet back from the server. 1005d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = 1006d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter( 1007d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new FromMatchesFilter(room + "/" + nickname), 1008d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketTypeFilter(Presence.class)); 1009d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1010d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send join packet. 1011d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(joinPresence); 1012d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1013d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence presence = 1014d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (Presence) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1015d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1016d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1017d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1018d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (presence == null) { 1019d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1020d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1021d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (presence.getError() != null) { 1022d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(presence.getError()); 1023d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1024d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.nickname = nickname; 1025d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1026d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1027d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1028d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Changes the occupant's availability status within the room. The presence type 1029d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will remain available but with a new status that describes the presence update and 1030d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a new presence mode (e.g. Extended away). 1031d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1032d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param status a text message describing the presence update. 1033d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param mode the mode type for the presence update. 1034d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1035d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void changeAvailabilityStatus(String status, Presence.Mode mode) { 1036d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nickname == null || nickname.equals("")) { 1037d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("Nickname must not be null or blank."); 1038d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1039d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check that we already have joined the room before attempting to change the 1040d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // availability status. 1041d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!joined) { 1042d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException( 1043d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "Must be logged into the room to change the " + "availability status."); 1044d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1045d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We change the availability status by sending a presence packet to the room with the 1046d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // new presence status and mode 1047d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence joinPresence = new Presence(Presence.Type.available); 1048d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setStatus(status); 1049d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setMode(mode); 1050d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinPresence.setTo(room + "/" + nickname); 1051d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Invoke presence interceptors so that extra information can be dynamically added 1052d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketInterceptor packetInterceptor : presenceInterceptors) { 1053d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packetInterceptor.interceptPacket(joinPresence); 1054d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1055d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1056d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send join packet. 1057d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(joinPresence); 1058d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1059d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1060d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1061d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Kicks a visitor or participant from the room. The kicked occupant will receive a presence 1062d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of type "unavailable" including a status code 307 and optionally along with the reason 1063d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (if provided) and the bare JID of the user who initiated the kick. After the occupant 1064d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was kicked from the room, the rest of the occupants will receive a presence of type 1065d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * "unavailable". The presence will include a status code 307 which means that the occupant 1066d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was kicked from the room. 1067d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1068d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname of the participant or visitor to kick from the room 1069d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. "john"). 1070d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason why the participant or visitor is being kicked from the room. 1071d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs kicking the occupant. In particular, a 1072d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" 1073d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was intended to be kicked (i.e. Not Allowed error); or a 1074d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the occupant that intended to kick another occupant does 1075d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * not have kicking privileges (i.e. Forbidden error); or a 1076d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 400 error can occur if the provided nickname is not present in the room. 1077d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1078d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void kickParticipant(String nickname, String reason) throws XMPPException { 1079d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nickname, "none", reason); 1080d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1081d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1082d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1083d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants voice to visitors in the room. In a moderated room, a moderator may want to manage 1084d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * who does and does not have "voice" in the room. To have voice means that a room occupant 1085d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is able to send messages to the room occupants. 1086d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1087d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nicknames the nicknames of the visitors to grant voice in the room (e.g. "john"). 1088d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting voice to a visitor. In particular, a 1089d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the occupant that intended to grant voice is not 1090d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a moderator in this room (i.e. Forbidden error); or a 1091d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 400 error can occur if the provided nickname is not present in the room. 1092d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1093d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantVoice(Collection<String> nicknames) throws XMPPException { 1094d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nicknames, "participant"); 1095d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1096d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1097d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1098d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants voice to a visitor in the room. In a moderated room, a moderator may want to manage 1099d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * who does and does not have "voice" in the room. To have voice means that a room occupant 1100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is able to send messages to the room occupants. 1101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname of the visitor to grant voice in the room (e.g. "john"). 1103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting voice to a visitor. In particular, a 1104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 403 error can occur if the occupant that intended to grant voice is not 1105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a moderator in this room (i.e. Forbidden error); or a 1106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 400 error can occur if the provided nickname is not present in the room. 1107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantVoice(String nickname) throws XMPPException { 1109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nickname, "participant", null); 1110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes voice from participants in the room. In a moderated room, a moderator may want to 1114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * revoke an occupant's privileges to speak. To have voice means that a room occupant 1115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is able to send messages to the room occupants. 1116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nicknames the nicknames of the participants to revoke voice (e.g. "john"). 1118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking voice from a participant. In particular, a 1119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" 1120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was tried to revoke his voice (i.e. Not Allowed error); or a 1121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 400 error can occur if the provided nickname is not present in the room. 1122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeVoice(Collection<String> nicknames) throws XMPPException { 1124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nicknames, "visitor"); 1125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes voice from a participant in the room. In a moderated room, a moderator may want to 1129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * revoke an occupant's privileges to speak. To have voice means that a room occupant 1130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is able to send messages to the room occupants. 1131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname of the participant to revoke voice (e.g. "john"). 1133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking voice from a participant. In particular, a 1134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" 1135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was tried to revoke his voice (i.e. Not Allowed error); or a 1136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 400 error can occur if the provided nickname is not present in the room. 1137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeVoice(String nickname) throws XMPPException { 1139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nickname, "visitor", null); 1140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Bans users from the room. An admin or owner of the room can ban users from a room. This 1144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * means that the banned user will no longer be able to join the room unless the ban has been 1145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * removed. If the banned user was present in the room then he/she will be removed from the 1146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * room and notified that he/she was banned along with the reason (if provided) and the bare 1147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * XMPP user ID of the user who initiated the ban. 1148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the bare XMPP user IDs of the users to ban. 1150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs banning a user. In particular, a 1151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" 1152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was tried to be banned (i.e. Not Allowed error). 1153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void banUsers(Collection<String> jids) throws XMPPException { 1155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jids, "outcast"); 1156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Bans a user from the room. An admin or owner of the room can ban users from a room. This 1160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * means that the banned user will no longer be able to join the room unless the ban has been 1161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * removed. If the banned user was present in the room then he/she will be removed from the 1162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * room and notified that he/she was banned along with the reason (if provided) and the bare 1163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * XMPP user ID of the user who initiated the ban. 1164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to ban (e.g. "user@host.org"). 1166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the optional reason why the user was banned. 1167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs banning a user. In particular, a 1168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 405 error can occur if a moderator or a user with an affiliation of "owner" or "admin" 1169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * was tried to be banned (i.e. Not Allowed error). 1170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void banUser(String jid, String reason) throws XMPPException { 1172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jid, "outcast", reason); 1173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants membership to other users. Only administrators are able to grant membership. A user 1177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room 1178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that a user cannot enter without being on the member list). 1179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the XMPP user IDs of the users to grant membership. 1181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting membership to a user. 1182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantMembership(Collection<String> jids) throws XMPPException { 1184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jids, "member"); 1185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants membership to a user. Only administrators are able to grant membership. A user 1189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room 1190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that a user cannot enter without being on the member list). 1191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the XMPP user ID of the user to grant membership (e.g. "user@host.org"). 1193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting membership to a user. 1194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantMembership(String jid) throws XMPPException { 1196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jid, "member", null); 1197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes users' membership. Only administrators are able to revoke membership. A user 1201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room 1202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that a user cannot enter without being on the member list). If the user is in the room and 1203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room is of type members-only then the user will be removed from the room. 1204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the bare XMPP user IDs of the users to revoke membership. 1206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking membership to a user. 1207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeMembership(Collection<String> jids) throws XMPPException { 1209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jids, "none"); 1210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes a user's membership. Only administrators are able to revoke membership. A user 1214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that becomes a room member will be able to enter a room of type Members-Only (i.e. a room 1215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that a user cannot enter without being on the member list). If the user is in the room and 1216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the room is of type members-only then the user will be removed from the room. 1217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to revoke membership (e.g. "user@host.org"). 1219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking membership to a user. 1220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeMembership(String jid) throws XMPPException { 1222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jid, "none", null); 1223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants moderator privileges to participants or visitors. Room administrators may grant 1227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite 1228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * other users, modify room's subject plus all the partcipants privileges. 1229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nicknames the nicknames of the occupants to grant moderator privileges. 1231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting moderator privileges to a user. 1232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantModerator(Collection<String> nicknames) throws XMPPException { 1234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nicknames, "moderator"); 1235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants moderator privileges to a participant or visitor. Room administrators may grant 1239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite 1240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * other users, modify room's subject plus all the partcipants privileges. 1241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname of the occupant to grant moderator privileges. 1243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting moderator privileges to a user. 1244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantModerator(String nickname) throws XMPPException { 1246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nickname, "moderator", null); 1247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes moderator privileges from other users. The occupant that loses moderator 1251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become a participant. Room administrators may revoke moderator privileges 1252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * only to occupants whose affiliation is member or none. This means that an administrator is 1253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * not allowed to revoke moderator privileges from other room administrators or owners. 1254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nicknames the nicknames of the occupants to revoke moderator privileges. 1256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking moderator privileges from a user. 1257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeModerator(Collection<String> nicknames) throws XMPPException { 1259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nicknames, "participant"); 1260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes moderator privileges from another user. The occupant that loses moderator 1264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become a participant. Room administrators may revoke moderator privileges 1265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * only to occupants whose affiliation is member or none. This means that an administrator is 1266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * not allowed to revoke moderator privileges from other room administrators or owners. 1267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param nickname the nickname of the occupant to revoke moderator privileges. 1269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking moderator privileges from a user. 1270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeModerator(String nickname) throws XMPPException { 1272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeRole(nickname, "participant", null); 1273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants ownership privileges to other users. Room owners may grant ownership privileges. 1277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Some room implementations will not allow to grant ownership privileges to other users. 1278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An owner is allowed to change defining room features as well as perform all administrative 1279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * functions. 1280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the collection of bare XMPP user IDs of the users to grant ownership. 1282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting ownership privileges to a user. 1283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantOwnership(Collection<String> jids) throws XMPPException { 1285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jids, "owner"); 1286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants ownership privileges to another user. Room owners may grant ownership privileges. 1290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Some room implementations will not allow to grant ownership privileges to other users. 1291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An owner is allowed to change defining room features as well as perform all administrative 1292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * functions. 1293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to grant ownership (e.g. "user@host.org"). 1295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting ownership privileges to a user. 1296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantOwnership(String jid) throws XMPPException { 1298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jid, "owner", null); 1299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes ownership privileges from other users. The occupant that loses ownership 1303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become an administrator. Room owners may revoke ownership privileges. 1304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Some room implementations will not allow to grant ownership privileges to other users. 1305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the bare XMPP user IDs of the users to revoke ownership. 1307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking ownership privileges from a user. 1308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeOwnership(Collection<String> jids) throws XMPPException { 1310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jids, "admin"); 1311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes ownership privileges from another user. The occupant that loses ownership 1315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become an administrator. Room owners may revoke ownership privileges. 1316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Some room implementations will not allow to grant ownership privileges to other users. 1317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to revoke ownership (e.g. "user@host.org"). 1319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking ownership privileges from a user. 1320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeOwnership(String jid) throws XMPPException { 1322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByAdmin(jid, "admin", null); 1323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants administrator privileges to other users. Room owners may grant administrator 1327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges to a member or unaffiliated user. An administrator is allowed to perform 1328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * administrative functions such as banning users and edit moderator list. 1329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the bare XMPP user IDs of the users to grant administrator privileges. 1331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting administrator privileges to a user. 1332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantAdmin(Collection<String> jids) throws XMPPException { 1334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByOwner(jids, "admin"); 1335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Grants administrator privileges to another user. Room owners may grant administrator 1339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges to a member or unaffiliated user. An administrator is allowed to perform 1340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * administrative functions such as banning users and edit moderator list. 1341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to grant administrator privileges 1343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. "user@host.org"). 1344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs granting administrator privileges to a user. 1345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void grantAdmin(String jid) throws XMPPException { 1347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByOwner(jid, "admin"); 1348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes administrator privileges from users. The occupant that loses administrator 1352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become a member. Room owners may revoke administrator privileges from 1353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a member or unaffiliated user. 1354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jids the bare XMPP user IDs of the user to revoke administrator privileges. 1356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking administrator privileges from a user. 1357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeAdmin(Collection<String> jids) throws XMPPException { 1359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByOwner(jids, "member"); 1360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Revokes administrator privileges from a user. The occupant that loses administrator 1364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * privileges will become a member. Room owners may revoke administrator privileges from 1365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a member or unaffiliated user. 1366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid the bare XMPP user ID of the user to revoke administrator privileges 1368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. "user@host.org"). 1369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occurs revoking administrator privileges from a user. 1370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void revokeAdmin(String jid) throws XMPPException { 1372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen changeAffiliationByOwner(jid, "member"); 1373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeAffiliationByOwner(String jid, String affiliation) throws XMPPException { 1376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 1377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new affiliation. 1380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner.Item item = new MUCOwner.Item(affiliation); 1381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setJid(jid); 1382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeAffiliationByOwner(Collection<String> jids, String affiliation) 1403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 1404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 1405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (String jid : jids) { 1408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new affiliation. 1409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner.Item item = new MUCOwner.Item(affiliation); 1410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setJid(jid); 1411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Tries to change the affiliation with an 'muc#admin' namespace 1434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param jid 1436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param affiliation 1437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param reason the reason for the affiliation change (optional) 1438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException 1439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeAffiliationByAdmin(String jid, String affiliation, String reason) 1441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 1442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new affiliation. 1446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setJid(jid); 1448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if(reason != null) 1449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setReason(reason); 1450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeAffiliationByAdmin(Collection<String> jids, String affiliation) 1471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException { 1472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (String jid : jids) { 1476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new affiliation. 1477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setJid(jid); 1479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeRole(String nickname, String role, String reason) throws XMPPException { 1501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new role. 1505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setNick(nickname); 1507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setReason(reason); 1508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void changeRole(Collection<String> nicknames, String role) throws XMPPException { 1529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.SET); 1532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (String nickname : nicknames) { 1533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the new role. 1534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen item.setNick(nickname); 1536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the change request to the server. 1543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the number of occupants in the group chat.<p> 1559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Note: this value will only be accurate after joining the group chat, and 1561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * may fluctuate over time. If you query this value directly after joining the 1562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * group chat it may not be accurate, as it takes a certain amount of time for 1563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the server to send all presence packets to this client. 1564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the number of occupants in the group chat. 1566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public int getOccupantsCount() { 1568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return occupantsMap.size(); 1569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an Iterator (of Strings) for the list of fully qualified occupants 1573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the group chat. For example, "conference@chat.jivesoftware.com/SomeUser". 1574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Typically, a client would only display the nickname of the occupant. To 1575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * get the nickname from the fully qualified name, use the 1576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * {@link org.jivesoftware.smack.util.StringUtils#parseResource(String)} method. 1577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Note: this value will only be accurate after joining the group chat, and may 1578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * fluctuate over time. 1579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return an Iterator for the occupants in the group chat. 1581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Iterator<String> getOccupants() { 1583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return Collections.unmodifiableList(new ArrayList<String>(occupantsMap.keySet())) 1584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .iterator(); 1585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the presence info for a particular user, or <tt>null</tt> if the user 1589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is not in the room.<p> 1590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the room occupant to search for his presence. The format of user must 1592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). 1593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the occupant's current presence, or <tt>null</tt> if the user is unavailable 1594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or if no presence information is available. 1595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Presence getOccupantPresence(String user) { 1597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return occupantsMap.get(user); 1598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the Occupant information for a particular occupant, or <tt>null</tt> if the 1602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * user is not in the room. The Occupant object may include information such as full 1603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * JID of the user as well as the role and affiliation of the user in the room.<p> 1604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param user the room occupant to search for his presence. The format of user must 1606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). 1607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the Occupant or <tt>null</tt> if the user is unavailable (i.e. not in the room). 1608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Occupant getOccupant(String user) { 1610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence presence = occupantsMap.get(user); 1611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (presence != null) { 1612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new Occupant(presence); 1613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 1615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a packet listener that will be notified of any new Presence packets 1619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sent to the group chat. Using a listener is a suitable way to know when the list 1620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of occupants should be re-loaded due to any changes. 1621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a packet listener that will be notified of any presence packets 1623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sent to the group chat. 1624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addParticipantListener(PacketListener listener) { 1626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.addPacketListener(listener, presenceFilter); 1627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connectionListeners.add(listener); 1628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Remoces a packet listener that was being notified of any new Presence packets 1632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sent to the group chat. 1633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a packet listener that was being notified of any presence packets 1635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sent to the group chat. 1636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeParticipantListener(PacketListener listener) { 1638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.removePacketListener(listener); 1639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connectionListeners.remove(listener); 1640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> with the room owners. 1644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> with the room owners. 1646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Affiliate> getOwners() throws XMPPException { 1650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getAffiliatesByAdmin("owner"); 1651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> with the room administrators. 1655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> with the room administrators. 1657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Affiliate> getAdmins() throws XMPPException { 1661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getAffiliatesByOwner("admin"); 1662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> with the room members. 1666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> with the room members. 1668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Affiliate> getMembers() throws XMPPException { 1672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getAffiliatesByAdmin("member"); 1673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> with the room outcasts. 1677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> with the room outcasts. 1679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Affiliate> getOutcasts() throws XMPPException { 1683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getAffiliatesByAdmin("outcast"); 1684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> that have the specified room affiliation 1688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sending a request in the owner namespace. 1689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param affiliation the affiliation of the users in the room. 1691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> that have the specified room affiliation. 1692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Collection<Affiliate> getAffiliatesByOwner(String affiliation) throws XMPPException { 1696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner iq = new MUCOwner(); 1697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.GET); 1699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the specified affiliation. This may request the list of owners/admins/members/outcasts. 1700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner.Item item = new MUCOwner.Item(affiliation); 1701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the request to the server. 1707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCOwner answer = (MUCOwner) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the list of affiliates from the server's answer 1720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<Affiliate> affiliates = new ArrayList<Affiliate>(); 1721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<MUCOwner.Item> it = answer.getItems(); it.hasNext();) { 1722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen affiliates.add(new Affiliate(it.next())); 1723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return affiliates; 1725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Affiliate</code> that have the specified room affiliation 1729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sending a request in the admin namespace. 1730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param affiliation the affiliation of the users in the room. 1732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Affiliate</code> that have the specified room affiliation. 1733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Collection<Affiliate> getAffiliatesByAdmin(String affiliation) throws XMPPException { 1737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.GET); 1740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the specified affiliation. This may request the list of owners/admins/members/outcasts. 1741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(affiliation, null); 1742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the request to the server. 1748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the list of affiliates from the server's answer 1761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<Affiliate> affiliates = new ArrayList<Affiliate>(); 1762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<MUCAdmin.Item> it = answer.getItems(); it.hasNext();) { 1763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen affiliates.add(new Affiliate(it.next())); 1764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return affiliates; 1766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Occupant</code> with the room moderators. 1770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Occupant</code> with the room moderators. 1772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Occupant> getModerators() throws XMPPException { 1776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getOccupants("moderator"); 1777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1780d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Occupant</code> with the room participants. 1781d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1782d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Occupant</code> with the room participants. 1783d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1784d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1785d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1786d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Collection<Occupant> getParticipants() throws XMPPException { 1787d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return getOccupants("participant"); 1788d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1789d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1790d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1791d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a collection of <code>Occupant</code> that have the specified room role. 1792d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1793d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param role the role of the occupant in the room. 1794d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a collection of <code>Occupant</code> that have the specified room role. 1795d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if an error occured while performing the request to the server or you 1796d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * don't have enough privileges to get this information. 1797d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1798d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Collection<Occupant> getOccupants(String role) throws XMPPException { 1799d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin iq = new MUCAdmin(); 1800d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setTo(room); 1801d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setType(IQ.Type.GET); 1802d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Set the specified role. This may request the list of moderators/participants. 1803d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin.Item item = new MUCAdmin.Item(null, role); 1804d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.addItem(item); 1805d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1806d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for a response packet back from the server. 1807d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = new PacketIDFilter(iq.getPacketID()); 1808d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1809d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send the request to the server. 1810d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(iq); 1811d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1812d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCAdmin answer = (MUCAdmin) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1813d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1814d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1815d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1816d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1817d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1818d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1819d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1820d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1821d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1822d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the list of participants from the server's answer 1823d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<Occupant> participants = new ArrayList<Occupant>(); 1824d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (Iterator<MUCAdmin.Item> it = answer.getItems(); it.hasNext();) { 1825d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen participants.add(new Occupant(it.next())); 1826d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1827d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return participants; 1828d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1829d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1830d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1831d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends a message to the chat room. 1832d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1833d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param text the text of the message to send. 1834d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if sending the message fails. 1835d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1836d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void sendMessage(String text) throws XMPPException { 1837d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message message = new Message(room, Message.Type.groupchat); 1838d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen message.setBody(text); 1839d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(message); 1840d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1841d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1842d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1843d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a new Chat for sending private messages to a given room occupant. 1844d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The Chat's occupant address is the room's JID (i.e. roomName@service/nick). The server 1845d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * service will change the 'from' address to the sender's room JID and delivering the message 1846d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to the intended recipient's full JID. 1847d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1848d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param occupant occupant unique room JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). 1849d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener the listener is a message listener that will handle messages for the newly 1850d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * created chat. 1851d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return new Chat for sending private messages to a given room occupant. 1852d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1853d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Chat createPrivateChat(String occupant, MessageListener listener) { 1854d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return connection.getChatManager().createChat(occupant, listener); 1855d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1856d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1857d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1858d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Message to send to the chat room. 1859d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1860d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a new Message addressed to the chat room. 1861d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1862d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Message createMessage() { 1863d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new Message(room, Message.Type.groupchat); 1864d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1865d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1866d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1867d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends a Message to the chat room. 1868d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1869d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param message the message. 1870d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if sending the message fails. 1871d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1872d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void sendMessage(Message message) throws XMPPException { 1873d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(message); 1874d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1875d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1876d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1877d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Polls for and returns the next message, or <tt>null</tt> if there isn't 1878d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a message immediately available. This method provides significantly different 1879d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * functionalty than the {@link #nextMessage()} method since it's non-blocking. 1880d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * In other words, the method call will always return immediately, whereas the 1881d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * nextMessage method will return only when a message is available (or after 1882d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a specific timeout). 1883d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1884d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the next message if one is immediately available and 1885d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tt>null</tt> otherwise. 1886d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1887d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Message pollMessage() { 1888d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Message) messageCollector.pollResult(); 1889d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1890d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1891d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1892d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the next available message in the chat. The method call will block 1893d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (not return) until a message is available. 1894d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1895d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the next message. 1896d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1897d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Message nextMessage() { 1898d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Message) messageCollector.nextResult(); 1899d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1900d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1901d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1902d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the next available message in the chat. The method call will block 1903d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (not return) until a packet is available or the <tt>timeout</tt> has elapased. 1904d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If the timeout elapses without a result, <tt>null</tt> will be returned. 1905d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1906d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param timeout the maximum amount of time to wait for the next message. 1907d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the next message, or <tt>null</tt> if the timeout elapses without a 1908d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * message becoming available. 1909d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1910d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Message nextMessage(long timeout) { 1911d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Message) messageCollector.nextResult(timeout); 1912d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1913d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1914d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1915d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a packet listener that will be notified of any new messages in the 1916d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * group chat. Only "group chat" messages addressed to this group chat will 1917d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be delivered to the listener. If you wish to listen for other packets 1918d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that may be associated with this group chat, you should register a 1919d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * PacketListener directly with the Connection with the appropriate 1920d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * PacketListener. 1921d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1922d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a packet listener. 1923d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1924d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addMessageListener(PacketListener listener) { 1925d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.addPacketListener(listener, messageFilter); 1926d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connectionListeners.add(listener); 1927d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1928d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1929d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1930d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a packet listener that was being notified of any new messages in the 1931d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * multi user chat. Only "group chat" messages addressed to this multi user chat were 1932d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * being delivered to the listener. 1933d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1934d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a packet listener. 1935d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1936d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeMessageListener(PacketListener listener) { 1937d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.removePacketListener(listener); 1938d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connectionListeners.remove(listener); 1939d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1940d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1941d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1942d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Changes the subject within the room. As a default, only users with a role of "moderator" 1943d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * are allowed to change the subject in a room. Although some rooms may be configured to 1944d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * allow a mere participant or even a visitor to change the subject. 1945d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 1946d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param subject the new room's subject to set. 1947d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException if someone without appropriate privileges attempts to change the 1948d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * room subject will throw an error with code 403 (i.e. Forbidden) 1949d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1950d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void changeSubject(final String subject) throws XMPPException { 1951d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message message = new Message(room, Message.Type.groupchat); 1952d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen message.setSubject(subject); 1953d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait for an error or confirmation message back from the server. 1954d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketFilter responseFilter = 1955d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter( 1956d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new FromMatchesFilter(room), 1957d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketTypeFilter(Message.class)); 1958d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen responseFilter = new AndFilter(responseFilter, new PacketFilter() { 1959d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean accept(Packet packet) { 1960d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message msg = (Message) packet; 1961d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return subject.equals(msg.getSubject()); 1962d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1963d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 1964d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector response = connection.createPacketCollector(responseFilter); 1965d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Send change subject packet. 1966d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(message); 1967d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Wait up to a certain number of seconds for a reply. 1968d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message answer = 1969d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (Message) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); 1970d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Stop queuing results 1971d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.cancel(); 1972d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1973d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (answer == null) { 1974d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from server."); 1975d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1976d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (answer.getError() != null) { 1977d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException(answer.getError()); 1978d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1979d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1980d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1981d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1982d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Notification message that the user has joined the room. 1983d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1984d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private synchronized void userHasJoined() { 1985d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update the list of joined rooms through this connection 1986d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> rooms = joinedRooms.get(connection); 1987d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rooms == null) { 1988d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rooms = new ArrayList<String>(); 1989d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joinedRooms.put(connection, rooms); 1990d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1991d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rooms.add(room); 1992d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 1993d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 1994d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 1995d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Notification message that the user has left the room. 1996d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 1997d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private synchronized void userHasLeft() { 1998d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update the list of joined rooms through this connection 1999d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> rooms = joinedRooms.get(connection); 2000d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rooms == null) { 2001d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 2002d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2003d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rooms.remove(room); 2004d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cleanup(); 2005d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2006d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2007d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2008d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the MUCUser packet extension included in the packet or <tt>null</tt> if none. 2009d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2010d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param packet the packet that may include the MUCUser extension. 2011d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return the MUCUser found in the packet. 2012d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2013d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private MUCUser getMUCUserExtension(Packet packet) { 2014d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (packet != null) { 2015d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the MUC User extension 2016d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (MUCUser) packet.getExtension("x", "http://jabber.org/protocol/muc#user"); 2017d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2018d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 2019d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2020d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2021d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2022d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener that will be notified of changes in your status in the room 2023d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * such as the user being kicked, banned, or granted admin permissions. 2024d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2025d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a user status listener. 2026d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2027d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addUserStatusListener(UserStatusListener listener) { 2028d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (userStatusListeners) { 2029d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!userStatusListeners.contains(listener)) { 2030d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userStatusListeners.add(listener); 2031d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2032d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2033d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2034d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2035d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2036d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener that was being notified of changes in your status in the room 2037d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * such as the user being kicked, banned, or granted admin permissions. 2038d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2039d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a user status listener. 2040d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2041d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeUserStatusListener(UserStatusListener listener) { 2042d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (userStatusListeners) { 2043d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userStatusListeners.remove(listener); 2044d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2045d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2046d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2047d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void fireUserStatusListeners(String methodName, Object[] params) { 2048d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen UserStatusListener[] listeners; 2049d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (userStatusListeners) { 2050d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listeners = new UserStatusListener[userStatusListeners.size()]; 2051d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userStatusListeners.toArray(listeners); 2052d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2053d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the classes of the method parameters 2054d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Class<?>[] paramClasses = new Class[params.length]; 2055d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < params.length; i++) { 2056d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen paramClasses[i] = params[i].getClass(); 2057d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2058d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 2059d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the method to execute based on the requested methodName and parameters classes 2060d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Method method = UserStatusListener.class.getDeclaredMethod(methodName, paramClasses); 2061d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (UserStatusListener listener : listeners) { 2062d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen method.invoke(listener, params); 2063d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2064d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (NoSuchMethodException e) { 2065d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2066d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (InvocationTargetException e) { 2067d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2068d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (IllegalAccessException e) { 2069d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2070d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2071d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2072d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2073d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2074d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener that will be notified of changes in occupants status in the room 2075d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * such as the user being kicked, banned, or granted admin permissions. 2076d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2077d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a participant status listener. 2078d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2079d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addParticipantStatusListener(ParticipantStatusListener listener) { 2080d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (participantStatusListeners) { 2081d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!participantStatusListeners.contains(listener)) { 2082d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen participantStatusListeners.add(listener); 2083d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2084d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2085d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2086d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2087d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2088d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener that was being notified of changes in occupants status in the room 2089d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * such as the user being kicked, banned, or granted admin permissions. 2090d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2091d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener a participant status listener. 2092d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2093d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeParticipantStatusListener(ParticipantStatusListener listener) { 2094d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (participantStatusListeners) { 2095d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen participantStatusListeners.remove(listener); 2096d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2097d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2098d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2099d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void fireParticipantStatusListeners(String methodName, List<String> params) { 2100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ParticipantStatusListener[] listeners; 2101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (participantStatusListeners) { 2102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listeners = new ParticipantStatusListener[participantStatusListeners.size()]; 2103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen participantStatusListeners.toArray(listeners); 2104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 2106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the method to execute based on the requested methodName and parameter 2107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Class<?>[] classes = new Class[params.size()]; 2108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i=0;i<params.size(); i++) { 2109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen classes[i] = String.class; 2110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Method method = ParticipantStatusListener.class.getDeclaredMethod(methodName, classes); 2112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (ParticipantStatusListener listener : listeners) { 2113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen method.invoke(listener, params.toArray()); 2114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (NoSuchMethodException e) { 2116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (InvocationTargetException e) { 2118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (IllegalAccessException e) { 2120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 2121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void init() { 2125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create filters 2126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen messageFilter = 2127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter( 2128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new FromMatchesFilter(room), 2129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new MessageTypeFilter(Message.Type.groupchat)); 2130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen messageFilter = new AndFilter(messageFilter, new PacketFilter() { 2131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean accept(Packet packet) { 2132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message msg = (Message) packet; 2133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return msg.getBody() != null; 2134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }); 2136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen presenceFilter = 2137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new AndFilter(new FromMatchesFilter(room), new PacketTypeFilter(Presence.class)); 2138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a collector for incoming messages. 2140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen messageCollector = new ConnectionDetachedPacketCollector(); 2141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a listener for subject updates. 2143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketListener subjectListener = new PacketListener() { 2144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void processPacket(Packet packet) { 2145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message msg = (Message) packet; 2146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Update the room subject 2147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen subject = msg.getSubject(); 2148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire event for subject updated listeners 2149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireSubjectUpdatedListeners( 2150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen msg.getSubject(), 2151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen msg.getFrom()); 2152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 2155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a listener for all presence updates. 2157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketListener presenceListener = new PacketListener() { 2158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void processPacket(Packet packet) { 2159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence presence = (Presence) packet; 2160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String from = presence.getFrom(); 2161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String myRoomJID = room + "/" + nickname; 2162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isUserStatusModification = presence.getFrom().equals(myRoomJID); 2163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (presence.getType() == Presence.Type.available) { 2164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Presence oldPresence = occupantsMap.put(from, presence); 2165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (oldPresence != null) { 2166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the previous occupant's affiliation & role 2167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucExtension = getMUCUserExtension(oldPresence); 2168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String oldAffiliation = mucExtension.getItem().getAffiliation(); 2169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String oldRole = mucExtension.getItem().getRole(); 2170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the new occupant's affiliation & role 2171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucExtension = getMUCUserExtension(presence); 2172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String newAffiliation = mucExtension.getItem().getAffiliation(); 2173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String newRole = mucExtension.getItem().getRole(); 2174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire role modification events 2175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkRoleModifications(oldRole, newRole, isUserStatusModification, from); 2176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire affiliation modification events 2177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkAffiliationModifications( 2178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen oldAffiliation, 2179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newAffiliation, 2180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen isUserStatusModification, 2181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen from); 2182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // A new occupant has joined the room 2185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isUserStatusModification) { 2186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("joined", params); 2189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (presence.getType() == Presence.Type.unavailable) { 2193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.remove(from); 2194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = getMUCUserExtension(presence); 2195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (mucUser != null && mucUser.getStatus() != null) { 2196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire events according to the received presence code 2197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen checkPresenceCode( 2198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.getStatus().getCode(), 2199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen presence.getFrom().equals(myRoomJID), 2200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser, 2201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen from); 2202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 2203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // An occupant has left the room 2204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!isUserStatusModification) { 2205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("left", params); 2208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 2213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Listens for all messages that include a MUCUser extension and fire the invitation 2215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // rejection listeners if the message includes an invitation rejection. 2216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketListener declinesListener = new PacketListener() { 2217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void processPacket(Packet packet) { 2218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the MUC User extension 2219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = getMUCUserExtension(packet); 2220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if the MUCUser informs that the invitee has declined the invitation 2221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (mucUser.getDecline() != null && 2222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Message) packet).getType() != Message.Type.error) { 2223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire event for invitation rejection listeners 2224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireInvitationRejectionListeners( 2225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.getDecline().getFrom(), 2226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.getDecline().getReason()); 2227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 2230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketMultiplexListener packetMultiplexor = new PacketMultiplexListener( 2232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen messageCollector, presenceListener, subjectListener, 2233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen declinesListener); 2234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roomListenerMultiplexor = RoomListenerMultiplexor.getRoomMultiplexor(connection); 2236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roomListenerMultiplexor.addRoom(room, packetMultiplexor); 2238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires notification events if the role of a room occupant has changed. If the occupant that 2242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * changed his role is your occupant then the <code>UserStatusListeners</code> added to this 2243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>MultiUserChat</code> will be fired. On the other hand, if the occupant that changed 2244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * his role is not yours then the <code>ParticipantStatusListeners</code> added to this 2245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>MultiUserChat</code> will be fired. The following table shows the events that will 2246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be fired depending on the previous and new role of the occupant. 2247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <pre> 2249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <table border="1"> 2250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr> 2251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Visitor</td><td>--</td></tr> 2253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Visitor</td><td>Participant</td><td>voiceGranted</td></tr> 2254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Participant</td><td>Moderator</td><td>moderatorGranted</td></tr> 2255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Participant</td><td>voiceGranted</td></tr> 2257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr> 2258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Visitor</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr> 2259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Moderator</td><td>Participant</td><td>moderatorRevoked</td></tr> 2261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Participant</td><td>Visitor</td><td>voiceRevoked</td></tr> 2262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Visitor</td><td>None</td><td>kicked</td></tr> 2263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Moderator</td><td>Visitor</td><td>voiceRevoked + moderatorRevoked</td></tr> 2265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Moderator</td><td>None</td><td>kicked</td></tr> 2266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Participant</td><td>None</td><td>kicked</td></tr> 2267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </table> 2268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </pre> 2269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param oldRole the previous role of the user in the room before receiving the new presence 2271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param newRole the new role of the user in the room after receiving the new presence 2272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param isUserModification whether the received presence is about your user in the room or not 2273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param from the occupant whose role in the room has changed 2274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. room@conference.jabber.org/nick). 2275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void checkRoleModifications( 2277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String oldRole, 2278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String newRole, 2279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isUserModification, 2280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String from) { 2281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Voice was granted to a visitor 2282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (("visitor".equals(oldRole) || "none".equals(oldRole)) 2283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen && "participant".equals(newRole)) { 2284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("voiceGranted", new Object[] {}); 2286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("voiceGranted", params); 2291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The participant's voice was revoked from the room 2294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ( 2295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "participant".equals(oldRole) 2296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen && ("visitor".equals(newRole) || "none".equals(newRole))) { 2297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("voiceRevoked", new Object[] {}); 2299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("voiceRevoked", params); 2304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Moderator privileges were granted to a participant 2307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!"moderator".equals(oldRole) && "moderator".equals(newRole)) { 2308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ("visitor".equals(oldRole) || "none".equals(oldRole)) { 2309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("voiceGranted", new Object[] {}); 2311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("voiceGranted", params); 2316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("moderatorGranted", new Object[] {}); 2320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("moderatorGranted", params); 2325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Moderator privileges were revoked from a participant 2328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("moderator".equals(oldRole) && !"moderator".equals(newRole)) { 2329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ("visitor".equals(newRole) || "none".equals(newRole)) { 2330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("voiceRevoked", new Object[] {}); 2332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("voiceRevoked", params); 2337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("moderatorRevoked", new Object[] {}); 2341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("moderatorRevoked", params); 2346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires notification events if the affiliation of a room occupant has changed. If the 2352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * occupant that changed his affiliation is your occupant then the 2353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>UserStatusListeners</code> added to this <code>MultiUserChat</code> will be fired. 2354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * On the other hand, if the occupant that changed his affiliation is not yours then the 2355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <code>ParticipantStatusListeners</code> added to this <code>MultiUserChat</code> will be 2356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * fired. The following table shows the events that will be fired depending on the previous 2357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and new affiliation of the occupant. 2358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <pre> 2360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <table border="1"> 2361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr> 2362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Member</td><td>membershipGranted</td></tr> 2364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Member</td><td>Admin</td><td>membershipRevoked + adminGranted</td></tr> 2365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Admin</td><td>Owner</td><td>adminRevoked + ownershipGranted</td></tr> 2366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Admin</td><td>adminGranted</td></tr> 2368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>None</td><td>Owner</td><td>ownershipGranted</td></tr> 2369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Member</td><td>Owner</td><td>membershipRevoked + ownershipGranted</td></tr> 2370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Owner</td><td>Admin</td><td>ownershipRevoked + adminGranted</td></tr> 2372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Admin</td><td>Member</td><td>adminRevoked + membershipGranted</td></tr> 2373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Member</td><td>None</td><td>membershipRevoked</td></tr> 2374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Owner</td><td>Member</td><td>ownershipRevoked + membershipGranted</td></tr> 2376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Owner</td><td>None</td><td>ownershipRevoked</td></tr> 2377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td>Admin</td><td>None</td><td>adminRevoked</td></tr> 2378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <tr><td><i>Anyone</i></td><td>Outcast</td><td>banned</td></tr> 2379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </table> 2380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </pre> 2381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param oldAffiliation the previous affiliation of the user in the room before receiving the 2383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * new presence 2384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param newAffiliation the new affiliation of the user in the room after receiving the new 2385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * presence 2386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param isUserModification whether the received presence is about your user in the room or not 2387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param from the occupant whose role in the room has changed 2388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (e.g. room@conference.jabber.org/nick). 2389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void checkAffiliationModifications( 2391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String oldAffiliation, 2392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String newAffiliation, 2393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isUserModification, 2394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String from) { 2395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // First check for revoked affiliation and then for granted affiliations. The idea is to 2396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // first fire the "revoke" events and then fire the "grant" events. 2397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user's ownership to the room was revoked 2399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ("owner".equals(oldAffiliation) && !"owner".equals(newAffiliation)) { 2400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("ownershipRevoked", new Object[] {}); 2402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("ownershipRevoked", params); 2407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user's administrative privileges to the room were revoked 2410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("admin".equals(oldAffiliation) && !"admin".equals(newAffiliation)) { 2411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("adminRevoked", new Object[] {}); 2413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("adminRevoked", params); 2418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user's membership to the room was revoked 2421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("member".equals(oldAffiliation) && !"member".equals(newAffiliation)) { 2422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("membershipRevoked", new Object[] {}); 2424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("membershipRevoked", params); 2429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user was granted ownership to the room 2433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!"owner".equals(oldAffiliation) && "owner".equals(newAffiliation)) { 2434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("ownershipGranted", new Object[] {}); 2436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("ownershipGranted", params); 2441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user was granted administrative privileges to the room 2444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (!"admin".equals(oldAffiliation) && "admin".equals(newAffiliation)) { 2445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("adminGranted", new Object[] {}); 2447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("adminGranted", params); 2452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // The user was granted membership to the room 2455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if (!"member".equals(oldAffiliation) && "member".equals(newAffiliation)) { 2456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("membershipGranted", new Object[] {}); 2458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("membershipGranted", params); 2463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires events according to the received presence code. 2469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param code 2471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param isUserModification 2472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param mucUser 2473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param from 2474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void checkPresenceCode( 2476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String code, 2477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isUserModification, 2478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser, 2479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String from) { 2480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if an occupant was kicked from the room 2481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if ("307".equals(code)) { 2482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if this occupant was kicked 2483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = false; 2485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners( 2487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "kicked", 2488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new Object[] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); 2489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset occupant information. 2491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.clear(); 2492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nickname = null; 2493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasLeft(); 2494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(mucUser.getItem().getActor()); 2499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(mucUser.getItem().getReason()); 2500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("kicked", params); 2501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // A user was banned from the room 2504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("301".equals(code)) { 2505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if this occupant was banned 2506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = false; 2508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners( 2510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "banned", 2511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new Object[] { mucUser.getItem().getActor(), mucUser.getItem().getReason()}); 2512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset occupant information. 2514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.clear(); 2515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nickname = null; 2516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasLeft(); 2517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else { 2519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(mucUser.getItem().getActor()); 2522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(mucUser.getItem().getReason()); 2523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("banned", params); 2524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // A user's membership was revoked from the room 2527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("321".equals(code)) { 2528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if this occupant's membership was revoked 2529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isUserModification) { 2530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen joined = false; 2531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireUserStatusListeners("membershipRevoked", new Object[] {}); 2533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Reset occupant information. 2535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen occupantsMap.clear(); 2536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nickname = null; 2537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen userHasLeft(); 2538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // A occupant has changed his nickname in the room 2541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else if ("303".equals(code)) { 2542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List<String> params = new ArrayList<String>(); 2543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(from); 2544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen params.add(mucUser.getItem().getNick()); 2545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireParticipantStatusListeners("nicknameChanged", params); 2546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void cleanup() { 2550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 2551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (connection != null) { 2552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen roomListenerMultiplexor.removeRoom(room); 2553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Remove all the PacketListeners added to the connection by this chat 2554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (PacketListener connectionListener : connectionListeners) { 2555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.removePacketListener(connectionListener); 2556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Exception e) { 2559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Do nothing 2560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void finalize() throws Throwable { 2564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cleanup(); 2565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen super.finalize(); 2566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * An InvitationsMonitor monitors a given connection to detect room invitations. Every 2570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * time the InvitationsMonitor detects a new invitation it will fire the invitation listeners. 2571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak 2573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static class InvitationsMonitor implements ConnectionListener { 2575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We use a WeakHashMap so that the GC can collect the monitor when the 2576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // connection is no longer referenced by any object. 2577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Note that when the InvitationsMonitor is used, i.e. when there are InvitationListeners, it will add a 2578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // PacketListener to the Connection and therefore a strong reference from the Connection to the 2579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // InvitationsMonior will exists, preventing it from beeing gc'ed. After the last InvitationListener is gone, 2580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // the PacketListener will get removed (cancel()) allowing the garbage collection of the InvitationsMonitor 2581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // instance. 2582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final static Map<Connection, WeakReference<InvitationsMonitor>> monitors = 2583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new WeakHashMap<Connection, WeakReference<InvitationsMonitor>>(); 2584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We don't use a synchronized List here because it would break the semantic of (add|remove)InvitationListener 2586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private final List<InvitationListener> invitationsListeners = 2587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new ArrayList<InvitationListener>(); 2588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Connection connection; 2589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PacketFilter invitationFilter; 2590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PacketListener invitationPacketListener; 2591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns a new or existing InvitationsMonitor for a given connection. 2594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param conn the connection to monitor for room invitations. 2596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return a new or existing InvitationsMonitor for a given connection. 2597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static InvitationsMonitor getInvitationsMonitor(Connection conn) { 2599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (monitors) { 2600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!monitors.containsKey(conn) || monitors.get(conn).get() == null) { 2601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // We need to use a WeakReference because the monitor references the 2602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // connection and this could prevent the GC from collecting the monitor 2603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // when no other object references the monitor 2604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InvitationsMonitor ivm = new InvitationsMonitor(conn); 2605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen monitors.put(conn, new WeakReference<InvitationsMonitor>(ivm)); 2606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return ivm; 2607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Return the InvitationsMonitor that monitors the connection 2609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return monitors.get(conn).get(); 2610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new InvitationsMonitor that will monitor invitations received 2615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * on a given connection. 2616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param connection the connection to monitor for possible room invitations 2618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private InvitationsMonitor(Connection connection) { 2620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.connection = connection; 2621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a listener to invitation notifications. The listener will be fired anytime 2625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an invitation is received.<p> 2626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If this is the first monitor's listener then the monitor will be initialized in 2628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * order to start listening to room invitations. 2629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation listener. 2631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void addInvitationListener(InvitationListener listener) { 2633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationsListeners) { 2634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If this is the first monitor's listener then initialize the listeners 2635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // on the connection to detect room invitations 2636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (invitationsListeners.size() == 0) { 2637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen init(); 2638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!invitationsListeners.contains(listener)) { 2640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationsListeners.add(listener); 2641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a listener to invitation notifications. The listener will be fired anytime 2647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an invitation is received.<p> 2648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If there are no more listeners to notifiy for room invitations then the monitor will 2650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * be stopped. As soon as a new listener is added to the monitor, the monitor will resume 2651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * monitoring the connection for new room invitations. 2652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 2653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener an invitation listener. 2654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void removeInvitationListener(InvitationListener listener) { 2656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationsListeners) { 2657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (invitationsListeners.contains(listener)) { 2658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationsListeners.remove(listener); 2659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // If there are no more listeners to notifiy for room invitations 2661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // then proceed to cancel/release this monitor 2662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (invitationsListeners.size() == 0) { 2663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cancel(); 2664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Fires invitation listeners. 2670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void fireInvitationListeners(String room, String inviter, String reason, String password, 2672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message message) { 2673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InvitationListener[] listeners; 2674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (invitationsListeners) { 2675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listeners = new InvitationListener[invitationsListeners.size()]; 2676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationsListeners.toArray(listeners); 2677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (InvitationListener listener : listeners) { 2679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener.invitationReceived(connection, room, inviter, reason, password, message); 2680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionClosed() { 2684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cancel(); 2685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionClosedOnError(Exception e) { 2688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // ignore 2689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectingIn(int seconds) { 2692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // ignore 2693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectionSuccessful() { 2696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // ignore 2697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectionFailed(Exception e) { 2700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // ignore 2701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Initializes the listeners to detect received room invitations and to detect when the 2705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * connection gets closed. As soon as a room invitation is received the invitations 2706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * listeners will be fired. When the connection gets closed the monitor will remove 2707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * his listeners on the connection. 2708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void init() { 2710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Listens for all messages that include a MUCUser extension and fire the invitation 2711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // listeners if the message includes an invitation. 2712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationFilter = 2713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new PacketExtensionFilter("x", "http://jabber.org/protocol/muc#user"); 2714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen invitationPacketListener = new PacketListener() { 2715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void processPacket(Packet packet) { 2716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Get the MUCUser extension 2717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen MUCUser mucUser = 2718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (MUCUser) packet.getExtension("x", "http://jabber.org/protocol/muc#user"); 2719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Check if the MUCUser extension includes an invitation 2720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (mucUser.getInvite() != null && 2721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((Message) packet).getType() != Message.Type.error) { 2722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Fire event for invitation listeners 2723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen fireInvitationListeners(packet.getFrom(), mucUser.getInvite().getFrom(), 2724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen mucUser.getInvite().getReason(), mucUser.getPassword(), (Message) packet); 2725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 2728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.addPacketListener(invitationPacketListener, invitationFilter); 2729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add a listener to detect when the connection gets closed in order to 2730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // cancel/release this monitor 2731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.addConnectionListener(this); 2732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 2735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Cancels all the listeners that this InvitationsMonitor has added to the connection. 2736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 2737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void cancel() { 2738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.removePacketListener(invitationPacketListener); 2739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.removeConnectionListener(this); 2740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 2743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 2744