mucroomimpl.java
来自「基于Jabber协议的即时消息服务器」· Java 代码 · 共 1,693 行 · 第 1/5 页
JAVA
1,693 行
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.
removedRoles.add(leaveRole);
removeOccupantRole(leaveRole);
}
}
endTime = System.currentTimeMillis();
// Removes the room from the list of rooms hosted in the server
server.removeChatRoom(name);
// Set that the room has been destroyed
isDestroyed = true;
}
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);
}
}
// Remove the room from the DB if the room was persistent
MUCPersistenceManager.deleteFromDB(this);
}
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());
roomHistory.addMessage(message);
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);
}
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) {
roomHistory.addMessage((Message)packet);
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;
}
Element frag = null;
String jid = null;
if (hasToCheckRoleToBroadcastPresence()) {
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;
}
}
// Don't include the occupant's JID if the room is semi-anon and the new occupant
// is not a moderator
if (!canAnyoneDiscoverJID()) {
if (frag == null) {
frag = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
}
jid = frag.element("item").attributeValue("jid");
}
for (MUCRole occupant : occupants.values()) {
// Don't include the occupant's JID if the room is semi-anon and the new occupant
// is not a moderator
if (!canAnyoneDiscoverJID()) {
if (MUCRole.Role.moderator == occupant.getRole()) {
frag.element("item").addAttribute("jid", jid);
}
else {
frag.element("item").addAttribute("jid", null);
}
}
occupant.send(presence);
}
}
private void broadcast(Message message) {
for (MUCRole occupant : occupants.values()) {
// Do not send broadcast messages to deaf occupants
if (!occupant.isVoiceOnly()) {
occupant.send(message);
}
}
if (isLogEnabled()) {
MUCRole senderRole = null;
JID senderAddress;
if (message.getFrom() != null && message.getFrom().getResource() != null) {
senderRole = occupants.get(message.getFrom().getResource());
}
if (senderRole == null) {
// The room itself is sending the message
senderAddress = getRole().getRoleAddress();
}
else {
// An occupant is sending the message
senderAddress = senderRole.getChatUser().getAddress();
}
// Log the conversation
server.logConversation(this, message, senderAddress);
}
server.messageBroadcastedTo(occupants.size());
}
/**
* An empty role that represents the room itself in the chatroom. Chatrooms need to be able to
* speak (server messages) and so must have their own role in the chatroom.
*/
private class RoomRole implements MUCRole {
private MUCRoom room;
private RoomRole(MUCRoom room) {
this.room = room;
}
public Presence getPresence() {
return null;
}
public Element getExtendedPresenceInformation() {
return null;
}
public void setPresence(Presence presence) {
}
public void setRole(MUCRole.Role newRole) {
}
public MUCRole.Role getRole() {
return MUCRole.Role.moderator;
}
public void setAffiliation(MUCRole.Affiliation newAffiliation) {
}
public MUCRole.Affiliation getAffiliation() {
return MUCRole.Affiliation.owner;
}
public String getNickname() {
return null;
}
public MUCUser getChatUser() {
return null;
}
public boolean isVoiceOnly() {
return false;
}
public MUCRoom getChatRoom() {
return room;
}
private JID crJID = null;
public JID getRoleAddress() {
if (crJID == null) {
crJID = new JID(room.getName(), server.getServiceDomain(), "");
}
return crJID;
}
public void send(Packet packet) {
room.send(packet);
}
public void changeNickname(String nickname) {
}
}
public long getChatLength() {
return endTime - startTime;
}
/**
* Updates all the presences of the given user with the new affiliation and role information. Do
* nothing if the given jid is not present in the room. If the user has joined the room from
* several client resources, all his/her occupants' presences will be updated.
*
* @param bareJID the bare jid of the user to update his/her role.
* @param newAffiliation the new affiliation for the JID.
* @param newRole the new role for the JID.
* @return the list of updated presences of all the client resources that the client used to
* join the room.
* @throws NotAllowedException If trying to change the moderator role to an owner or an admin or
* if trying to ban an owner or an administrator.
*/
private List<Presence> changeOccupantAffiliation(String bareJID, MUCRole.Affiliation newAffiliation, MUCRole.Role newRole)
throws NotAllowedException {
List<Presence> presences = new ArrayList<Presence>();
// Get all the roles (i.e. occupants) of this user based on his/her bare JID
List<MUCRole> roles = occupantsByBareJID.get(bareJID);
if (roles == null) {
return presences;
}
// Collect all the updated presences of these roles
for (MUCRole role : roles) {
// Update the presence with the new affiliation and role
role.setAffiliation(newAffiliation);
role.setRole(newRole);
// Prepare a new presence to be sent to all the room occupants
presences.add(role.getPresence().createCopy());
}
// Answer all the updated presences
return presences;
}
/**
* Updates the presence of the given user with the new role information. Do nothing if the given
* jid is not present in the room.
*
* @param jid the full jid of the user to update his/her role.
* @param newRole the new role for the JID.
* @return the updated presence of the user or null if none.
* @throws NotAllowedException If trying to change the moderator role to an owner or an admin.
*/
private Presence changeOccupantRole(JID jid, MUCRole.Role newRole) throws NotAllowedException {
// Try looking the role in the bare JID list
MUCRole role = occupantsByFullJID.get(jid);
if (role != null) {
// Update the presence with the new role
role.setRole(newRole);
// Prepare a new presence to be sent to all the room occupants
return role.getPresence().createCopy();
}
return null;
}
public void addFirstOwner(String bareJID) {
owners.add(bareJID);
}
public List<Presence> addOwner(String bareJID, MUCRole sendRole) throws ForbiddenException {
MUCRole.Affiliation oldAffiliation = MUCRole.Affiliation.none;
if (MUCRole.Affiliation.owner != sendRole.getAffiliation()) {
throw new ForbiddenException();
}
// Check if user is already an owner
if (owners.contains(bareJID)) {
// Do nothing
return Collections.emptyList();
}
owners.add(bareJID);
// Remove the user from other affiliation lists
if (removeAdmin(bareJID)) {
oldAffiliation = MUCRole.Affiliation.admin;
}
else if (removeMember(bareJID)) {
oldAffiliation = MUCRole.Affiliation.member;
}
else if (removeOutcast(bareJID)) {
oldAffiliation = MUCRole.Affiliation.outcast;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?