From edb5a1800090f718c18142fd204d5f4555caa5fd Mon Sep 17 00:00:00 2001 From: fros4943 Date: Tue, 22 Apr 2008 10:12:16 +0000 Subject: [PATCH] interact with simulations using javascripts --- .../sics/cooja/plugins/LogScriptEngine.java | 203 ++++++++++++++++++ .../se/sics/cooja/plugins/ScriptRunner.java | 134 ++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java create mode 100644 tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java diff --git a/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java b/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java new file mode 100644 index 000000000..40ec029dc --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/plugins/LogScriptEngine.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2008, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: LogScriptEngine.java,v 1.1 2008/04/22 10:12:16 fros4943 Exp $ + */ + +package se.sics.cooja.plugins; + +import java.lang.reflect.UndeclaredThrowableException; +import java.util.*; +import javax.swing.*; +import javax.script.*; + +import org.apache.log4j.Logger; +import se.sics.cooja.*; + +/** + * Executes JavaScripts on mote logs. + * + * @see ScriptRunner + * + * @author Fredrik Osterlind + */ +public class LogScriptEngine { + private static final long serialVersionUID = 1L; + private static Logger logger = Logger.getLogger(LogScriptEngine.class); + + private ScriptEngineManager factory = new ScriptEngineManager(); + private ScriptEngine engine = factory.getEngineByName("JavaScript"); + + private Observer logObserver = null; + private Observer simObserver = null; + private Observer guiObserver = null; + + private GUI gui; + + private Observer scriptedLogObserver = null; + + private Observer scriptLogObserver = null; + + private String scriptCode; + + private interface ScriptLog { + public void log(String log); + } + + public LogScriptEngine(GUI gui, String code) { + this.gui = gui; + this.scriptCode = code; + + /* Create GUI observer: keeps track of new simulations */ + guiObserver = new Observer() { + public void update(Observable obs, Object obj) { + if (LogScriptEngine.this.gui.getSimulation() != null) { + LogScriptEngine.this.gui.getSimulation().addObserver(simObserver); + } + + registerLogObserver(); + } + }; + + /* Create simulation observer: keeps track of newly added nodes */ + simObserver = new Observer() { + public void update(Observable obs, Object obj) { + registerLogObserver(); + } + }; + + /* Create log observer: watches all log interfaces */ + logObserver = new Observer() { + public void update(Observable obs, Object obj) { + try { + if (scriptedLogObserver != null) { + scriptedLogObserver.update(obs, obj); + } + } catch (UndeclaredThrowableException e) { + JOptionPane.showMessageDialog(GUI.getTopParentContainer(), + e.getMessage(), + "Script error", JOptionPane.ERROR_MESSAGE); + unregisterLogObserver(); + } + } + }; + + /* Create script engine */ + try { + createScriptEngine(scriptCode); + } catch (ScriptException e) { + JOptionPane.showMessageDialog(GUI.getTopParentContainer(), + e.getMessage(), + "Script error", JOptionPane.ERROR_MESSAGE); + unregisterLogObserver(); + } + } + + public void setScriptLogObserver(Observer observer) { + scriptLogObserver = observer; + } + + private void unregisterLogObserver() { + /* Unregister mote log observer */ + if (logObserver != null && gui.getSimulation() != null) { + for (int i=0; i < gui.getSimulation().getMotesCount(); i++) { + Mote mote = gui.getSimulation().getMote(i); + if (mote.getInterfaces().getLog() != null) { + mote.getInterfaces().getLog().deleteObserver(logObserver); + } + } + } + } + + private void registerLogObserver() { + /* Register mote log observer */ + if (logObserver != null && gui.getSimulation() != null) { + for (int i=0; i < gui.getSimulation().getMotesCount(); i++) { + Mote mote = gui.getSimulation().getMote(i); + if (mote.getInterfaces().getLog() != null) { + mote.getInterfaces().getLog().addObserver(logObserver); + } + } + } + } + + /** + * Activate script + */ + public void activateScript() { + gui.addObserver(guiObserver); + + if (gui.getSimulation() != null) { + gui.getSimulation().addObserver(simObserver); + } + + registerLogObserver(); + } + + /** + * Deactivate script + */ + public void deactiveScript() { + gui.deleteObserver(guiObserver); + + if (gui.getSimulation() != null) { + gui.getSimulation().deleteObserver(simObserver); + } + + unregisterLogObserver(); + } + + private void createScriptEngine(String code) throws ScriptException { + engine.eval("function update(obs, obj) { " + + "if (obj != null) {" + + " mote = obj;" + + " id = mote.getInterfaces().getMoteID().getMoteID();" + + " msg = mote.getInterfaces().getLog().getLastLogMessages();" + + "} else {" + + " return;" + + "} " + + code + + " };"); + + Invocable inv = (Invocable) engine; + scriptedLogObserver = inv.getInterface(Observer.class); + + /* Create script logger */ + engine.put("log", new ScriptLog() { + public void log(String msg) { + if (scriptLogObserver != null) { + scriptLogObserver.update(null, msg); + } + } + }); + + /* TODO Test script */ + logObserver.update(null, null); + } + +} diff --git a/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java new file mode 100644 index 000000000..a3aff34ff --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/plugins/ScriptRunner.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2008, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ScriptRunner.java,v 1.1 2008/04/22 10:12:16 fros4943 Exp $ + */ + +package se.sics.cooja.plugins; + +import java.awt.BorderLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.*; +import javax.swing.*; +import org.apache.log4j.Logger; +import org.jdom.Element; + +import se.sics.cooja.*; + +@ClassDescription("Script Runner (Log)") +@PluginType(PluginType.COOJA_PLUGIN) +public class ScriptRunner extends VisPlugin { + private static final long serialVersionUID = 1L; + private static Logger logger = Logger.getLogger(ScriptRunner.class); + + private JTextArea scriptTextArea; + private JTextArea logTextArea; + + private GUI gui; + + private LogScriptEngine scriptTester = null; + + private JButton toggleButton; + + public ScriptRunner(GUI gui) { + super("Script Runner (Log)", gui); + this.gui = gui; + + scriptTextArea = new JTextArea(8,50); + scriptTextArea.setMargin(new Insets(5,5,5,5)); + scriptTextArea.setEditable(true); + scriptTextArea.setCursor(null); + scriptTextArea.setText("log.log('ID=' + id + ': ' + msg);"); + + logTextArea = new JTextArea(8,50); + logTextArea.setMargin(new Insets(5,5,5,5)); + logTextArea.setEditable(false); + logTextArea.setCursor(null); + + toggleButton = new JButton("Activate"); + toggleButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + if (toggleButton.getText().equals("Activate")) { + scriptTester = new LogScriptEngine(ScriptRunner.this.gui, scriptTextArea.getText()); + scriptTester.activateScript(); + scriptTester.setScriptLogObserver(new Observer() { + public void update(Observable obs, Object obj) { + logTextArea.append((String) obj); + } + }); + toggleButton.setText("Deactivate"); + scriptTextArea.setEnabled(false); + + } else { + if (scriptTester != null) { + scriptTester.deactiveScript(); + scriptTester = null; + } + toggleButton.setText("Activate"); + scriptTextArea.setEnabled(true); + } + } + }); + + JPanel centerPanel = new JPanel(new BorderLayout()); + centerPanel.add(BorderLayout.CENTER, new JScrollPane(scriptTextArea)); + centerPanel.add(BorderLayout.SOUTH, new JScrollPane(logTextArea)); + + JPanel buttonPanel = new JPanel(new BorderLayout()); + buttonPanel.add(BorderLayout.EAST, toggleButton); + + getContentPane().add(BorderLayout.CENTER, centerPanel); + getContentPane().add(BorderLayout.SOUTH, buttonPanel); + + pack(); + + try { + setSelected(true); + } catch (java.beans.PropertyVetoException e) { + // Could not select + } + } + + public void closePlugin() { + if (scriptTester != null) { + scriptTester.deactiveScript(); + scriptTester.setScriptLogObserver(null); + } + } + + public Collection getConfigXML() { + return null; + } + + public boolean setConfigXML(Collection configXML, boolean visAvailable) { + return true; + } + +}