/* * Copyright (c) 2007, 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: XMLCommandHandler.java,v 1.1 2007/08/21 14:39:58 fros4943 Exp $ */ package se.sics.chakana; import java.io.File; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Collection; import javax.swing.JFrame; import javax.swing.JInternalFrame; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import se.sics.chakana.EventpointEvaluator.EventpointException; import se.sics.chakana.eventpoints.*; import se.sics.cooja.AddressMemory; import se.sics.cooja.CoreComm; import se.sics.cooja.GUI; import se.sics.cooja.Mote; import se.sics.cooja.MoteMemory; import se.sics.cooja.RadioMedium; import se.sics.cooja.Simulation; import se.sics.cooja.Mote.State; import se.sics.cooja.MoteType.MoteTypeCreationException; import se.sics.cooja.dialogs.MessageList; import se.sics.cooja.plugins.VisState; import se.sics.cooja.plugins.Visualizer2D; import se.sics.cooja.radiomediums.UDGM; /** * Handles incoming XML commands. * Each command handling call blocks during handling and returns a reply to the client. * * A command must always be of the form: * ... * * @author Fredrik Osterlind */ public class XMLCommandHandler { public static final boolean DEBUG_OUTPUT = true; private static Logger logger = Logger.getLogger(XMLCommandHandler.class); public static final String XML_OK = ""; public static final String XML_OK_START = ""; public static final String XML_OK_END = ""; public static final String XML_INFO_START = ""; public static final String XML_INFO_END = ""; public static final String XML_ERROR_START = ""; public static final String XML_ERROR_END = ""; public static final String XML_COMMAND_NAME = "command"; public static final String XML_COMMAND_END = ""; public static final String XML_EVENTPOINT_START = ""; public static final String XML_EVENTPOINT_END = ""; public static final String XML_ID_NAME = "id"; public static final String XML_TYPE_NAME = "type"; public static final String XML_MOTE_NAME = "mote"; public static final String XML_VARIABLE_NAME = "variable"; public static final String XML_MOTECOUNT_NAME = "motecount"; public static final String XML_VALUE_NAME = "value"; public static final String XML_TIME_NAME = "time"; public static final String XML_SIZE_NAME = "size"; public static final String XML_ADDRESS_NAME = "address"; public static final String XML_VISIBLE_NAME = "visible"; public static final String XML_TRIGGERON_NAME = "triggeron"; public static final String XML_WATCHPOINT_INT = "int"; public static final String XML_WATCHPOINT_VARIABLE = "variable"; public static final String XML_WATCHPOINT_ADDRESS = "address"; public static final String XML_TIMEPOINT_SIMULATION = "time"; public static final String XML_TIMEPOINT_REAL = "realtime"; public static final String XML_EVENTPOINT_RADIOMEDIUM = "radiomedium"; private GUI myGUI; private EventpointEvaluator myEvaluator; private ChakanaPlugin myParent; public enum Command { CREATE_SIM, CONF_SIM, CONF_PLUGINS, CONTROL_SIM, SET_GUI, ADD_EVENTPOINT, READ_MEMORY, WRITE_MEMORY, CLEAR_EVENTPOINTS, DELETE_EVENTPOINT, KILL_NODES, GET_INFO, CUSTOM_COMMAND, EXIT_COOJA; } public enum ControlSimulationCommand { RESUME; } /** * TODO Document * * @param gui * @param parent * @param evaluator */ public XMLCommandHandler(GUI gui, ChakanaPlugin parent, EventpointEvaluator evaluator) { myGUI = gui; myEvaluator = evaluator; myParent = parent; } /** * @param command * @return */ public boolean containsEntireCommand(String command) { return command.contains(XMLCommandHandler.XML_COMMAND_END); // TODO Ugly trick } /** * Handle given command (XML format). * Method blocks until given command has been handled. * * @param command * Command to handle * @return Reply to client in XML format */ public String handleCommand(String command) { try { SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(new StringReader(command)); Element root = doc.getRootElement(); if (!root.getName().equals(XML_COMMAND_NAME)) { return createErrorMessage("Malformed command: " + root.getName()); } String cmdTypeString = root.getAttributeValue("value"); Command cmdType; try { cmdType = Command.valueOf(cmdTypeString); } catch (IllegalArgumentException e) { return createErrorMessage("Unknown command: " + cmdTypeString); } Collection cmdInfo = root.getChildren(); logger.debug("Command type: " + cmdType); switch (cmdType) { case CREATE_SIM: return createSimulation(cmdInfo); case CONF_SIM: return configureSimulation(cmdInfo); case CONF_PLUGINS: return configurePlugins(cmdInfo); case CONTROL_SIM: return controlSimulation(cmdInfo); case ADD_EVENTPOINT: return addEventpoint(cmdInfo); case SET_GUI: return configureGUI(cmdInfo); case READ_MEMORY: return readMemory(cmdInfo); case WRITE_MEMORY: return writeMemory(cmdInfo); case CLEAR_EVENTPOINTS: return clearEventpoints(); case DELETE_EVENTPOINT: return deleteEventpoint(cmdInfo); case KILL_NODES: return killNodes(cmdInfo); case GET_INFO: return getInfo(cmdInfo); case CUSTOM_COMMAND: return handleCustomCommand(cmdInfo); case EXIT_COOJA: return shutdownCOOJA(cmdInfo); default: return createErrorMessage("Unknown command: " + cmdType); } } catch (JDOMException e) { logger.fatal("Command parsing exception: " + e); return createErrorMessage("Invalid command syntax: " + e.getMessage()); } catch (IOException e) { logger.fatal("Command parsing exception: " + e); return createErrorMessage("Invalid command syntax: " + e.getMessage()); } } /** * Handle create new simulation command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String createSimulation(Collection arguments) { Simulation simulation = new Simulation(myGUI); simulation.setTitle("[chakana - no title]"); simulation.setDelayTime(0); simulation.setSimulationTime(0); simulation.setTickTime(1); try { RadioMedium radioMedium = RadioMedium.generateRadioMedium(UDGM.class, simulation); simulation.setRadioMedium(radioMedium); } catch (Exception e) { return createErrorMessage("Create simulation: Could not create radio medium: " + e.getMessage()); } // Let simulation parse command arguments myGUI.setSimulation(simulation); try { boolean success = simulation.setConfigXML(arguments, false); } catch (Exception e) { logger.fatal("Error when configuring simulation: " + e); if (DEBUG_OUTPUT) { if (e instanceof MoteTypeCreationException) { MessageList compilationOutput = ((MoteTypeCreationException) e).getCompilationOutput(); if (compilationOutput != null) { logger.info("Compilation output:"); for(int i = 0; i < compilationOutput.getModel().getSize(); i++) { logger.info(compilationOutput.getModel().getElementAt(i)); } } StackTraceElement[] stackTrace = e.getStackTrace(); if (stackTrace != null) { logger.info("Stack trace:"); for(StackTraceElement element: stackTrace) { logger.info(element); } } GUI.showErrorDialog(new JFrame(""), "Set DEBUG_OUTPUT to false to disable this frame", e, false); // XXX Graphical component } } return createErrorMessage("Create simulation: Could not configure simulation: " + e.getMessage()); } return XML_OK; } /** * Handle configure simulation command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String configureSimulation(Collection arguments) { Simulation simulation = myGUI.getSimulation(); // Let simulation parse command arguments try { simulation.setConfigXML(arguments, false); } catch (Exception e) { logger.fatal("Error when configuring simulation: " + e); e.printStackTrace(); return createErrorMessage("Could not configure simulation: " + e.getMessage()); } return XML_OK; } /** * Handle configure plugins command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String configurePlugins(Collection arguments) { Simulation simulation = myGUI.getSimulation(); // Let GUI parse command arguments try { myGUI.setPluginsConfigXML(arguments, simulation, false); } catch (Exception e) { logger.fatal("Error when configuring plugins: " + e); return createErrorMessage("Could not configure plugins: " + e.getMessage()); } return XML_OK; } /** * Handle control simulation command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String controlSimulation(Collection arguments) { String reply = ""; for (Element element : arguments) { ControlSimulationCommand cmdType; try { cmdType = ControlSimulationCommand.valueOf(element.getName()); } catch (IllegalArgumentException e) { return createErrorMessage("Unknown simulation control command: " + element.getName()); } switch (cmdType) { case RESUME: // TODO Check performance degradation using try-blocks try { myEvaluator.resumeSimulation(); reply += createEventpointMessage(myEvaluator); } catch (EventpointException e) { return createErrorMessage("Exception during simulation: " + e); } break; default: return createErrorMessage("Unknown simulation control command"); } } return reply; } /** * Handle exit COOJA command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String shutdownCOOJA(Collection arguments) { myParent.performCOOJAShutdown(); logger.info("Shutdown requested"); return XML_OK; } /** * Fetch mote variable value as specified by arguments. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String readMemory(Collection arguments) { Simulation simulation = myGUI.getSimulation(); String type = null; String mote = null; String variable = null; String size = null; String address = null; for (Element element : arguments) { if (element.getName().equals(XML_TYPE_NAME)) { type = element.getText(); } else if (element.getName().equals(XML_MOTE_NAME)) { mote = element.getText(); } else if (element.getName().equals(XML_VARIABLE_NAME)) { variable = element.getText(); } else if (element.getName().equals(XML_SIZE_NAME)) { size = element.getText(); } else if (element.getName().equals(XML_ADDRESS_NAME)) { address = element.getText(); } else { return createErrorMessage("Unknown read memory parameter: " + element.getName()); } } if (type == null) return createErrorMessage("No read memory type specified"); if (mote == null) return createErrorMessage("No mote specified"); if (mote == null) return createErrorMessage("No mote ID specified"); int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } MoteMemory memory = simulation.getMote(moteNr).getMemory(); // Read integer variable if (type.equals("int")) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't read mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } int val = ((AddressMemory) memory).getIntValueOf(variable); return XML_OK_START + val + XML_OK_END; } else if (type.equals("variable")) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't read mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } byte[] val = ((AddressMemory) memory).getByteArray(variable, sizeParsed); String ret = ""; for (byte b: val) ret += (int) (0xff&b) + " "; ret = ret.trim(); return XML_OK_START + ret + XML_OK_END; } else if (type.equals("address")) { if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } int addressParsed = Integer.parseInt(address); if (addressParsed < 0) { return createErrorMessage("Bad start address specified: " + addressParsed); } byte[] val = memory.getMemorySegment(addressParsed, sizeParsed); String ret = ""; for (byte b: val) ret += (int) (0xff&b) + " "; ret = ret.trim(); return XML_OK_START + ret + XML_OK_END; } return createErrorMessage("Bad read memory type specified: " + type); } /** * Write mote variable value as specified by arguments. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String writeMemory(Collection arguments) { Simulation simulation = myGUI.getSimulation(); String type = null; String mote = null; String variable = null; String size = null; String address = null; String value = null; for (Element element : arguments) { if (element.getName().equals(XML_TYPE_NAME)) { type = element.getText(); } else if (element.getName().equals(XML_MOTE_NAME)) { mote = element.getText(); } else if (element.getName().equals(XML_VARIABLE_NAME)) { variable = element.getText(); } else if (element.getName().equals(XML_SIZE_NAME)) { size = element.getText(); } else if (element.getName().equals(XML_ADDRESS_NAME)) { address = element.getText(); } else if (element.getName().equals(XML_VALUE_NAME)) { value = element.getText(); } else { return createErrorMessage("Unknown write memory parameter: " + element.getName()); } } if (type == null) return createErrorMessage("No write memory type specified"); if (mote == null) return createErrorMessage("No mote specified"); if (mote == null) return createErrorMessage("No mote ID specified"); int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } MoteMemory memory = simulation.getMote(moteNr).getMemory(); // Write integer variable if (type.equals("int")) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't read mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } if (value == null) return createErrorMessage("No value specified"); if (value.contains(" ")) return createErrorMessage("Integer value must not contain spaces: " + value); int val; try { val = Integer.parseInt(value); } catch (NumberFormatException e) { return createErrorMessage("Bad integer value specified: " + e); } ((AddressMemory) memory).setIntValueOf(variable, val); return XML_OK; } else if (type.equals("variable")) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't read mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } if (value == null) return createErrorMessage("No value specified"); String[] bytesParsed = value.split(" "); if (bytesParsed.length != sizeParsed) return createErrorMessage("Number of bytes and specified size does not match: " + bytesParsed.length + "!=" + sizeParsed); byte[] val = new byte[bytesParsed.length]; for (int i=0; i < sizeParsed; i++) { val[i] = Byte.parseByte(bytesParsed[i]); } ((AddressMemory) memory).setByteArray(variable, val); return XML_OK; } else if (type.equals("address")) { if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } int addressParsed = Integer.parseInt(address); if (addressParsed < 0) { return createErrorMessage("Bad start address specified: " + addressParsed); } if (value == null) return createErrorMessage("No value specified"); String[] bytesParsed = value.split(" "); if (bytesParsed.length != sizeParsed) return createErrorMessage("Number of bytes and specified size does not match: " + bytesParsed.length + "!=" + sizeParsed); byte[] val = new byte[bytesParsed.length]; for (int i=0; i < sizeParsed; i++) { val[i] = Byte.parseByte(bytesParsed[i]); } memory.setMemorySegment(addressParsed, val); return XML_OK; } return createErrorMessage("Bad write memory type specified: " + type); } /** * Handle add new eventpoint command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String addEventpoint(Collection arguments) { Simulation simulation = myGUI.getSimulation(); String type = null; String mote = null; String variable = null; String time = null; String size = null; String triggeron = null; String address = null; String count = null; for (Element element : arguments) { if (element.getName().equals(XML_TYPE_NAME)) { type = element.getText(); } else if (element.getName().equals(XML_MOTE_NAME)) { mote = element.getText(); } else if (element.getName().equals(XML_VARIABLE_NAME)) { variable = element.getText(); } else if (element.getName().equals(XML_TIME_NAME)) { time = element.getText(); } else if (element.getName().equals(XML_SIZE_NAME)) { size = element.getText(); } else if (element.getName().equals(XML_ADDRESS_NAME)) { address = element.getText(); } else if (element.getName().equals(XML_TRIGGERON_NAME)) { triggeron = element.getText(); } else if (element.getName().equals("count")) { count = element.getText(); } else { return createErrorMessage("Unknown eventpoint parameter: " + element.getName()); } } logger.debug("Eventpoint type: " + type); if (type == null) return createErrorMessage("No eventpoint type specified"); // Integer variable watchpoint if (type.equals(XML_WATCHPOINT_INT)) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (mote == null) return createErrorMessage("No mote ID specified"); int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } Mote moteObject = simulation.getMote(moteNr); MoteMemory memory = simulation.getMote(moteNr).getMemory(); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't write mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } Eventpoint newEventpoint = new IntegerWatchpoint(moteObject, variable); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } // Variable watchpoint if (type.equals(XML_WATCHPOINT_VARIABLE)) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (mote == null) return createErrorMessage("No mote ID specified"); if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } Mote moteObject = simulation.getMote(moteNr); MoteMemory memory = simulation.getMote(moteNr).getMemory(); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't write mote memory variables (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } Eventpoint newEventpoint = new VariableWatchpoint(moteObject, variable, sizeParsed); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } // Memory area watchpoint if (type.equals(XML_WATCHPOINT_ADDRESS)) { if (mote == null) return createErrorMessage("No mote ID specified"); if (size == null) return createErrorMessage("No size specified"); int sizeParsed = Integer.parseInt(size); if (sizeParsed < 0) { return createErrorMessage("Bad size specified: " + sizeParsed); } int addressParsed = Integer.parseInt(address); if (addressParsed < 0) { return createErrorMessage("Bad start address specified: " + addressParsed); } int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } Mote moteObject = simulation.getMote(moteNr); MoteMemory memory = simulation.getMote(moteNr).getMemory(); Eventpoint newEventpoint = new Watchpoint(moteObject, addressParsed, sizeParsed); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } // Simulation timepoint if (type.equals(XML_TIMEPOINT_SIMULATION)) { if (time == null) return createErrorMessage("No time specified"); int timeParsed = Integer.parseInt(time); if (timeParsed < 0) { return createErrorMessage("Bad time specified: " + timeParsed); } Eventpoint newEventpoint = new SimulationTimepoint(simulation, timeParsed); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } // Real timepoint if (type.equals(XML_TIMEPOINT_REAL)) { if (time == null) return createErrorMessage("No time specified"); long timeParsed = Long.parseLong(time); if (timeParsed < 0) { return createErrorMessage("Bad time specified: " + timeParsed); } Eventpoint newEventpoint = new RealTimepoint(timeParsed); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } // Radio medium event point if (type.equals(XML_EVENTPOINT_RADIOMEDIUM)) { int countInt; try { countInt = Integer.parseInt(count); } catch (NumberFormatException e) { return createErrorMessage("Bad count specified: " + e); } if (triggeron == null || triggeron.equals("all")) { Eventpoint newEventpoint = new RadioMediumEventpoint(simulation.getRadioMedium(), countInt); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } else if (triggeron.equals("completed")) { Eventpoint newEventpoint = new TransmissionRadioMediumEventpoint(simulation.getRadioMedium(), countInt); myEvaluator.addEventpoint(newEventpoint); return createOkMessage(newEventpoint, simulation.getSimulationTime()); } else { return createErrorMessage("Bad trigger on parameter: " + triggeron); } } return createErrorMessage("Bad eventpoint type specified: " + type); } /** * Handle configure GUI command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String configureGUI(Collection arguments) { String visible = null; for (Element element : arguments) { if (element.getName().equals(XML_VISIBLE_NAME)) { visible = element.getText(); } else { return createErrorMessage("Unknown GUI configure parameter: " + element.getName()); } } boolean shouldBeVisible = Boolean.parseBoolean(visible); if (myGUI.isVisualized() != shouldBeVisible) { myGUI.setVisualized(shouldBeVisible); } return XML_OK; } /** * Handle delete eventpoint command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String deleteEventpoint(Collection arguments) { String id = null; for (Element element : arguments) { if (element.getName().equals(XML_ID_NAME)) { id = element.getText(); } else { return createErrorMessage("Unknown eventpoint parameter: " + element.getName()); } } int idInt; try { idInt = Integer.parseInt(id); } catch (NumberFormatException e) { return createErrorMessage("Bad eventpoint ID specified: " + e); } Eventpoint eventpoint = myEvaluator.getEventpoint(idInt); if (eventpoint == null) return createErrorMessage("No eventpoint with ID " + idInt + " exists"); myEvaluator.deleteEventpoint(idInt); return XML_OK; } /** * Handle kill nodes command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String killNodes(Collection arguments) { String lowId = null; String highId = null; for (Element element : arguments) { if (element.getName().equals("lowmote")) { lowId = element.getText(); } else if (element.getName().equals("highmote")) { highId = element.getText(); } else { return createErrorMessage("Unknown eventpoint parameter: " + element.getName()); } } int lowIdInt; int highIdInt; try { lowIdInt = Integer.parseInt(lowId); highIdInt = Integer.parseInt(highId); } catch (NumberFormatException e) { return createErrorMessage("Bad mote interval specified: " + e); } if (lowIdInt > highIdInt) return createErrorMessage("Bad mote interval specified: Low ID must be <= than high ID"); if (lowIdInt < 0) return createErrorMessage("Bad mote interval specified: Low ID >= 0"); if (myGUI.getSimulation() == null) return createErrorMessage("No simulation exists"); if (myGUI.getSimulation().getMotesCount() < highIdInt) return createErrorMessage("Bad mote interval specified: Only " + myGUI.getSimulation().getMotesCount() + " motes exist"); for (int pos=lowIdInt; pos <= highIdInt; pos++) { Mote mote = myGUI.getSimulation().getMote(pos); mote.setState(State.DEAD); } return XML_OK; } /** * Handle get info command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String getInfo(Collection arguments) { Simulation simulation = myGUI.getSimulation(); String type = null; String mote = null; String variable = null; for (Element element : arguments) { if (element.getName().equals(XML_TYPE_NAME)) { type = element.getText(); } else if (element.getName().equals(XML_MOTE_NAME)) { mote = element.getText(); } else if (element.getName().equals(XML_VARIABLE_NAME)) { variable = element.getText(); } else { return createErrorMessage("Unknown info parameter: " + element.getName()); } } if (type.equals("motestate")) { if (mote == null) return createErrorMessage("No mote ID specified"); int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } State state = simulation.getMote(moteNr).getState(); if (state == State.DEAD) return XML_OK_START + 0 + XML_OK_END; return XML_OK_START + 1 + XML_OK_END; } else if (type.equals("time")) { return XML_OK_START + myGUI.getSimulation().getSimulationTime() + XML_OK_END; } else if (type.equals(XML_MOTECOUNT_NAME)) { return XML_OK_START + myGUI.getSimulation().getMotesCount() + XML_OK_END; } else if (type.equals("var_address")) { if (variable == null) return createErrorMessage("No variable name specified"); if (variable.contains(" ")) return createErrorMessage("Variable name must not contain spaces: " + variable); if (mote == null) return createErrorMessage("No mote ID specified"); int moteNr = Integer.parseInt(mote); if (moteNr < 0 || simulation.getMotesCount() <= moteNr) { return createErrorMessage("Bad mote ID specified: " + moteNr); } Mote moteObject = simulation.getMote(moteNr); MoteMemory memory = simulation.getMote(moteNr).getMemory(); if (!(memory instanceof AddressMemory)) return createErrorMessage("Can't read mote memory variable address (not address memory)"); if (!((AddressMemory) memory).variableExists(variable)) { return createErrorMessage("Variable does not exist: " + variable); } int address = ((AddressMemory) memory).getVariableAddress(variable); return XML_OK_START + address + XML_OK_END; } return createErrorMessage("Unknown type: " + type); } /** * Handle custom command. * * @param arguments Command arguments * @return Reply to client (XML format) */ private String handleCustomCommand(Collection arguments) { Simulation simulation = myGUI.getSimulation(); String action = null; int id = -1; int visible = -1; int hide = -1; for (Element element : arguments) { if (element.getName().equals("action")) { action = element.getText(); } else if (element.getName().equals("id")) { String idString = element.getText(); id = Integer.parseInt(idString); } else if (element.getName().equals("hide")) { String hideString = element.getText(); hide = Integer.parseInt(hideString); } else if (element.getName().equals("visible")) { String visibleString = element.getText(); visible = Integer.parseInt(visibleString); } else { return createErrorMessage("Unknown info parameter: " + element.getName()); } } if (action.equals("CLICK_SINK")) { simulation.getMote(0).getInterfaces().getButton().clickButton(); return XML_OK; } if (action.equals("SHOW_FIRE")) { if (!simulation.getGUI().isVisualized()) return XML_OK; JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames(); try { Class pluginClass = (Class) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis"); Class[] parameterTypes = new Class[1]; parameterTypes[0] = Boolean.TYPE; Method method = pluginClass.getMethod("showFire", parameterTypes); Object[] parameterArguments = new Object[1]; parameterArguments[0] = new Boolean(visible==1?true:false); for (JInternalFrame plugin: allPlugins) { if (plugin.getClass() == pluginClass) { method.invoke(plugin, parameterArguments); } } } catch (Exception e) { return createErrorMessage("Exception: " + e.getMessage()); } return XML_OK; } if (action.equals("RESET_COLORS")) { if (!simulation.getGUI().isVisualized()) return XML_OK; JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames(); try { Class pluginClass = (Class) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis"); Class[] parameterTypes = new Class[0]; Method method = pluginClass.getMethod("resetColors", parameterTypes); Object[] parameterArguments = new Object[0]; for (JInternalFrame plugin: allPlugins) { if (plugin.getClass() == pluginClass) { method.invoke(plugin, parameterArguments); } } } catch (Exception e) { return createErrorMessage("Exception: " + e.getMessage()); } return XML_OK; } if (action.equals("SHOW_TRUCK")) { if (!simulation.getGUI().isVisualized()) return XML_OK; JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames(); try { Class pluginClass = (Class) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis"); if (hide == 0) { Class[] parameterTypes = new Class[0]; Method method = pluginClass.getMethod("showTruck", parameterTypes); Object[] parameterArguments = new Object[0]; for (JInternalFrame plugin: allPlugins) { if (plugin.getClass() == pluginClass) { method.invoke(plugin, parameterArguments); } } } else { Class[] parameterTypes = new Class[0]; Method method = pluginClass.getMethod("hideTruck", parameterTypes); Object[] parameterArguments = new Object[0]; for (JInternalFrame plugin: allPlugins) { if (plugin.getClass() == pluginClass) { method.invoke(plugin, parameterArguments); } } } } catch (Exception e) { return createErrorMessage("Exception: " + e.getMessage()); } return XML_OK; } if (action.equals("INDICATE_MOTE")) { if (!simulation.getGUI().isVisualized()) return XML_OK; JInternalFrame[] allPlugins = simulation.getGUI().getDesktopPane().getAllFrames(); try { Class pluginClass = (Class) simulation.getGUI().tryLoadClass(this, Visualizer2D.class, "se.sics.runes.RunesVis"); Class[] parameterTypes = new Class[1]; parameterTypes[0] = Integer.TYPE; Method method = pluginClass.getMethod("indicateMote", parameterTypes); Object[] parameterArguments = new Object[1]; parameterArguments[0] = new Integer(id); for (JInternalFrame plugin: allPlugins) { if (plugin.getClass() == pluginClass) { method.invoke(plugin, parameterArguments); } } } catch (Exception e) { return createErrorMessage("Exception: " + e.getMessage()); } return XML_OK; } return createErrorMessage("Unknown action: " + action); } /** * Handle clear eventpoints command. * * @return Reply to client (XML format) */ private String clearEventpoints() { myEvaluator.clearAllEventpoints(); return XML_OK; } public static String createErrorMessage(String message) { return XML_ERROR_START + message + XML_ERROR_END; } public static String createInfoMessage(String message) { return XML_INFO_START + message + XML_INFO_END; } public static String createOkMessage(Eventpoint eventpoint, int time) { return XML_OK_START + eventpoint.getID() + XML_OK_END; } public static String createEventpointMessage(EventpointEvaluator evaluator) { return XML_EVENTPOINT_START + evaluator.getLastTriggeredEventpointID() + XML_INFO_START + evaluator.getTriggeredEventpoint().getMessage() + XML_INFO_END + XML_EVENTPOINT_END; } }