Java tutorial
package net.emiva.crossfire.plugin.muc; /** * $RCSfile: HistoryRequest.java,v $ * $Revision: 2899 $ * $Date: 2005-09-28 15:30:42 -0300 (Wed, 28 Sep 2005) $ * * Copyright (C) 2004-2008 Jive Software. All rights reserved. * * 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. */ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import java.util.TimeZone; import net.emiva.crossfire.plugin.muc.spi.LocalMUCRole; import net.emiva.util.GlobalConstants; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xmpp.packet.Message; /** * Represents the amount of history requested by an occupant while joining a room. There are * basically four ways to control the amount of history that a user may receive. Those are: limit * by the maximum limit of characters to receive, limit by a maximum number of stanzas to receive, * limit to receive only the messages before a given date or of the last X seconds.<p> * * A user may combine any of these four methods. The idea is that the user will receive the smallest * amount of traffic so the amount of history to collect will stop as soon as any of the requested * method has reached its limit. * * @author Gaston Dombiak */ public class HistoryRequest { private static final Logger Log = LoggerFactory.getLogger(HistoryRequest.class); private static final DateFormat formatter = new SimpleDateFormat(GlobalConstants.XMPP_DATETIME_FORMAT); private static final DateFormat delayedFormatter = new SimpleDateFormat( GlobalConstants.XMPP_DELAY_DATETIME_FORMAT); static { delayedFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); } private int maxChars = -1; private int maxStanzas = -1; private int seconds = -1; private Date since; public HistoryRequest(Element userFragment) { Element history = userFragment.element("history"); if (history != null) { if (history.attribute("maxchars") != null) { this.maxChars = Integer.parseInt(history.attributeValue("maxchars")); } if (history.attribute("maxstanzas") != null) { this.maxStanzas = Integer.parseInt(history.attributeValue("maxstanzas")); } if (history.attribute("seconds") != null) { this.seconds = Integer.parseInt(history.attributeValue("seconds")); } if (history.attribute("since") != null) { try { // parse utc into Date synchronized (formatter) { this.since = formatter.parse(history.attributeValue("since")); } } catch (ParseException pe) { Log.error("Error parsing date from history management", pe); this.since = null; } } } } /** * Returns the total number of characters to receive in the history. * * @return total number of characters to receive in the history. */ public int getMaxChars() { return maxChars; } /** * Returns the total number of messages to receive in the history. * * @return the total number of messages to receive in the history. */ public int getMaxStanzas() { return maxStanzas; } /** * Returns the number of seconds to use to filter the messages received during that time. * In other words, only the messages received in the last "X" seconds will be included in * the history. * * @return the number of seconds to use to filter the messages received during that time. */ public int getSeconds() { return seconds; } /** * Returns the since date to use to filter the messages received during that time. * In other words, only the messages received since the datetime specified will be * included in the history. * * @return the since date to use to filter the messages received during that time. */ public Date getSince() { return since; } /** * Returns true if the history has been configured with some values. * * @return true if the history has been configured with some values. */ private boolean isConfigured() { return maxChars > -1 || maxStanzas > -1 || seconds > -1 || since != null; } /** * Sends the smallest amount of traffic that meets any combination of the requested criteria. * * @param joinRole the user that will receive the history. * @param roomHistory the history of the room. */ public void sendHistory(LocalMUCRole joinRole, MUCRoomHistory roomHistory) { if (!isConfigured()) { Iterator history = roomHistory.getMessageHistory(); while (history.hasNext()) { joinRole.send((Message) history.next()); } } else { Message changedSubject = roomHistory.getChangedSubject(); boolean addChangedSubject = (changedSubject != null) ? true : false; if (getMaxChars() == 0) { // The user requested to receive no history if (addChangedSubject) { joinRole.send(changedSubject); } return; } Message message; int accumulatedChars = 0; int accumulatedStanzas = 0; Element delayInformation; LinkedList<Message> historyToSend = new LinkedList<Message>(); ListIterator iterator = roomHistory.getReverseMessageHistory(); while (iterator.hasPrevious()) { message = (Message) iterator.previous(); // Update number of characters to send String text = message.getBody() == null ? message.getSubject() : message.getBody(); if (text == null) { // Skip this message since it has no body and no subject continue; } accumulatedChars += text.length(); if (getMaxChars() > -1 && accumulatedChars > getMaxChars()) { // Stop collecting history since we have exceded a limit break; } // Update number of messages to send accumulatedStanzas++; if (getMaxStanzas() > -1 && accumulatedStanzas > getMaxStanzas()) { // Stop collecting history since we have exceded a limit break; } if (getSeconds() > -1 || getSince() != null) { delayInformation = message.getChildElement("x", "jabber:x:delay"); try { // Get the date when the historic message was sent Date delayedDate; synchronized (delayedFormatter) { delayedDate = delayedFormatter.parse(delayInformation.attributeValue("stamp")); } if (getSince() != null && delayedDate.before(getSince())) { // Stop collecting history since we have exceded a limit break; } if (getSeconds() > -1) { Date current = new Date(); long diff = (current.getTime() - delayedDate.getTime()) / 1000; if (getSeconds() <= diff) { // Stop collecting history since we have exceded a limit break; } } } catch (Exception e) { Log.error("Error parsing date from historic message", e); } } // Don't add the latest subject change if it's already in the history. if (addChangedSubject) { if (changedSubject != null && changedSubject.equals(message)) { addChangedSubject = false; } } historyToSend.addFirst(message); } // Check if we should add the latest subject change. if (addChangedSubject) { historyToSend.addFirst(changedSubject); } // Send the smallest amount of traffic to the user for (Object aHistoryToSend : historyToSend) { joinRole.send((Message) aHistoryToSend); } } } }