package net.sf.colossus.webserver;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.colossus.webcommon.ChatMessage;
public class ChatMsgStorage
{
private static final Logger LOGGER = Logger.getLogger(ChatMsgStorage.class
.getName());
private final WebServerOptions options;
private final ChatChannel channel;
private final List<ChatMessage> lastNChatMessages;
/** Just by coincidence, we use the same separator as for the network
* transmissions, so then there is no risk of "can't be unambiguely
* encoded".
*/
private final static String SEP = " ~ ";
public ChatMsgStorage(ChatChannel theChannel, WebServerOptions options)
{
this.options = options;
this.channel = theChannel;
LOGGER.fine("Chat Message Storage instantiated for channel "
+ getChannel().getChannelId());
this.lastNChatMessages = new ArrayList<ChatMessage>();
restoreMessages();
}
public void dispose()
{
storeMessages();
LOGGER.fine("disposing - stored " + lastNChatMessages.size()
+ " messages");
}
public ChatChannel getChannel()
{
return channel;
}
public List<ChatMessage> getLastNChatMessages()
{
return Collections.unmodifiableList(lastNChatMessages);
}
void storeMessage(ChatMessage msg)
{
List<ChatMessage> list = lastNChatMessages;
synchronized (list)
{
list.add(msg);
if (list.size() > WebServerConstants.keepLastNMessages)
{
// if longer than max, remove oldest one
list.remove(0);
}
}
}
/** Store all messages to a permanent storage (Disk file or DB) from where
* they can be read back when server is restarting
*/
private void storeMessages()
{
String usersFileDirectory = options
.getStringOption(WebServerConstants.optDataDirectory);
if (usersFileDirectory == null)
{
LOGGER
.severe("Data Directory (for chat messages file) is null! Define it in cf file!");
System.exit(1);
}
String filename = "Chatmessages-" + getChannel().getChannelId()
+ ".txt";
PrintWriter out = null;
try
{
out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(
new File(usersFileDirectory, filename)),
WebServerConstants.charset));
for (ChatMessage msg : getLastNChatMessages())
{
String line = makeLine(msg);
out.println(line);
}
out.close();
}
catch (FileNotFoundException e)
{
LOGGER.log(Level.SEVERE, "Writing char messages file " + filename
+ "failed: FileNotFoundException: ", e);
}
}
private void restoreMessages()
{
String usersFileDirectory = options
.getStringOption(WebServerConstants.optDataDirectory);
if (usersFileDirectory == null)
{
LOGGER
.severe("Data Directory (for chat messages file) is null! Define it in cf file!");
System.exit(1);
}
String filename = "Chatmessages-" + getChannel().getChannelId()
+ ".txt";
try
{
BufferedReader msgs = new BufferedReader(new InputStreamReader(
new FileInputStream(new File(usersFileDirectory, filename)),
WebServerConstants.charset));
String line = null;
while ((line = msgs.readLine()) != null)
{
if (line.matches("\\s*"))
{
// ignore empty line
}
else
{
parseMsgLine(line);
}
}
msgs.close();
LOGGER.info("Restored " + lastNChatMessages.size()
+ " messages from file.");
}
catch (FileNotFoundException e)
{
LOGGER.log(Level.SEVERE, "Chat messages file " + filename
+ " not found!", e);
System.exit(1);
}
catch (IOException e)
{
LOGGER.log(Level.SEVERE,
"IOException while reading chat messages file " + filename
+ "!", e);
System.exit(1);
}
}
public String makeLine(ChatMessage msg)
{
return msg.getChatId() + SEP + msg.getWhen() + SEP + msg.getSender()
+ SEP + msg.getMessage();
}
private void parseMsgLine(String line)
{
String[] tokens = line.split(SEP, 4);
if (tokens.length != 4)
{
LOGGER.log(Level.WARNING, "invalid line '" + line
+ "' in chat messages file!");
return;
}
String chatId = tokens[0].trim();
long when = Long.parseLong(tokens[1].trim());
String sender = tokens[2].trim();
String text = tokens[3].trim();
ChatMessage msg = new ChatMessage(chatId, when, sender, text);
storeMessage(msg);
}
}