/**
   * Adds a message to this message store. Messages will be stored and made available for later
   * delivery.
   *
   * @param message the message to store.
   */
  public void addMessage(Message message) {
    if (message == null) {
      return;
    }
    if (!shouldStoreMessage(message)) {
      return;
    }
    JID recipient = message.getTo();
    String username = recipient.getNode();
    // If the username is null (such as when an anonymous user), don't store.
    if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) {
      return;
    } else if (!XMPPServer.getInstance()
        .getServerInfo()
        .getXMPPDomain()
        .equals(recipient.getDomain())) {
      // Do not store messages sent to users of remote servers
      return;
    }

    long messageID = SequenceManager.nextID(JiveConstants.OFFLINE);

    // Get the message in XML format.
    String msgXML = message.getElement().asXML();

    Connection con = null;
    PreparedStatement pstmt = null;
    try {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(INSERT_OFFLINE);
      pstmt.setString(1, username);
      pstmt.setLong(2, messageID);
      pstmt.setString(3, StringUtils.dateToMillis(new java.util.Date()));
      pstmt.setInt(4, msgXML.length());
      pstmt.setString(5, msgXML);
      pstmt.executeUpdate();
    } catch (Exception e) {
      Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
    } finally {
      DbConnectionManager.closeConnection(pstmt, con);
    }

    // Update the cached size if it exists.
    if (sizeCache.containsKey(username)) {
      int size = sizeCache.get(username);
      size += msgXML.length();
      sizeCache.put(username, size);
    }
  }
  /* (non-Javadoc)
   * @see org.jivesoftware.openfire.roster.RosterItemProvider#createItem(java.lang.String, org.jivesoftware.openfire.roster.RosterItem)
   */
  public RosterItem createItem(String username, RosterItem item) throws UserAlreadyExistsException {
    Connection con = null;
    PreparedStatement pstmt = null;
    try {
      con = DbConnectionManager.getConnection();

      long rosterID = SequenceManager.nextID(JiveConstants.ROSTER);
      pstmt = con.prepareStatement(CREATE_ROSTER_ITEM);
      pstmt.setString(1, username);
      pstmt.setLong(2, rosterID);
      pstmt.setString(3, item.getJid().toBareJID());
      pstmt.setInt(4, item.getSubStatus().getValue());
      pstmt.setInt(5, item.getAskStatus().getValue());
      pstmt.setInt(6, item.getRecvStatus().getValue());
      pstmt.setString(7, item.getNickname());
      pstmt.executeUpdate();

      item.setID(rosterID);
      insertGroups(rosterID, item.getGroups().iterator(), con);
    } catch (SQLException e) {
      throw new UserAlreadyExistsException(item.getJid().toBareJID());
    } finally {
      try {
        if (pstmt != null) {
          pstmt.close();
        }
      } catch (Exception e) {
        Log.error(e);
      }
      try {
        if (con != null) {
          con.close();
        }
      } catch (Exception e) {
        Log.error(e);
      }
    }
    return item;
  }