📄 localmucroom.java
字号:
List<MUCRole> list = occupantsByBareJID.get(event.getUserAddress().toBareJID());
if (list == null) {
list = new ArrayList<MUCRole>();
occupantsByBareJID.put(event.getUserAddress().toBareJID(), list);
}
list.add(joinRole);
occupantsByFullJID.put(event.getUserAddress(), joinRole);
// Update the date when the last occupant left the room
setEmptyDate(null);
if (event.isOriginator()) {
// Fire event that occupant joined the room
server.fireOccupantJoined(getRole().getRoleAddress(), event.getUserAddress(), joinRole.getNickname());
}
// Check if we need to send presences of the new occupant to occupants hosted by this JVM
if (event.isSendPresence()) {
for (MUCRole occupant : occupants.values()) {
if (occupant.isLocal()) {
occupant.send(event.getPresence().createCopy());
}
}
}
}
public void leaveRoom(MUCRole leaveRole) {
if (leaveRole.isLocal()) {
// Ask other cluster nodes to remove occupant from room
OccupantLeftEvent event = new OccupantLeftEvent(this, leaveRole);
CacheFactory.doClusterTask(event);
}
try {
Presence presence = leaveRole.getPresence().createCopy();
presence.setType(Presence.Type.unavailable);
presence.setStatus(null);
// Change (or add) presence information about roles and affiliations
Element childElement = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
if (childElement == null) {
childElement = presence.addChildElement("x", "http://jabber.org/protocol/muc#user");
}
Element item = childElement.element("item");
if (item == null) {
item = childElement.addElement("item");
}
item.addAttribute("role", "none");
// Inform the leaving user that he/she has left the room
leaveRole.send(presence);
// Inform the rest of the room occupants that the user has left the room
broadcastPresence(presence);
}
catch (Exception e) {
Log.error(e);
}
// Remove occupant from room and destroy room if empty and not persistent
OccupantLeftEvent event = new OccupantLeftEvent(this, leaveRole);
event.setOriginator(true);
event.run();
}
public void leaveRoom(OccupantLeftEvent event) {
MUCRole leaveRole = event.getRole();
if (leaveRole == null) {
return;
}
lock.writeLock().lock();
try {
// Removes the role from the room
removeOccupantRole(leaveRole, event.isOriginator());
// TODO Implement this: If the room owner becomes unavailable for any reason before
// submitting the form (e.g., a lost connection), the service will receive a presence
// stanza of type "unavailable" from the owner to the room@service/nick or room@service
// (or both). The service MUST then destroy the room, sending a presence stanza of type
// "unavailable" from the room to the owner including a <destroy/> element and reason
// (if provided) as defined under the "Destroying a Room" use case.
// Remove the room from the server only if there are no more occupants and the room is
// not persistent
if (occupants.isEmpty() && !isPersistent()) {
endTime = System.currentTimeMillis();
if (event.isOriginator()) {
server.removeChatRoom(name);
// Fire event that the room has been destroyed
server.fireRoomDestroyed(getRole().getRoleAddress());
}
}
if (occupants.isEmpty()) {
// Update the date when the last occupant left the room
setEmptyDate(new Date());
}
}
finally {
lock.writeLock().unlock();
}
}
/**
* Removes the role of the occupant from all the internal occupants collections. The role will
* also be removed from the user's roles.
*
* @param leaveRole the role to remove.
* @param originator true if this JVM is the one that originated the event.
*/
private void removeOccupantRole(MUCRole leaveRole, boolean originator) {
occupants.remove(leaveRole.getNickname().toLowerCase());
JID userAddress = leaveRole.getUserAddress();
// Notify the user that he/she is no longer in the room
leaveRole.destroy();
// Update the tables of occupants based on the bare and full JID
List list = occupantsByBareJID.get(userAddress.toBareJID());
if (list != null) {
list.remove(leaveRole);
if (list.isEmpty()) {
occupantsByBareJID.remove(userAddress.toBareJID());
}
}
occupantsByFullJID.remove(userAddress);
if (originator) {
// Fire event that occupant left the room
server.fireOccupantLeft(getRole().getRoleAddress(), userAddress);
}
}
public void destroyRoom(DestroyRoomRequest destroyRequest) {
String alternateJID = destroyRequest.getAlternateJID();
String reason = destroyRequest.getReason();
MUCRole leaveRole;
Collection<MUCRole> removedRoles = new ArrayList<MUCRole>();
lock.writeLock().lock();
try {
boolean hasRemoteOccupants = false;
// Remove each occupant
for (String nickname: occupants.keySet()) {
leaveRole = occupants.remove(nickname);
if (leaveRole != null) {
// Add the removed occupant to the list of removed occupants. We are keeping a
// list of removed occupants to process later outside of the lock.
if (leaveRole.isLocal()) {
removedRoles.add(leaveRole);
}
else {
hasRemoteOccupants = true;
}
removeOccupantRole(leaveRole, destroyRequest.isOriginator());
}
}
endTime = System.currentTimeMillis();
// Set that the room has been destroyed
isDestroyed = true;
if (destroyRequest.isOriginator()) {
if (hasRemoteOccupants) {
// Ask other cluster nodes to remove occupants since room is being destroyed
CacheFactory.doClusterTask(new DestroyRoomRequest(this, alternateJID, reason));
}
// Removes the room from the list of rooms hosted in the server
server.removeChatRoom(name);
}
}
finally {
lock.writeLock().unlock();
}
// Send an unavailable presence to each removed occupant
for (MUCRole removedRole : removedRoles) {
try {
// Send a presence stanza of type "unavailable" to the occupant
Presence presence = createPresence(Presence.Type.unavailable);
presence.setFrom(removedRole.getRoleAddress());
// A fragment containing the x-extension for room destruction.
Element fragment = presence.addChildElement("x",
"http://jabber.org/protocol/muc#user");
Element item = fragment.addElement("item");
item.addAttribute("affiliation", "none");
item.addAttribute("role", "none");
if (alternateJID != null && alternateJID.length() > 0) {
fragment.addElement("destroy").addAttribute("jid", alternateJID);
}
if (reason != null && reason.length() > 0) {
Element destroy = fragment.element("destroy");
if (destroy == null) {
destroy = fragment.addElement("destroy");
}
destroy.addElement("reason").setText(reason);
}
removedRole.send(presence);
}
catch (Exception e) {
Log.error(e);
}
}
if (destroyRequest.isOriginator()) {
// Remove the room from the DB if the room was persistent
MUCPersistenceManager.deleteFromDB(this);
// Fire event that the room has been destroyed
server.fireRoomDestroyed(getRole().getRoleAddress());
}
}
public void destroyRoom(String alternateJID, String reason) {
DestroyRoomRequest destroyRequest = new DestroyRoomRequest(this, alternateJID, reason);
destroyRequest.setOriginator(true);
destroyRequest.run();
}
public Presence createPresence(Presence.Type presenceType) throws UnauthorizedException {
Presence presence = new Presence();
presence.setType(presenceType);
presence.setFrom(role.getRoleAddress());
return presence;
}
public void serverBroadcast(String msg) {
Message message = new Message();
message.setType(Message.Type.groupchat);
message.setBody(msg);
message.setFrom(role.getRoleAddress());
broadcast(message);
}
public void sendPublicMessage(Message message, MUCRole senderRole) throws ForbiddenException {
// Check that if the room is moderated then the sender of the message has to have voice
if (isModerated() && senderRole.getRole().compareTo(MUCRole.Role.participant) > 0) {
throw new ForbiddenException();
}
// Send the message to all occupants
message.setFrom(senderRole.getRoleAddress());
send(message);
// Fire event that message was receibed by the room
server.fireMessageReceived(getRole().getRoleAddress(), senderRole.getUserAddress(),
senderRole.getNickname(), message);
}
public void sendPrivatePacket(Packet packet, MUCRole senderRole) throws NotFoundException {
String resource = packet.getTo().getResource();
MUCRole occupant = occupants.get(resource.toLowerCase());
if (occupant != null) {
packet.setFrom(senderRole.getRoleAddress());
occupant.send(packet);
}
else {
throw new NotFoundException();
}
}
public void send(Packet packet) {
if (packet instanceof Message) {
broadcast((Message)packet);
}
else if (packet instanceof Presence) {
broadcastPresence((Presence)packet);
}
else if (packet instanceof IQ) {
IQ reply = IQ.createResultIQ((IQ) packet);
reply.setChildElement(((IQ) packet).getChildElement());
reply.setError(PacketError.Condition.bad_request);
router.route(reply);
}
}
/**
* Broadcasts the specified presence to all room occupants. If the presence belongs to a
* user whose role cannot be broadcast then the presence will only be sent to the presence's
* user. On the other hand, the JID of the user that sent the presence won't be included if the
* room is semi-anon and the target occupant is not a moderator.
*
* @param presence the presence to broadcast.
*/
private void broadcastPresence(Presence presence) {
if (presence == null) {
return;
}
if (hasToCheckRoleToBroadcastPresence()) {
Element frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
// Check if we can broadcast the presence for this role
if (!canBroadcastPresence(frag.element("item").attributeValue("role"))) {
// Just send the presence to the sender of the presence
try {
MUCRole occupant = getOccupant(presence.getFrom().getResource());
occupant.send(presence);
}
catch (UserNotFoundException e) {
// Do nothing
}
return;
}
}
// Broadcast presence to occupants hosted by other cluster nodes
BroascastPresenceRequest request = new BroascastPresenceRequest(this, presence);
CacheFactory.doClusterTask(request);
// Broadcast presence to occupants connected to this JVM
request = new BroascastPresenceRequest(this, presence);
request.setOriginator(true);
request.run();
}
public void broadcast(BroascastPresenceRequest presenceRequest) {
String jid = null;
Presence presence = presenceRequest.getPresence();
Element frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
// Don't include the occupant's JID if the room is semi-anon and the new occupant
// is not a moderator
if (!canAnyoneDiscoverJID()) {
jid = frag.element("item").attributeValue("jid");
}
for (MUCRole occupant : occupants.values()) {
if (!occupant.isLocal()) {
continue;
}
// Don't include the occupant's JID if the room is semi-anon and the new occupant
// is not a moderator
if (!canAnyoneDiscoverJID()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -