⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ajaxchatdao.java

📁 该源码是使用ajax技术实现的一个聊天室功能。如果想对程序进行修改
💻 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 + -