mucroomimpl.java
来自「基于Jabber协议的即时消息服务器」· Java 代码 · 共 1,693 行 · 第 1/5 页
JAVA
1,693 行
public Date getEmptyDate() {
return this.emptyDate;
}
public MUCRole getRole() {
return role;
}
public MUCRole getOccupant(String nickname) throws UserNotFoundException {
if (nickname == null) {
throw new UserNotFoundException();
}
MUCRole role = occupants.get(nickname.toLowerCase());
if (role != null) {
return role;
}
throw new UserNotFoundException();
}
public List<MUCRole> getOccupantsByBareJID(String jid) throws UserNotFoundException {
List<MUCRole> roles = occupantsByBareJID.get(jid);
if (roles != null && !roles.isEmpty()) {
return Collections.unmodifiableList(roles);
}
throw new UserNotFoundException();
}
public MUCRole getOccupantByFullJID(JID jid) throws UserNotFoundException {
MUCRole role = occupantsByFullJID.get(jid);
if (role != null) {
return role;
}
throw new UserNotFoundException();
}
public Collection<MUCRole> getOccupants() {
return Collections.unmodifiableCollection(occupants.values());
}
public int getOccupantsCount() {
return occupants.size();
}
public boolean hasOccupant(String nickname) {
return occupants.containsKey(nickname.toLowerCase());
}
public String getReservedNickname(String bareJID) {
String answer = members.get(bareJID);
if (answer == null || answer.trim().length() == 0) {
return null;
}
return answer;
}
public MUCRole.Affiliation getAffiliation(String bareJID) {
if (owners.contains(bareJID)) {
return MUCRole.Affiliation.owner;
}
else if (admins.contains(bareJID)) {
return MUCRole.Affiliation.admin;
}
else if (members.containsKey(bareJID)) {
return MUCRole.Affiliation.member;
}
else if (outcasts.contains(bareJID)) {
return MUCRole.Affiliation.outcast;
}
return MUCRole.Affiliation.none;
}
public MUCRole joinRoom(String nickname, String password, HistoryRequest historyRequest,
MUCUser user, Presence presence) throws UnauthorizedException,
UserAlreadyExistsException, RoomLockedException, ForbiddenException,
RegistrationRequiredException, ConflictException, ServiceUnavailableException,
NotAcceptableException {
MUCRoleImpl joinRole = null;
lock.writeLock().lock();
try {
// If the room has a limit of max user then check if the limit has been reached
if (isDestroyed || (getMaxUsers() > 0 && getOccupantsCount() >= getMaxUsers())) {
throw new ServiceUnavailableException();
}
boolean isOwner = owners.contains(user.getAddress().toBareJID());
// If the room is locked and this user is not an owner raise a RoomLocked exception
if (isLocked()) {
if (!isOwner) {
throw new RoomLockedException();
}
}
// If the user is already in the room raise a UserAlreadyExists exception
if (occupants.containsKey(nickname.toLowerCase())) {
throw new UserAlreadyExistsException();
}
// If the room is password protected and the provided password is incorrect raise a
// Unauthorized exception
if (isPasswordProtected()) {
if (password == null || !password.equals(getPassword())) {
throw new UnauthorizedException();
}
}
// If another user attempts to join the room with a nickname reserved by the first user
// raise a ConflictException
if (members.containsValue(nickname)) {
if (!nickname.equals(members.get(user.getAddress().toBareJID()))) {
throw new ConflictException();
}
}
if (isLoginRestrictedToNickname()) {
String reservedNickname = members.get(user.getAddress().toBareJID());
if (reservedNickname != null && !nickname.equals(reservedNickname)) {
throw new NotAcceptableException();
}
}
// Set the corresponding role based on the user's affiliation
MUCRole.Role role;
MUCRole.Affiliation affiliation;
if (isOwner) {
// The user is an owner. Set the role and affiliation accordingly.
role = MUCRole.Role.moderator;
affiliation = MUCRole.Affiliation.owner;
}
else if (server.getSysadmins().contains(user.getAddress().toBareJID())) {
// The user is a system administrator of the MUC service. Treat him as an owner
// although he won't appear in the list of owners
role = MUCRole.Role.moderator;
affiliation = MUCRole.Affiliation.owner;
}
else if (admins.contains(user.getAddress().toBareJID())) {
// The user is an admin. Set the role and affiliation accordingly.
role = MUCRole.Role.moderator;
affiliation = MUCRole.Affiliation.admin;
}
else if (members.containsKey(user.getAddress().toBareJID())) {
// The user is a member. Set the role and affiliation accordingly.
role = MUCRole.Role.participant;
affiliation = MUCRole.Affiliation.member;
}
else if (outcasts.contains(user.getAddress().toBareJID())) {
// The user is an outcast. Raise a "Forbidden" exception.
throw new ForbiddenException();
}
else {
// The user has no affiliation (i.e. NONE). Set the role accordingly.
if (isMembersOnly()) {
// The room is members-only and the user is not a member. Raise a
// "Registration Required" exception.
throw new RegistrationRequiredException();
}
role = (isModerated() ? MUCRole.Role.visitor : MUCRole.Role.participant);
affiliation = MUCRole.Affiliation.none;
}
// Create a new role for this user in this room
joinRole =
new MUCRoleImpl(server, this, nickname, role, affiliation, (MUCUserImpl) user,
presence, router);
// Add the new user as an occupant of this room
occupants.put(nickname.toLowerCase(), joinRole);
// Update the tables of occupants based on the bare and full JID
List<MUCRole> list = occupantsByBareJID.get(user.getAddress().toBareJID());
if (list == null) {
list = new ArrayList<MUCRole>();
occupantsByBareJID.put(user.getAddress().toBareJID(), list);
}
list.add(joinRole);
occupantsByFullJID.put(user.getAddress(), joinRole);
}
finally {
lock.writeLock().unlock();
}
// Send presence of existing occupants to new occupant
sendInitialPresences(joinRole);
// It is assumed that the room is new based on the fact that it's locked and
// that it was locked when it was created.
boolean isRoomNew = isLocked() && creationDate.getTime() == lockedTime;
try {
// Send the presence of this new occupant to existing occupants
Presence joinPresence = joinRole.getPresence().createCopy();
if (isRoomNew) {
Element frag = joinPresence.getChildElement(
"x", "http://jabber.org/protocol/muc#user");
frag.addElement("status").addAttribute("code", "201");
}
broadcastPresence(joinPresence);
}
catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
// If the room has just been created send the "room locked until configuration is
// confirmed" message
if (isRoomNew) {
Message message = new Message();
message.setType(Message.Type.groupchat);
message.setBody(LocaleUtils.getLocalizedString("muc.new"));
message.setFrom(role.getRoleAddress());
joinRole.send(message);
}
else if (isLocked()) {
// Warn the owner that the room is locked but it's not new
Message message = new Message();
message.setType(Message.Type.groupchat);
message.setBody(LocaleUtils.getLocalizedString("muc.locked"));
message.setFrom(role.getRoleAddress());
joinRole.send(message);
}
else if (canAnyoneDiscoverJID()) {
// Warn the new occupant that the room is non-anonymous (i.e. his JID will be
// public)
Message message = new Message();
message.setType(Message.Type.groupchat);
message.setBody(LocaleUtils.getLocalizedString("muc.warnnonanonymous"));
message.setFrom(role.getRoleAddress());
Element frag = message.addChildElement("x", "http://jabber.org/protocol/muc#user");
frag.addElement("status").addAttribute("code", "100");
joinRole.send(message);
}
if (historyRequest == null) {
Iterator history = roomHistory.getMessageHistory();
while (history.hasNext()) {
joinRole.send((Message) history.next());
}
}
else {
historyRequest.sendHistory(joinRole, roomHistory);
}
// Update the date when the last occupant left the room
setEmptyDate(null);
return joinRole;
}
/**
* Sends presence of existing occupants to new occupant.
*
* @param joinRole the role of the new occupant in the room.
*/
private void sendInitialPresences(MUCRoleImpl joinRole) {
for (MUCRole occupant : occupants.values()) {
if (occupant == joinRole) {
continue;
}
Presence occupantPresence = occupant.getPresence();
// Skip to the next occupant if we cannot send presence of this occupant
if (hasToCheckRoleToBroadcastPresence()) {
Element frag = occupantPresence.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"))) {
continue;
}
}
// Don't include the occupant's JID if the room is semi-anon and the new occupant
// is not a moderator
if (!canAnyoneDiscoverJID() && MUCRole.Role.moderator != joinRole.getRole()) {
occupantPresence = occupantPresence.createCopy();
Element frag = occupantPresence.getChildElement("x",
"http://jabber.org/protocol/muc#user");
frag.element("item").addAttribute("jid", null);
}
joinRole.send(occupantPresence);
}
}
public void leaveRoom(String nickname) throws UserNotFoundException {
MUCRole leaveRole = null;
lock.writeLock().lock();
try {
leaveRole = occupants.remove(nickname.toLowerCase());
if (leaveRole == null) {
throw new UserNotFoundException();
}
// Removes the role from the room
removeOccupantRole(leaveRole);
// 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();
server.removeChatRoom(name);
}
if (occupants.isEmpty()) {
// Update the date when the last occupant left the room
setEmptyDate(new Date());
}
}
finally {
lock.writeLock().unlock();
}
try {
Presence presence = leaveRole.getPresence().createCopy();
presence.setType(Presence.Type.unavailable);
presence.setStatus(null);
// 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);
}
}
/**
* 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.
*/
private void removeOccupantRole(MUCRole leaveRole) {
occupants.remove(leaveRole.getNickname().toLowerCase());
MUCUser user = leaveRole.getChatUser();
// Notify the user that he/she is no longer in the room
user.removeRole(getName());
// Update the tables of occupants based on the bare and full JID
List list = occupantsByBareJID.get(user.getAddress().toBareJID());
if (list != null) {
list.remove(leaveRole);
if (list.isEmpty()) {
occupantsByBareJID.remove(user.getAddress().toBareJID());
}
}
occupantsByFullJID.remove(user.getAddress());
}
public void destroyRoom(String alternateJID, String reason) {
MUCRole leaveRole = null;
Collection<MUCRole> removedRoles = new ArrayList<MUCRole>();
lock.writeLock().lock();
try {
// Remove each occupant
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?