diff --git a/src/java/org/jivesoftware/spark/ui/ChatContainer.java b/src/java/org/jivesoftware/spark/ui/ChatContainer.java
index 35f7a0d5..1b41a4c1 100644
--- a/src/java/org/jivesoftware/spark/ui/ChatContainer.java
+++ b/src/java/org/jivesoftware/spark/ui/ChatContainer.java
@@ -14,6 +14,7 @@ import org.jivesoftware.MainWindow;
import org.jivesoftware.Spark;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
+import org.jivesoftware.resource.Default;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
@@ -45,9 +46,9 @@ import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
-import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
+import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -57,6 +58,10 @@ import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Toolkit;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
@@ -97,9 +102,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
* Creates the ChatRooms to hold all ChatRooms.
*/
public ChatContainer() {
- // Have the chat start at the bottom.
super(JTabbedPane.BOTTOM);
-
// Set minimum size
setMinimumSize(new Dimension(400, 200));
// Don't allow tabs to shrink and allow scrolling.
@@ -132,9 +135,12 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
this.setFocusable(false);
setOpaque(true);
+
setBackground(Color.white);
}
+
+
/**
* Adds navigation capability to chat rooms. Users can navigate using the alt-left or right arrow keys.
*/
@@ -176,10 +182,8 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
}
});
- this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl W"), "escape");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "escape");
- this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control W"), "escape");
-
+ this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("Ctrl W"), "escape");
this.getActionMap().put("escape", new AbstractAction("escape") {
public void actionPerformed(ActionEvent evt) {
@@ -192,7 +196,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
String appleString = org.jivesoftware.spark.util.StringUtils.keyStroke2String(appleStroke);
// Handle Apple Key W
- this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(appleString + " W"), "appleStroke");
+ this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(appleString + "w"), "appleStroke");
this.getActionMap().put("appleStroke", new AbstractAction("appleStroke") {
public void actionPerformed(ActionEvent evt) {
closeActiveRoom();
@@ -216,7 +220,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
*
* @param room the ChatRoom to add.
*/
- public void addChatRoom(final ChatRoom room) {
+ public synchronized void addChatRoom(final ChatRoom room) {
createFrameIfNeeded();
room.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY));
@@ -247,7 +251,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
tooltip = "
Contact: " + nickname + "
JID: " + tooltip;
}
else {
- tooltip = ((GroupChatRoom)room).getRoomname();
+ tooltip = room.getRoomname();
}
// Create ChatRoom UI and dock
@@ -270,7 +274,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
chatFrame.setTitle(room.getRoomTitle());
}
- SwingWorker worker = new SwingWorker() {
+ final SwingWorker visibilityThread = new SwingWorker() {
public Object construct() {
try {
Thread.sleep(100);
@@ -286,13 +290,15 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
}
};
- worker.start();
+ visibilityThread.start();
// Add to ChatRoomList
chatRoomList.add(room);
+ // Notify users that the chat room has been opened.
fireChatRoomOpened(room);
+ // Focus Chat
focusChat();
}
@@ -377,7 +383,25 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
flashWindow(chatRoom);
}
else if (!chatFrame.isVisible()) {
- handleHiddenChatFrame(chatRoom);
+ if (Spark.isWindows()) {
+ chatFrame.setFocusableWindowState(false);
+ chatFrame.setState(Frame.ICONIFIED);
+ }
+ chatFrame.setVisible(true);
+
+ // Set to new tab.
+ int tabLocation = indexOfComponent(chatRoom);
+ setSelectedIndex(tabLocation);
+
+ // If the ContactList is in the tray, we need better notification by flashing
+ // the chatframe.
+ if (!SparkManager.getMainWindow().isVisible()) {
+ flashWindow(chatRoom);
+ }
+ else if (chatFrame.getState() == Frame.ICONIFIED) {
+ flashWindow(chatRoom);
+ }
+
}
}
@@ -398,17 +422,12 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
}
fireChatRoomClosed(room);
-
room.removeMessageListener(this);
// Remove mappings
presenceMap.remove(room.getRoomname());
chatRoomList.remove(room);
-
- // Cleanup
- room.getTranscriptWindow().clear();
- room.getTranscripts().clear();
}
/**
@@ -583,9 +602,6 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
}
private void handleMessageNotification(final ChatRoom chatRoom) {
- if (true) {
- return;
- }
ChatRoom activeChatRoom = null;
try {
activeChatRoom = getActiveChatRoom();
@@ -623,32 +639,31 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
startFlashing(chatRoom);
}
else if (!chatFrame.isVisible()) {
- handleHiddenChatFrame(chatRoom);
+ if (Spark.isWindows()) {
+ chatFrame.setFocusableWindowState(false);
+ chatFrame.setState(Frame.ICONIFIED);
+ }
+ chatFrame.setVisible(true);
+
+ // Set to new tab.
+ int tabLocation = indexOfComponent(chatRoom);
+ setSelectedIndex(tabLocation);
+
+ // If the ContactList is in the tray, we need better notification by flashing
+ // the chatframe.
+ if (!SparkManager.getMainWindow().isVisible()) {
+ startFlashing(chatRoom);
+ }
+ else if (chatFrame.getState() == Frame.ICONIFIED) {
+ startFlashing(chatRoom);
+ }
+
}
else if (chatRoom != activeChatRoom) {
startFlashing(chatRoom);
}
}
- private void handleHiddenChatFrame(ChatRoom chatRoom) {
- int tabLocation = indexOfComponent(chatRoom);
- setSelectedIndex(tabLocation);
- if (Spark.isWindows()) {
- chatFrame.setState(Frame.ICONIFIED);
- }
-
- chatFrame.setVisible(true);
-
- // If the ContactList is in the tray, we need better notification by flashing
- // the chatframe.
- if (!SparkManager.getMainWindow().isVisible()) {
- flashWindow(chatRoom);
- }
- else if (chatFrame.getState() == Frame.ICONIFIED) {
- flashWindow(chatRoom);
- }
- }
-
public void messageSent(ChatRoom room, Message message) {
useTabDefault(room);
}
@@ -670,6 +685,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
// Set the title of the room.
chatFrame.setTitle(room.getRoomTitle());
+ chatFrame.setIconImage(SparkManager.getMainWindow().getIconImage());
}
catch (ChatRoomNotFoundException e1) {
// Ignore
@@ -961,14 +977,8 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
if (room instanceof ChatRoomImpl) {
final ChatRoomImpl chatRoomImpl = (ChatRoomImpl)room;
if (!chatRoomImpl.isIconHandler()) {
- Icon icon = chatRoomImpl.getAlternativeIcon();
-
- // if an alternative icon is not used, get the icon based on the users
- // presence.
- if (icon == null) {
- Presence presence = chatRoomImpl.getPresence();
- icon = SparkManager.getUserManager().getTabIconForPresence(presence);
- }
+ Presence presence = chatRoomImpl.getPresence();
+ Icon icon = SparkManager.getUserManager().getTabIconForPresence(presence);
tab.setIcon(icon);
}
}
@@ -1076,7 +1086,6 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
// Set the title of the room.
chatFrame.setTitle(room.getRoomTitle());
- chatFrame.setIconImage(SparkManager.getMainWindow().getIconImage());
}
catch (ChatRoomNotFoundException e1) {
}
@@ -1086,9 +1095,6 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
public void windowDeactivated(WindowEvent windowEvent) {
}
- public void windowClosing(WindowEvent e) {
- }
-
});
// Start timer
@@ -1100,7 +1106,7 @@ public class ChatContainer extends SparkTabbedPane implements MessageListener, C
SwingWorker worker = new SwingWorker() {
public Object construct() {
try {
- Thread.sleep(50);
+ Thread.sleep(1000);
}
catch (InterruptedException e1) {
Log.error(e1);
diff --git a/src/java/org/jivesoftware/spark/ui/ChatRoom.java b/src/java/org/jivesoftware/spark/ui/ChatRoom.java
index a2dd74c2..8a006dc5 100644
--- a/src/java/org/jivesoftware/spark/ui/ChatRoom.java
+++ b/src/java/org/jivesoftware/spark/ui/ChatRoom.java
@@ -94,7 +94,7 @@ public abstract class ChatRoom extends BackgroundPanel implements ActionListener
private final List packetIDList;
private final List messageListeners;
- private List transcript;
+ private List transcript;
private List fileDropListeners;
/**
@@ -110,7 +110,7 @@ public abstract class ChatRoom extends BackgroundPanel implements ActionListener
bottomPanel = new JPanel();
messageListeners = new ArrayList();
- transcript = new ArrayList();
+ transcript = new ArrayList();
editorBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 1));
fileDropListeners = new ArrayList();
@@ -529,7 +529,7 @@ public abstract class ChatRoom extends BackgroundPanel implements ActionListener
*
* @return - the map of current chat responses.
*/
- public List getTranscripts() {
+ public List getTranscripts() {
return transcript;
}
diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java
index 12bf6847..ede590ce 100644
--- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java
+++ b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscriptPlugin.java
@@ -189,13 +189,9 @@ public class ChatTranscriptPlugin implements ChatRoomListener {
final String jid = room.getRoomname();
- List transcripts = room.getTranscripts();
-
- Iterator messages = transcripts.iterator();
-
- ChatTranscript transcript = ChatTranscripts.getChatTranscript(jid);
- while (messages.hasNext()) {
- Message message = (Message)messages.next();
+ final List transcripts = room.getTranscripts();
+ ChatTranscript transcript = new ChatTranscript();
+ for(Message message : transcripts){
HistoryMessage history = new HistoryMessage();
history.setTo(message.getTo());
history.setFrom(message.getFrom());
@@ -210,7 +206,7 @@ public class ChatTranscriptPlugin implements ChatRoomListener {
transcript.addHistoryMessage(history);
}
- ChatTranscripts.saveTranscript(jid);
+ ChatTranscripts.appendToTranscript(jid, transcript);
}
public void chatRoomActivated(ChatRoom room) {
diff --git a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java
index fedcb70e..0cc6e021 100644
--- a/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java
+++ b/src/java/org/jivesoftware/sparkimpl/plugin/transcripts/ChatTranscripts.java
@@ -10,34 +10,35 @@
package org.jivesoftware.sparkimpl.plugin.transcripts;
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.DocumentHelper;
-import org.dom4j.Element;
-import org.dom4j.io.SAXReader;
-import org.dom4j.io.XMLWriter;
import org.jivesoftware.spark.SparkManager;
+import org.jivesoftware.spark.util.URLFileSystem;
import org.jivesoftware.spark.util.log.Log;
+import org.xmlpull.mxp1.MXParser;
+import org.xmlpull.v1.XmlPullParser;
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.io.StringReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.Collection;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-public class ChatTranscripts {
- private static Map TRANSCRIPTS = new HashMap();
- private static Map CURRENT_TRANSCRIPTS = new HashMap();
+/**
+ * A Utility class that manages the Chat Transcripts within Spark.
+ *
+ * @author Derek DeMoro
+ */
+final public class ChatTranscripts {
+
+ /**
+ * Default Date Formatter *
+ */
private static DateFormat FORMATTER;
static {
@@ -48,159 +49,131 @@ public class ChatTranscripts {
}
- public static ChatTranscript getChatTranscript(String jid) {
- ChatTranscript transcript = TRANSCRIPTS.get(jid);
- if (transcript == null) {
- final File transcriptFile = getTranscriptFile(jid);
- transcript = load(transcriptFile);
- TRANSCRIPTS.put(jid, transcript);
+ /**
+ * 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
+ writeToFile(transcriptFile, transcript.getMessages());
+
+ // Write to current history File
+ final File currentHistoryFile = getCurrentHistoryFile(jid);
+ writeToFile(currentHistoryFile, transcript.getNumberOfEntries(20));
+ }
+
+ private static void writeToFile(File transcriptFile, Collection messages) {
+ final StringBuilder builder = new StringBuilder();
+
+ // Handle new transcript file.
+ if (!transcriptFile.exists()) {
+ builder.append("");
}
- return transcript;
- }
- public static ChatTranscript getCurrentChatTranscript(String jid) {
- ChatTranscript transcript = CURRENT_TRANSCRIPTS.get(jid);
- if (transcript == null) {
- final File transcriptFile = getCurrentHistoryFile(jid);
- transcript = load(transcriptFile);
- CURRENT_TRANSCRIPTS.put(jid, transcript);
+ for (HistoryMessage m : messages) {
+ builder.append("");
+ builder.append("").append(m.getTo()).append("");
+ builder.append("").append(m.getFrom()).append("");
+ builder.append("").append(m.getBody()).append("");
+
+ String dateString = FORMATTER.format(m.getDate());
+ builder.append("").append(dateString).append("");
+ builder.append("");
}
- return transcript;
- }
- public static void addChatTranscript(String jid, ChatTranscript transcript) {
- TRANSCRIPTS.put(jid, transcript);
- }
-
- public static void saveTranscript(String jid) {
- try {
- File transcriptFile = getTranscriptFile(jid);
- transcriptFile.getParentFile().mkdirs();
- ChatTranscript transcript = getChatTranscript(jid);
- if (transcript.getMessages().size() == 0) {
- return;
- }
-
- FileOutputStream fout = new FileOutputStream(transcriptFile);
-
- Element root = DocumentHelper.createElement("transcript");
- Element messages = root.addElement("messages");
-
- for (HistoryMessage m : transcript.getMessages()) {
- Element message = messages.addElement("message");
-
- message.addElement("to").setText(m.getTo());
- message.addElement("from").setText(m.getFrom());
- message.addElement("body").setText(m.getBody());
-
- String dateString = FORMATTER.format(m.getDate());
- message.addElement("date").setText(dateString);
- }
-
- ChatTranscript t = new ChatTranscript();
- for(HistoryMessage mes : transcript.getNumberOfEntries(20)){
- t.addHistoryMessage(mes);
- }
- CURRENT_TRANSCRIPTS.put(jid, t);
+ if (!transcriptFile.exists()) {
+ builder.append("");
+ }
+ if (!transcriptFile.exists()) {
+ // Write out new File
try {
- // Write out main transcript
+ FileOutputStream fout = new FileOutputStream(transcriptFile);
OutputStreamWriter ow = new OutputStreamWriter(fout, "UTF-8");
- XMLWriter saxWriter = new XMLWriter(ow);
- saxWriter.write(root);
- saxWriter.flush();
- saxWriter.close();
-
- // Write out current transcript
- List list = messages.elements();
- int size = list.size();
- if (list.size() > 20) {
- for (int i = 0; i < size - 20; i++) {
- final Element ele = (Element)list.get(i);
- messages.remove(ele);
- }
- }
-
- // Write out current transcript
- fout = new FileOutputStream(getCurrentHistoryFile(jid));
-
- ow = new OutputStreamWriter(fout, "UTF-8");
- saxWriter = new XMLWriter(ow);
- saxWriter.write(root);
- saxWriter.flush();
- saxWriter.close();
+ ow.write(builder.toString());
+ ow.close();
}
catch (IOException e) {
Log.error(e);
}
-
- }
- catch (Exception e) {
- Log.error("Error saving settings.", e);
+ return;
}
+ // Append to File
+ try {
+ RandomAccessFile raf = new RandomAccessFile(transcriptFile, "rw");
+ // Seek to end of file
+ raf.seek(transcriptFile.length() - 24);
+
+ builder.append("");
+
+ // Append to the end
+ raf.writeBytes(builder.toString());
+ raf.close();
+ }
+ catch (IOException e) {
+ Log.error(e);
+ }
}
- private static ChatTranscript load(File transcriptFile) {
- final ChatTranscript transcript = new ChatTranscript();
+ /**
+ * 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;
}
-
+ final String contents = URLFileSystem.getContents(transcriptFile);
try {
- FileInputStream fis = new FileInputStream(transcriptFile);
- InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
- SAXReader saxReader = new SAXReader();
- Document pluginXML = null;
- try {
- pluginXML = saxReader.read(isr);
- }
- catch (DocumentException e) {
- Log.error(e);
- return transcript;
- }
-
-
- List messages = pluginXML.selectNodes("/transcript/messages/message");
- Iterator iter = messages.iterator();
-
- while (iter.hasNext()) {
- HistoryMessage message = new HistoryMessage();
-
-
- try {
- Element messageElement = (Element)iter.next();
-
- String to = messageElement.selectSingleNode("to").getText();
- String from = messageElement.selectSingleNode("from").getText();
- String body = messageElement.selectSingleNode("body").getText();
- String date = messageElement.selectSingleNode("date").getText();
-
- message.setTo(to);
- message.setFrom(from);
- message.setBody(body);
- Date d = null;
- try {
- d = FORMATTER.parse(date);
- }
- catch (ParseException e) {
- d = new Date();
- }
- message.setDate(d);
- transcript.addHistoryMessage(message);
+ MXParser parser = new MXParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(new StringReader(contents));
+ boolean done = false;
+ while (!done) {
+ int eventType = parser.next();
+ if (eventType == XmlPullParser.START_TAG && "message".equals(parser.getName())) {
+ transcript.addHistoryMessage(getHistoryMessage(parser));
}
- catch (Exception ex) {
-
+ else if (eventType == XmlPullParser.END_TAG && "transcript".equals(parser.getName())) {
+ done = true;
}
}
}
catch (Exception e) {
- // Ignore
+ e.printStackTrace();
}
+
return transcript;
}
@@ -224,5 +197,40 @@ public class ChatTranscripts {
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(parser.nextText());
+ }
+ else if (eventType == XmlPullParser.START_TAG && "date".equals(parser.getName())) {
+ Date d = null;
+ 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;
+ }
+
}
\ No newline at end of file