📄 ajaxchatdao.java
字号:
/*
* Copyright 2005 Frank W. Zammetti
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.struts.apps.ajaxchat.dao;
import java.io.InputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Vector;
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.apps.ajaxchat.AjaxChatConfig;
import org.apache.struts.apps.ajaxchat.dto.MessageDTO;
import org.apache.struts.apps.ajaxchat.dto.RoomDTO;
import org.apache.struts.apps.ajaxchat.dto.UserDTO;
import org.xml.sax.SAXException;
/**
* This Data Access Object (DAO) is really the heart and soul of the app. All
* the real work is done here in terms of recording messages, dealing with
* users and rooms and most everything else. I think it's probably a bit more
* than what a DAO is supposed to generally be, but in this case I don't think
* it's a big deal. Besides, the idea is that if you want to make this a more
* robust application, with real message persistance and such, then all you
* should probably have to mess with is this class. That's the intent anyway.
*
* @author <a href="mailto:fzammetti@omnytex.com">Frank W. Zammetti</a>.
*/
public final class AjaxChatDAO {
/**
* Log instance.
*/
private static Log log = LogFactory.getLog(AjaxChatDAO.class);
/**
* This class is a singleton, so here's the one and only instance.
*/
private static AjaxChatDAO instance;
/**
* Collection of RoomDTO objects.
*/
private LinkedHashMap rooms = new LinkedHashMap();
/**
* Collection of UserDTO objects of currently logged in users.
*/
private Vector users = new Vector();
/**
* Make sure instances of this class can't be created.
*/
private AjaxChatDAO() {
} // End constructor.
/**
* Complete the singleton pattern. This method is the only way to get an
* instance of this class.
*
* @return The one and only instance of this class.
*/
public static AjaxChatDAO getInstance() {
log.debug("getInstance()...");
if (instance == null) {
instance = new AjaxChatDAO();
instance.init(null);
}
return instance;
} // End getInstance().
/**
* Initialize. Read in room-list.xml file and create RoomDTOs for each
* and add it to the collection of rooms. Note that the first time
* getInstance() is called, we pass in null for the isConfigFile parameter,
* and hence the config file is not read. Before this DAO can really be
* used, init() must be called, handing it an InputStream to the config
* file. This is done from ContextListener.
*
* @param isConfigFile InputStream to the config file.
*/
public synchronized void init(InputStream isConfigFile) {
log.debug("init()...");
if (isConfigFile != null) {
// Read in rooms config and create beans, hand off to DAO.
Digester digester = new Digester();
digester.setValidating(false);
digester.push(this);
digester.addObjectCreate("rooms/room",
"org.apache.struts.apps.ajaxchat.dto.RoomDTO");
digester.addSetProperties("rooms/room");
digester.addSetNext("rooms/room", "addRoom");
try {
digester.parse(isConfigFile);
log.info("***** Rooms = " + rooms);
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException se) {
se.printStackTrace();
}
}
} // End init().
/**
* Adds a room to the collection of rooms.
*
* @param inRoom The room to add.
*/
public synchronized void addRoom(RoomDTO inRoom) {
log.debug("addRoom()...");
log.info("Adding room " + inRoom);
rooms.put(inRoom.getName(), inRoom);
} // End addRoom().
/**
* Removes a room from the collection of rooms.
*
* @param inRoomName The namr of the room to remove.
*/
public synchronized void removeRoom(String inRoomName) {
log.debug("removeRoom()...");
RoomDTO room = (RoomDTO)rooms.get(inRoomName);
if (room.getUserList().size() == 0) {
rooms.remove(inRoomName);
log.info("removeRoom() removed room " + inRoomName);
} else {
log.info("removeRoom() Room not removed because " +
"there are users in it");
}
} // End removeRoom().
/**
* Add a message to the list of messages in the named room.
*
* @param inRoom The name of the room to post the message to.
* @param inMessage The message to post.
*/
public synchronized void postMessage(String inRoom, MessageDTO inMessage) {
log.debug("postMessage(): inRoom = " + inRoom +
" - inMessage = " + inMessage + "...");
RoomDTO room = (RoomDTO)rooms.get(inRoom);
room.postMessage(inMessage);
} // End postMessage().
/**
* Gets all messages in a named room newer than the specified datetime.
*
* @param inRoom The name of the room to get messages for.
* @param inDateTime The date/time to start retrieval from. We will actually
* get any message subsequent to this datetime.
* @return List of messages for the named room.
*/
public synchronized Vector getMessages(String inRoom, Date inDateTime) {
log.debug("getMessages(): inRoom = " + inRoom +
" - inDateTime = " + inDateTime + "...");
RoomDTO room = (RoomDTO)rooms.get(inRoom);
return room.getMessages(inDateTime);
} // End getMessages().
/**
* Returns a list of all rooms. Note that this returns the room name only,
* it DOES NOT return a list of RoomDTOs.
*
* @return List of all rooms names.
*/
public synchronized Vector getRoomList() {
log.debug("getRoomList()...");
Vector roomList = new Vector();
for (Iterator it = rooms.keySet().iterator(); it.hasNext();) {
roomList.add((String)it.next());
}
log.info("roomList = " + roomList);
return roomList;
} // End getRoomList().
/**
* Returns a Map of rooms, keyed by room name, with the number of users
* chatting in each as the value.
*
* @return List of all rooms and user counts.
*/
public synchronized LinkedHashMap getRoomUserCounts() {
log.debug("getRoomUserCounts()...");
LinkedHashMap roomList = new LinkedHashMap();
for (Iterator it = rooms.keySet().iterator(); it.hasNext();) {
String roomName = (String)it.next();
roomList.put(roomName,
new Integer(((RoomDTO)rooms.get(roomName)).getUserList().size()));
}
log.debug("roomList = " + roomList);
return roomList;
} // End getRoomUserCounts().
/**
* Returns a list of all users currently chatting in a given room. Note that
* this returns the username only, it DOES NOT return a list of UserDTOs.
*
* @param inRoom The name of the room to get the user list for.
* @return List of all usernames chatting in a named room.
*/
public synchronized Vector getUserList(String inRoom) {
log.debug("getUserList(): inRoom = " + inRoom + "...");
Vector userList = null;
RoomDTO room = (RoomDTO)rooms.get(inRoom);
userList = room.getUserList();
log.info("userList = " + userList);
return userList;
} // End getUserList().
/**
* Adds a user to the specified room.
*
* @param inRoom The room to add to.
* @param inUser The user to add.
*/
public synchronized void addUserToRoom(String inRoom, UserDTO inUser) {
log.info("addUserToRoom()...");
RoomDTO room = (RoomDTO)rooms.get(inRoom);
room.addUser(inUser);
} // End addUserToRoom().
/**
* Removes a user from the specified room.
*
* @param inRoom The room to add to.
* @param inUser The user to remove.
*/
public synchronized void removeUserFromRoom(String inRoom, UserDTO inUser) {
log.debug("removeUserFromRoom()...");
RoomDTO room = (RoomDTO)rooms.get(inRoom);
room.removeUser(inUser);
} // End removeUserFromRoom().
/**
* Removes a user from all rooms. This is kind of a safety net when a
* users' session is destroyed.
*
* @param inUser The user to remove.
*/
public synchronized void removeUserFromAllRooms(UserDTO inUser) {
log.debug("removeUserFromAllRooms()...");
for (Iterator it = rooms.keySet().iterator(); it.hasNext();) {
String roomName = (String)it.next();
RoomDTO room = (RoomDTO)rooms.get(roomName);
room.removeUser(inUser);
}
} // End removeUserFromAllRooms().
/**
* Adds a user to the list of logged on users.
*
* @param inUser The user to log in.
*/
public synchronized void logUserIn(UserDTO inUser) {
log.debug("logUserIn()...");
users.add(inUser);
log.info(inUser.getUsername() + " logged in");
} // End logUserIn().
/**
* Removes a user from the list of logged on users.
*
* @param inUser The user to log out.
*/
public synchronized void logUserOut(UserDTO inUser) {
log.debug("logUserOut()...");
String usernameToLogOut = inUser.getUsername();
int i = 0;
int indexToRemove = -1;
for (Iterator it = users.iterator(); it.hasNext();) {
UserDTO user = (UserDTO)it.next();
if (usernameToLogOut.equalsIgnoreCase(user.getUsername())) {
indexToRemove = i;
}
i++;
}
if (indexToRemove != -1) {
users.remove(indexToRemove);
log.info(usernameToLogOut + " logged out");
}
} // End logUserIn().
/**
* Checks to see if a given username is in use in any room.
*
* @param inUsername The name to check.
* @return True if the name is in use, false if not.
*/
public synchronized boolean isUsernameInUse(String inUsername) {
log.debug("isUsernameInUse()...");
boolean retVal = false;
for (Iterator it = users.iterator(); it.hasNext();) {
UserDTO user = (UserDTO)it.next();
if (inUsername.equalsIgnoreCase(user.getUsername())) {
retVal = true;
}
}
log.debug("Returning " + retVal);
return retVal;
} // End isUsernameInUse().
/**
* This method goes through the collection of users and determines which, if
* any, are inactive. Any that are inactive are removed. This is called
* from the UserClearerDaemon thread.
*/
public synchronized void removeInactiveUsers() {
log.debug("removeInactiveUsers()...");
Vector usersToRemove = new Vector();
for (Iterator it = users.iterator(); it.hasNext();) {
UserDTO user = (UserDTO)it.next();
long now = new Date().getTime();
long lastAJAXRequest = user.getLastAJAXRequest().getTime();
if ((now - lastAJAXRequest) >=
(AjaxChatConfig.getUserInactivitySeconds() * 1000)) {
log.info("User " + user.getUsername() + " will be removed");
usersToRemove.add(user);
}
}
for (Iterator it = usersToRemove.iterator(); it.hasNext();) {
UserDTO user = (UserDTO)it.next();
removeUserFromAllRooms(user);
logUserOut(user);
}
} // End removeInactiveUsers().
} // End class.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -