diff --git a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java index e8c79c70b..815f2b8fe 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: LogListener.java,v 1.9 2008/04/02 16:42:39 fros4943 Exp $ + * $Id: LogListener.java,v 1.10 2008/09/01 13:01:05 fros4943 Exp $ */ package se.sics.cooja.plugins; @@ -40,17 +40,14 @@ import java.util.*; import javax.swing.*; import org.apache.log4j.Logger; import org.jdom.Element; - import se.sics.cooja.*; import se.sics.cooja.interfaces.Log; /** * A simple mote log listener. - * When instantiated, is registers as a listener on all currently existing - * motes' log interfaces. (Observe that if new motes are added to a simulation, - * a new log listener must be created to listen to those motes also). + * Listens to all motes' log interfaces. * - * @author Fredrik Osterlind + * @author Fredrik Osterlind, Niclas Finne */ @ClassDescription("Log Listener") @PluginType(PluginType.SIM_PLUGIN) @@ -62,9 +59,12 @@ public class LogListener extends VisPlugin { private Observer logObserver; private Simulation simulation; - private String filterText = null; + private String filterText = ""; private JTextField filterTextField = null; + private String[] logCache = new String[256]; + private int logPos; + /** * Create a new simulation control panel. * @@ -84,25 +84,38 @@ public class LogListener extends VisPlugin { Mote mote = (Mote) obj; Log moteLogInterface = (Log) obs; + String lastMessage = moteLogInterface.getLastLogMessages(); + if (lastMessage.length() > 0 && lastMessage.charAt(lastMessage.length() - 1) == '\n') { + lastMessage = lastMessage.substring(0, lastMessage.length() - 1); + } String outputString = "TIME:" + simulation.getSimulationTime() + "\t"; if (mote != null && mote.getInterfaces().getMoteID() != null) { - outputString = outputString.concat("ID:" + mote.getInterfaces().getMoteID().getMoteID() + "\t"); + outputString += "ID:" + mote.getInterfaces().getMoteID().getMoteID() + "\t"; + } + outputString += lastMessage; + if (logCache.length > 1) { + synchronized (logCache) { + logCache[logPos] = outputString; + logPos = (logPos + 1) % logCache.length; + } } // Match against filter (if any) - if (filterText != null && !filterText.equals("") && - !moteLogInterface.getLastLogMessages().contains(filterText)) { + if (filterText.length() > 0 && !outputString.contains(filterText)) { return; } - outputString = outputString.concat(moteLogInterface.getLastLogMessages()); - final String str = outputString; SwingUtilities.invokeLater(new Runnable() { public void run() { - logTextArea.append("\n"); - logTextArea.append(str); - logTextArea.setCaretPosition(logTextArea.getDocument().getLength()); + int len = logTextArea.getDocument().getLength(); + if (len == 0) { + logTextArea.append(str); + } else { + logTextArea.append('\n' + str); + len++; + } + logTextArea.setCaretPosition(len + str.length()); } }); } @@ -140,15 +153,46 @@ public class LogListener extends VisPlugin { JPanel filterPanel = new JPanel(); filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.X_AXIS)); filterTextField = new JTextField(""); - filterPanel.add(Box.createVerticalStrut(2)); + filterPanel.add(Box.createHorizontalStrut(2)); filterPanel.add(new JLabel("Filter on string: ")); filterPanel.add(filterTextField); filterTextField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + String oldFilterText = filterText; filterText = filterTextField.getText(); + if (filterText == null) { + filterText = ""; + } + if (!filterText.equals(oldFilterText) && logCache.length > 1) { + // Update from log cache + StringBuilder sb = new StringBuilder(); + synchronized(logCache) { + int pos = logPos; + int count; + if(logCache[pos] != null) { + // Log cache has wrapped + count = logCache.length; + } else { + // Log cache has not wrapped yet + count = pos; + pos = 0; + } + for(int i = 0; i < count; i++) { + if (filterText.length() == 0 || logCache[pos].contains(filterText)) { + if (sb.length() > 0) { + sb.append('\n'); + } + sb.append(logCache[pos]); + } + pos = (pos + 1) % logCache.length; + } + } + logTextArea.setText(sb.toString()); + logTextArea.setCaretPosition(logTextArea.getDocument().getLength()); + } } }); - filterPanel.add(Box.createVerticalStrut(2)); + filterPanel.add(Box.createHorizontalStrut(2)); JButton saveButton; filterPanel.add(saveButton = new JButton("Save log")); saveButton.addActionListener(new ActionListener() { @@ -193,13 +237,13 @@ public class LogListener extends VisPlugin { } }); - if (gui.isVisualizedInApplet()) { + if (GUI.isVisualizedInApplet()) { saveButton.setToolTipText("Not available in applet"); saveButton.setEnabled(false); } getContentPane().add(BorderLayout.CENTER, new JScrollPane(logTextArea)); - getContentPane().add(BorderLayout.SOUTH, new JScrollPane(filterPanel)); + getContentPane().add(BorderLayout.SOUTH, filterPanel); setTitle("Log Listener - Listening on " + nrLogs + " mote logs"); pack(); @@ -230,6 +274,9 @@ public class LogListener extends VisPlugin { element = new Element("filter"); element.setText(filterText); config.add(element); + element = new Element("history"); + element.setText("" + logCache.length); + config.add(element); return config; } @@ -237,14 +284,22 @@ public class LogListener extends VisPlugin { public boolean setConfigXML(Collection configXML, boolean visAvailable) { for (Element element : configXML) { - if (element.getName().equals("filter")) { + String name = element.getName(); + if ("filter".equals(name)) { filterText = element.getText(); filterTextField.setText(filterText); + } else if ("history".equals(name)) { + try { + int size = Integer.parseInt(element.getText().trim()); + logCache = new String[size]; + logPos = 0; + } catch (Exception e) { + // Ignore malformed history size + } } } return true; } - }