/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 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. */ package org.jivesoftware.sparkimpl.plugin.transcripts; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.UserManager; import org.jivesoftware.spark.util.StringUtils; import org.jivesoftware.spark.util.log.Log; import org.xmlpull.mxp1.MXParser; import org.xmlpull.v1.XmlPullParser; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.RandomAccessFile; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; /** * A Utility class that manages the Chat Transcripts within Spark. * * @author Derek DeMoro */ public final class ChatTranscripts { /** * Default Date Formatter * */ private static DateFormat FORMATTER; static { FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z"); } private ChatTranscripts() { } /** * Appends the given ChatTranscript to the transcript file associated with a JID. * * @param jid the jid of the user. * @param transcript the ChatTranscript. */ public static void appendToTranscript(String jid, ChatTranscript transcript) { final File transcriptFile = getTranscriptFile(jid); // Write Full Transcript, appending the messages. writeToFile(transcriptFile, transcript.getMessages(), true); // Write to current history File final File currentHistoryFile = getCurrentHistoryFile(jid); ChatTranscript tempTranscript = getCurrentChatTranscript(jid); for (HistoryMessage message : transcript.getMessages()) { tempTranscript.addHistoryMessage(message); } writeToFile(currentHistoryFile, tempTranscript.getNumberOfEntries(20), false); } private static void writeToFile(File transcriptFile, Collection<HistoryMessage> messages, boolean append) { final StringBuilder builder = new StringBuilder(); final String one = " "; final String two = " "; final String three = " "; // Handle new transcript file. if (!transcriptFile.exists() || !append) { builder.append("<transcript>\n"); builder.append(one+"<messages>\n"); } for (HistoryMessage m : messages) { builder.append(two+"<message>\n"); builder.append(three+"<to>").append(m.getTo()).append("</to>\n"); builder.append(three+"<from>").append(m.getFrom()).append("</from>\n"); builder.append(three+"<body>").append(StringUtils.escapeForXML(m.getBody())).append("</body>\n"); String dateString = FORMATTER.format(m.getDate()); builder.append(three+"<date>").append(dateString).append("</date>\n"); builder.append(two+"</message>\n"); } if (!transcriptFile.exists() || !append) { builder.append(one+"</messages>\n"); builder.append("</transcript>"); } if (!transcriptFile.exists() || !append) { // Write out new File try { transcriptFile.getParentFile().mkdirs(); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(transcriptFile), "UTF-8")); out.write(builder.toString()); out.close(); } catch (IOException e) { Log.error(e); } return; } // Append to File try { final RandomAccessFile raf = new RandomAccessFile(transcriptFile, "rw"); // We want to append near the end of the document as the last // child in the transcript. final String endTag = " </messages>\n</transcript>"; String line = raf.readLine(); if(line.contains("</messages></transcript>")) { // replace the old one with the new one line = line.replace("</messages></transcript>",endTag); raf.write(line.getBytes("UTF-8")); } builder.append(endTag); raf.seek(transcriptFile.length() - endTag.length()); // Append to the end raf.write(builder.toString().getBytes("UTF-8")); raf.close(); } catch (IOException e) { Log.error(e); } } /** * Retrieve the current chat history. * * @param jid the jid of the user whos history you wish to retrieve. * @return the ChatTranscript (last 20 messages max). */ public static ChatTranscript getCurrentChatTranscript(String jid) { return getTranscript(getCurrentHistoryFile(jid)); } /** * Retrieve the full chat history. * * @param jid the jid of the the user whos history you wish to retrieve. * @return the ChatTranscript. */ public static ChatTranscript getChatTranscript(String jid) { return getTranscript(getTranscriptFile(jid)); } /** * Reads in the transcript file using the Xml Pull Parser. * * @param transcriptFile the transcript file to read. * @return the ChatTranscript. */ public static ChatTranscript getTranscript(File transcriptFile) { final ChatTranscript transcript = new ChatTranscript(); if (!transcriptFile.exists()) { return transcript; } try { final MXParser parser = new MXParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(transcriptFile), "UTF-8")); parser.setInput(in); boolean done = false; while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG && "message".equals(parser.getName())) { transcript.addHistoryMessage(getHistoryMessage(parser)); } else if (eventType == XmlPullParser.END_TAG && "transcript".equals(parser.getName())) { done = true; } } } catch (Exception e) { e.printStackTrace(); } return transcript; } /** * Returns the settings file. * * @param jid the * @return the settings file. */ public static File getTranscriptFile(String jid) { // Unescape Node jid = UserManager.unescapeJID(jid); return new File(SparkManager.getUserDirectory(), "transcripts/" + jid + ".xml"); } /** * Returns the current transcript (20 messages) for a particular jid. * * @param jid the jid of the user. * @return the current transcript file. */ public static File getCurrentHistoryFile(String jid) { // Unescape Node jid = UserManager.unescapeJID(jid); return new File(SparkManager.getUserDirectory(), "transcripts/" + jid + "_current.xml"); } private static HistoryMessage getHistoryMessage(XmlPullParser parser) throws Exception { HistoryMessage message = new HistoryMessage(); // Check for nickname boolean done = false; while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG && "to".equals(parser.getName())) { message.setTo(parser.nextText()); } else if (eventType == XmlPullParser.START_TAG && "from".equals(parser.getName())) { message.setFrom(parser.nextText()); } else if (eventType == XmlPullParser.START_TAG && "body".equals(parser.getName())) { message.setBody(StringUtils.unescapeFromXML(parser.nextText())); } else if (eventType == XmlPullParser.START_TAG && "date".equals(parser.getName())) { Date d; try { d = FORMATTER.parse(parser.nextText()); } catch (ParseException e) { d = new Date(); } message.setDate(d); } else if (eventType == XmlPullParser.END_TAG && "message".equals(parser.getName())) { done = true; } } return message; } }