diff --git a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java index 6e4323650..0a22206a5 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Swedish Institute of Computer Science. + * Copyright (c) 2012, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.regex.PatternSyntaxException; @@ -85,27 +86,26 @@ import javax.swing.table.TableRowSorter; import org.apache.log4j.Logger; import org.jdom.Element; -import se.sics.cooja.AddressMemory; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; import se.sics.cooja.Mote; +import se.sics.cooja.MoteMemory; +import se.sics.cooja.MoteMemory.MemoryEventType; import se.sics.cooja.Plugin; import se.sics.cooja.PluginType; import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.Simulation; +import se.sics.cooja.TimeEvent; import se.sics.cooja.VisPlugin; import se.sics.cooja.dialogs.TableColumnAdjuster; import se.sics.cooja.dialogs.UpdateAggregator; import se.sics.cooja.interfaces.IPAddress; import se.sics.cooja.motes.AbstractEmulatedMote; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryEventHandler; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryEventType; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryMonitor; import se.sics.cooja.util.ArrayQueue; import se.sics.cooja.util.StringUtils; /** - * @author Fredrik Osterlind + * @author Fredrik Osterlind, Niclas Finne */ @ClassDescription("Buffer Listener") @PluginType(PluginType.SIM_PLUGIN) @@ -156,10 +156,11 @@ public class BufferListener extends VisPlugin { registerBufferType(NodeIDBuffer.class); registerBufferType(Queuebuf0Buffer.class); /* TODO Add buffers: Queuebuf(1,2,3,4,..). */ - registerBufferType(CustomVariableBuffer.class); /* Special buffer: Custom Variable */ - registerBufferType(CustomPointerBuffer.class); /* Special buffer: Custom Pointer */ + registerBufferType(CustomVariableBuffer.class); + registerBufferType(CustomIntegerBuffer.class); + registerBufferType(CustomPointerBuffer.class); } - + private Parser parser = null; private Buffer buffer = null; public void startPlugin() { @@ -168,7 +169,12 @@ public class BufferListener extends VisPlugin { setParser(ByteArrayParser.class); } if (buffer == null) { - setBuffer(PacketbufBuffer.class); + Buffer b = createBufferInstance(PacketbufBuffer.class); + if (b != null) { + if (b.configure(BufferListener.this)) { + setBuffer(b); + } + } } } @@ -197,58 +203,21 @@ public class BufferListener extends VisPlugin { private boolean hideReads = true; private JCheckBoxMenuItem hideReadsCheckbox; - + private boolean withStackTrace = false; private JCheckBoxMenuItem withStackTraceCheckbox; - - private JMenu parserMenu = new JMenu("Parser"); - private JMenu bufferMenu = new JMenu("Buffer"); - - private ArrayList monitoredMotes = new ArrayList(); - private ArrayList monitoredMemories = new ArrayList(); - private MemoryEventHandler meh = new MemoryEventHandler() { - public void event(MemoryMonitor mm, MemoryEventType type, int adr, int data) { - MemoryMonitor observedMemory = null; - - if (mm.isPointer()) { - /* Stop observing pointed memory */ - observedMemory = mm.getPointedMemory(); - if (observedMemory == null) { - logger.fatal("No reference to pointed memory!"); - } else { - observedMemory.stop(); - monitoredMemories.remove(observedMemory); - } - /* Restart observing pointed memory */ - observedMemory = startObservingMemory( - (AbstractEmulatedMote) observedMemory.getMote(), - buffer.getAddress(observedMemory.getMote()), - buffer.getSize(observedMemory.getMote()) - ); - mm.setPointer(true, observedMemory); - } else { - observedMemory = mm; - } - - /* Display memory event */ - if (!hasHours && simulation.getSimulationTime() > TIME_HOUR) { - hasHours = true; - repaintTimeColumn(); - } - - BufferAccess previous = null; - previous = mm.getLastBufferAccess(); - BufferAccess current = new BufferAccess( - simulation.getSimulationTime(), - observedMemory, - type, - adr, /* XXX May be wrong if pointer, remove these */ - data, - previous - ); - logUpdateAggregator.add(current); - mm.setLastBufferAccess(current); + private JMenu bufferMenu = new JMenu("Buffer"); + private JMenu parserMenu = new JMenu("Show as"); + + private ArrayList motes = new ArrayList(); + private ArrayList memoryMonitors = new ArrayList(); + + private TimeEvent hourTimeEvent = new TimeEvent(0) { + public void execute(long t) { + hasHours = true; + repaintTimeColumn(); + hourTimeEvent = null; } }; @@ -298,6 +267,13 @@ public class BufferListener extends VisPlugin { super("Buffer Listener - " + "?" + " motes", gui); this.simulation = simulation; + if (simulation.getSimulationTime() > TIME_HOUR) { + hasHours = true; + hourTimeEvent = null; + } else { + simulation.scheduleEvent(hourTimeEvent, TIME_HOUR); + } + model = new AbstractTableModel() { private static final long serialVersionUID = 3065150390849332924L; public String getColumnName(int col) { @@ -315,13 +291,13 @@ public class BufferListener extends VisPlugin { public Object getValueAt(int row, int col) { BufferAccess log = logs.get(row); if (col == COLUMN_TIME) { - return log.getTime(); + return log.getTime(formatTimeString, hasHours); } else if (col == COLUMN_FROM) { return log.getID(); } else if (col == COLUMN_TYPE) { return log.getType(); } else if (col == COLUMN_DATA) { - return log.getParsedData(); + return parser.parse(log); } else if (col == COLUMN_SOURCE) { return log.getSource(); } @@ -343,7 +319,7 @@ public class BufferListener extends VisPlugin { if (row < 0 || column < 0) { return super.getToolTipText(e); } - + if (column == COLUMN_SOURCE) { BufferAccess ba = logs.get(row); if (ba.stackTrace != null) { @@ -356,21 +332,11 @@ public class BufferListener extends VisPlugin { } if (column == COLUMN_DATA) { BufferAccess ba = logs.get(row); - if (parser instanceof GraphicalParser) { - return - "
" +
-            StringUtils.hexDump(ba.mem, 4, 4) +
-            "
"; - } - - String baString = ba.getParsedString(); - StringBuilder sb = new StringBuilder(); - sb.append(""); - while (baString.length() > 60) { - sb.append(baString.substring(0, 60)).append("
"); - baString = baString.substring(60); - }; - return sb.append(baString).append("").toString(); + return + "
" +
+          "Address: " + (ba.address==0?"null":String.format("%04x\n", ba.address)) +
+          StringUtils.hexDump(ba.mem, 4, 4) +
+          "
"; } return super.getToolTipText(e); @@ -417,7 +383,7 @@ public class BufferListener extends VisPlugin { if (isSelected) { bgColor = table.getSelectionBackground(); } - + if (value instanceof BufferAccess && parser instanceof GraphicalParser) { graphicalParserPanel.update((BufferAccess) value, (GraphicalParser)parser); graphicalParserPanel.setBackground(bgColor); @@ -425,7 +391,7 @@ public class BufferListener extends VisPlugin { } else { setBackground(bgColor); } - + return super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); } @@ -593,7 +559,7 @@ public class BufferListener extends VisPlugin { repaint(); } }); - + logTable.setComponentPopupMenu(popupMenu); /* Column width adjustment */ @@ -609,7 +575,11 @@ public class BufferListener extends VisPlugin { simulation.getEventCentral().addMoteCountListener(logOutputListener = new MoteCountListener() { public void moteWasAdded(Mote mote) { /* Update title */ - startObserving(mote); + try { + startMonitoring(mote); + } catch (Exception e) { + logger.warn("Could not monitor buffer on: " + mote, e); + } } public void moteWasRemoved(Mote mote) { /* Update title */ @@ -660,75 +630,151 @@ public class BufferListener extends VisPlugin { setLocation(0, gui.getDesktopPane().getHeight() - 300); } - private boolean startObserving(Mote mote) { - if (!(mote instanceof AbstractEmulatedMote)) { - logger.fatal("Failed creating memory monitor: wrong mote type"); - return false; - } - AbstractEmulatedMote am = (AbstractEmulatedMote) mote; - if (!(am.getMemory() instanceof AddressMemory)) { - logger.fatal("Failed creating memory monitor: wrong memory type"); - return false; - } - + private boolean startMonitoring(Mote mote) throws Exception { /* If this is a pointer buffer, * we must observe both the pointer itself, and the pointed to memory */ - int address = buffer.getAddress(am); - int size = buffer.getSize(am); - if (address < 0 || size < 0 || size > MAX_BUFFER_SIZE) { - logger.fatal("Failed start observing memory: bad addr/size: " + address + "/" + size); - return false; - } - - MemoryMonitor mm = startObservingMemory(am, address, size); - if (mm == null) { - return false; - } - boolean pointer = (buffer instanceof PointerBuffer); - if (pointer) { - int pointerAddress = ((PointerBuffer)buffer).getPointerAddress(am); - /* Whenever the pointer changes, we re-register this observation */ - MemoryMonitor pointerMM = startObservingMemory(am, pointerAddress, 2); - pointerMM.setPointer(true, mm); - } - return true; - } - private MemoryMonitor startObservingMemory(AbstractEmulatedMote mote, int address, int size) { - MemoryMonitor mm = mote.createMemoryMonitor(meh); - if (mm == null) { - logger.fatal("Failed creating memory monitor: not implemented"); - return null; - } - - boolean started = mm.start(address, size); - if (!started) { - logger.fatal("Failed creating memory monitor: could not start monitor"); - return null; - } - - monitoredMemories.add(mm); - /* TODO Don't keep pointed memories in this list. - * Instead automatically unregister them from their parent memories. */ - if (!monitoredMotes.contains(mote)) { - monitoredMotes.add(mote); + SegmentMemoryMonitor mm = buffer.createMemoryMonitor(this, mote); + memoryMonitors.add(mm); + if (!motes.contains(mote)) { + motes.add(mote); } updateTitle(); - return mm; + return true; } - private void stopObserving(Mote mote) { - if (!(mote instanceof AbstractEmulatedMote)) { - return; + + public enum MemoryMonitorType { SEGMENT, POINTER, CONSTPOINTER }; + + static class PointerMemoryMonitor extends SegmentMemoryMonitor { + private SegmentMemoryMonitor segmentMonitor = null; + private int lastSegmentAddress = -1; + private final int pointerAddress; + private final int pointerSize; + + public PointerMemoryMonitor( + BufferListener bl, Mote mote, + int pointerAddress, int pointerSize, int segmentSize) + throws Exception { + super(bl, mote, pointerAddress, pointerSize); + this.pointerAddress = pointerAddress; + this.pointerSize = pointerSize; + + registerSegmentMonitor(segmentSize, false); } - for (MemoryMonitor mm: monitoredMemories.toArray(new MemoryMonitor[0])) { - if (mm.getMote() == mote) { - mm.stop(); - monitoredMemories.remove(mm); + private void registerSegmentMonitor(int size, boolean notify) throws Exception { + byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize); + int segmentAddress = mote.getMemory().parseInt(pointerValue); + + segmentMonitor = new SegmentMemoryMonitor(bl, mote, segmentAddress, size); + if (notify) { + segmentMonitor.memoryChanged(mote.getMemory(), MemoryEventType.WRITE, -1); + } + lastSegmentAddress = segmentAddress; + } + + final public void memoryChanged(MoteMemory memory, + se.sics.cooja.MoteMemory.MemoryEventType type, int address) { + if (type == MemoryEventType.READ) { + return; + } + + byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize); + int segmentAddress = mote.getMemory().parseInt(pointerValue); + if (segmentAddress == lastSegmentAddress) { + return; + } + + /* Pointer changed - we need to create new segment monitor */ + segmentMonitor.dispose(); + try { + registerSegmentMonitor(segmentMonitor.getSize(), true); + } catch (Exception e) { + logger.warn("Could not re-register memory monitor on: " + mote, e); } } - monitoredMotes.remove(mote); + public MemoryMonitorType getType() { + return MemoryMonitorType.POINTER; + } + + public void dispose() { + super.dispose(); + segmentMonitor.dispose(); + } + } + + static class SegmentMemoryMonitor implements se.sics.cooja.MoteMemory.MemoryMonitor { + protected final BufferListener bl; + protected final Mote mote; + + private final int address; + private final int size; + + private byte[] oldData = null; + + public SegmentMemoryMonitor(BufferListener bl, Mote mote, int address, int size) + throws Exception { + this.bl = bl; + this.mote = mote; + this.address = address; + this.size = size; + + if (address != 0) { + if (!mote.getMemory().addMemoryMonitor(address, size, this)) { + throw new Exception("Could not register memory monitor on: " + mote); + } + } + } + + public Mote getMote() { + return mote; + } + public int getAddress() { + return address; + } + public int getSize() { + return size; + } + public MemoryMonitorType getType() { + return MemoryMonitorType.SEGMENT; + } + + public void dispose() { + if (address != 0) { + mote.getMemory().removeMemoryMonitor(address, size, this); + } + } + + public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) { + byte[] newData = getAddress()==0?null:mote.getMemory().getMemorySegment(getAddress(), getSize()); + addBufferAccess(bl, mote, oldData, newData, type, this.address); + oldData = newData; + } + + void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, MemoryEventType type, int address) { + BufferAccess ba = new BufferAccess( + mote, + mote.getSimulation().getSimulationTime(), + address, + newData, + oldData, + type, + bl.withStackTrace + ); + bl.logUpdateAggregator.add(ba); + } + } + + private void stopObserving(Mote mote) { + for (SegmentMemoryMonitor mm: memoryMonitors.toArray(new SegmentMemoryMonitor[0])) { + if (mm.getMote() == mote) { + mm.dispose(); + memoryMonitors.remove(mm); + } + } + + motes.remove(mote); updateTitle(); } @@ -740,37 +786,16 @@ public class BufferListener extends VisPlugin { private void updateTitle() { if (buffer != null) { - String bufferDesc = GUI.getDescriptionOf(buffer); - /* Special buffer: Custom Variable/Custom Pointer */ - if (buffer.getClass() == CustomVariableBuffer.class) { - int offset = ((CustomVariableBuffer)buffer).getOffset(); - if (offset > 0) { - bufferDesc = "&" + ((CustomVariableBuffer)buffer).getVariable() + "[" + offset + "] (" + ((CustomVariableBuffer)buffer).getSize() + ")"; - } else { - bufferDesc = ((CustomVariableBuffer)buffer).getVariable() + " (" + ((CustomVariableBuffer)buffer).getSize() + ")"; - } - } else if (buffer.getClass() == CustomPointerBuffer.class) { - int offset = ((CustomPointerBuffer)buffer).getOffset(); - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + " (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - if (offset > 0) { - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + "[" + offset + "] (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - } else { - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + " (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - } - } - - int count=0; - for (MemoryMonitor mm: monitoredMemories) { - if (mm.isPointer()) continue; - count++; - } + String status = buffer.getStatusString(); setTitle("Buffer Listener - " + - bufferDesc + " - " + - count + " buffers on " + monitoredMotes.size() + " motes"); + ((status!=null)?status:GUI.getDescriptionOf(buffer)) + " " + + "- " + memoryMonitors.size() + " buffers on " + motes.size() + " motes"); } } public void closePlugin() { + if (hourTimeEvent != null) hourTimeEvent.remove(); + /* Stop observing motes */ logUpdateAggregator.stop(); simulation.getEventCentral().removeMoteCountListener(logOutputListener); @@ -814,18 +839,9 @@ public class BufferListener extends VisPlugin { element = new Element("buffer"); element.setText(buffer.getClass().getName()); - /* Special buffer: Custom Variable/Custom Pointer */ - if (buffer.getClass() == CustomVariableBuffer.class) { - element.setAttribute("variable", ((CustomVariableBuffer) buffer).getVariable()); - element.setAttribute("size", "" + ((CustomVariableBuffer) buffer).getSize()); - element.setAttribute("offset", "" + ((CustomVariableBuffer) buffer).getOffset()); - } else if (buffer.getClass() == CustomPointerBuffer.class) { - element.setAttribute("variable", ((CustomPointerBuffer) buffer).getVariable()); - element.setAttribute("size", "" + ((CustomPointerBuffer) buffer).getSize()); - element.setAttribute("offset", "" + ((CustomPointerBuffer) buffer).getOffset()); - } + buffer.writeConfig(element); config.add(element); - + return config; } @@ -865,21 +881,15 @@ public class BufferListener extends VisPlugin { } } else if ("buffer".equals(name)) { String bufferClassname = element.getText(); - Class bufferClass = + Class btClass = simulation.getGUI().tryLoadClass(this, Buffer.class, bufferClassname); - if (bufferClass == null) { + if (btClass == null) { logger.warn("Could not create buffer parser: could not find class: " + bufferClassname); } else { - - /* Special buffer: Custom Variable/Custom Pointer */ - if (bufferClass == CustomVariableBuffer.class || - bufferClass == CustomPointerBuffer.class) { - String varName = element.getAttributeValue("variable"); - int varSize = Integer.parseInt(element.getAttributeValue("size")); - int offset = Integer.parseInt(element.getAttributeValue("offset")); - setBuffer(bufferClass, varName, varSize, offset); - } else { - setBuffer(bufferClass); + Buffer b = createBufferInstance(btClass); + if (b != null) { + b.applyConfig(element); + setBuffer(b); } } } @@ -907,13 +917,13 @@ public class BufferListener extends VisPlugin { public boolean include(RowFilter.Entry entry) { if (hideReads) { int row = (Integer) entry.getIdentifier(); - if (logs.get(row).isRead) { + if (logs.get(row).type == MemoryEventType.READ) { return false; } } if (regexp != null) { boolean pass = regexp.include(entry); - + if (inverseFilter && pass) { return false; } else if (!inverseFilter && !pass) { @@ -953,80 +963,63 @@ public class BufferListener extends VisPlugin { }); } - public class BufferAccess { - public final AbstractEmulatedMote mote; - public final long time; - - public final boolean isRead; + public static class BufferAccess { + public static final byte[] NULL_DATA = new byte[0]; - private MemoryMonitor mm; - private int adr; - - public final String typeStr; + public final Mote mote; + public final long time; + + public final byte[] mem; + private boolean[] accessedBitpattern = null; + + public final MemoryEventType type; public final String sourceStr; public final String stackTrace; - public final byte[] mem; - - private boolean[] accessedBitpattern = null; - + public final int address; + public BufferAccess( - long time, MemoryMonitor mm, - MemoryEventType type, int adr, int data, - BufferAccess previous) { + Mote mote, long time, int address, byte[] newData, byte[] oldData, MemoryEventType type, boolean withStackTrace) { + this.mote = mote; this.time = time; - this.mote = (AbstractEmulatedMote) mm.getMote(); - this.mm = mm; - this.adr = adr; - this.isRead = (type == MemoryEventType.READ); - this.mem = mm.getMote().getMemory().getMemorySegment(mm.getAddress(), mm.getSize()); - - /* Apply currently written data, if write operation */ - if (type == MemoryEventType.WRITE) { - if (adr >= mm.getAddress() && adr < mm.getAddress() + mm.getSize()) { - int offset = adr - mm.getAddress(); - byte now = (byte)(0xff&data); - /*byte prev = mem[offset];*/ - /*logger.debug(String.format( - "WRITE: 0x%02x: %02x -> %02x", adr, prev, now));*/ - mem[offset] = now; - } else { - logger.warn(String.format( - "Write operation outside monitored addresses: %x !@ %x - %x", - adr, mm.getAddress(), mm.getAddress()+mm.getSize())); - } - } - + this.mem = newData==null?NULL_DATA:newData; + this.type = type; + this.address = address; + /* Generate diff bit pattern */ - if (previous != null) { - accessedBitpattern = new boolean[previous.mem.length]; - for (int i=0; i < previous.mem.length; i++) { - accessedBitpattern[i] = (previous.mem[i] != mem[i]); + if (newData != null && oldData != null) { + accessedBitpattern = new boolean[newData.length]; + for (int i=0; i < newData.length; i++) { + accessedBitpattern[i] = (oldData[i] != mem[i]); } + } else if (newData != null) { + accessedBitpattern = new boolean[newData.length]; + Arrays.fill(accessedBitpattern, true); } - - typeStr = type.toString(); - String s = mote.getPCString(); - sourceStr = s==null?"[unknown]":s; - if (withStackTrace) { - this.stackTrace = mote.getStackTrace(); + + if (mote instanceof AbstractEmulatedMote) { + String s = ((AbstractEmulatedMote)mote).getPCString(); + sourceStr = s==null?"[unknown]":s; + if (withStackTrace) { + this.stackTrace = ((AbstractEmulatedMote)mote).getStackTrace(); + } else { + this.stackTrace = null; + } } else { + this.sourceStr = "[unknown]"; this.stackTrace = null; } } - public Object getParsedData() { - return parser.parse(mm, adr, this); + public String getAsHex() { + return String.format("%04x", address) + ":" + StringUtils.toHex(mem); } - public String getParsedString() { - return StringUtils.toHex(mem); - } - + public boolean[] getAccessedBitpattern() { return accessedBitpattern; } public String getType() { - return typeStr; + return type.toString(); } public Object getSource() { @@ -1036,8 +1029,8 @@ public class BufferListener extends VisPlugin { public String getID() { return "ID:" + mote.getID(); } - - public String getTime() { + + public String getTime(boolean formatTimeString, boolean hasHours) { if (formatTimeString) { long t = time; long h = (t / TIME_HOUR); @@ -1104,7 +1097,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1153,20 +1146,20 @@ public class BufferListener extends VisPlugin { } int model = logTable.convertRowIndexToModel(view); long time = logs.get(model).time; - + Plugin[] plugins = simulation.getGUI().getStartedPlugins(); for (Plugin p: plugins) { if (!(p instanceof TimeLine)) { continue; } - + /* Select simulation time */ TimeLine plugin = (TimeLine) p; plugin.trySelectTime(time); } } }; - + private Action radioLoggerAction = new AbstractAction("in Radio Logger") { private static final long serialVersionUID = -3041714249257346688L; public void actionPerformed(ActionEvent e) { @@ -1193,7 +1186,7 @@ public class BufferListener extends VisPlugin { private Action showInAllAction = new AbstractAction("All") { private static final long serialVersionUID = -8433490108577001803L; { - putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)); } public void actionPerformed(ActionEvent e) { @@ -1230,7 +1223,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1260,7 +1253,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1285,7 +1278,7 @@ public class BufferListener extends VisPlugin { }; private void updateParserMenu() { parserMenu.removeAll(); - + for (Class bpClass: bufferParsers) { JCheckBoxMenuItem mi = new JCheckBoxMenuItem(GUI.getDescriptionOf(bpClass), bpClass==parser.getClass()); mi.putClientProperty("CLASS", bpClass); @@ -1300,13 +1293,22 @@ public class BufferListener extends VisPlugin { Class btClass = (Class) ((JMenuItem) e.getSource()).getClientProperty("CLASS"); - setBuffer(btClass); + + Buffer b = createBufferInstance(btClass); + if (b != null) { + if (b.configure(BufferListener.this)) { + setBuffer(b); + } + } } }; private void updateBufferMenu() { bufferMenu.removeAll(); - + for (Class btClass: bufferTypes) { + if (btClass == CustomVariableBuffer.class) { + bufferMenu.addSeparator(); + } JCheckBoxMenuItem mi = new JCheckBoxMenuItem(GUI.getDescriptionOf(btClass), btClass==buffer.getClass()); mi.putClientProperty("CLASS", btClass); mi.addActionListener(bufferSelectedListener); @@ -1325,32 +1327,37 @@ public class BufferListener extends VisPlugin { logger.warn("Could not create buffer parser: " + e.getMessage(), e); return; } - + parser = bp; logTable.getColumnModel().getColumn(COLUMN_DATA).setHeaderValue(GUI.getDescriptionOf(bp)); repaint(); } - - private class VariableInfoComponent { + private static class BufferInput { private JPanel mainPanel = new JPanel(); private JTextField textName = new JTextField(); private JTextField textSize = new JTextField(); private JTextField textOffset = new JTextField(); - public VariableInfoComponent(String name, String size, String offset) { - textName.setText(name); - textSize.setText(size); - textOffset.setText(offset); - + public BufferInput(String name, String size, String offset) { mainPanel.setLayout(new GridLayout(3, 2, 5, 5)); - mainPanel.add(new JLabel("Variable name:")); - mainPanel.add(textName); - mainPanel.add(new JLabel("Buffer size (1-" + MAX_BUFFER_SIZE + "):")); - mainPanel.add(textSize); - mainPanel.add(new JLabel("Offset:")); - mainPanel.add(textOffset); + + if (name != null) { + textName.setText(name); + mainPanel.add(new JLabel("Symbol:")); + mainPanel.add(textName); + } + if (size != null) { + textSize.setText(size); + mainPanel.add(new JLabel("Size (1-" + MAX_BUFFER_SIZE + "):")); + mainPanel.add(textSize); + } + if (size != null) { + textOffset.setText(offset); + mainPanel.add(new JLabel("Offset")); + mainPanel.add(textOffset); + } } public String getName() { return textName.getText(); @@ -1365,91 +1372,36 @@ public class BufferListener extends VisPlugin { return mainPanel; } } - - private void setBuffer(Class btClass) { - setBuffer(btClass, null, -1, -1); - } - private void setBuffer(Class btClass, String varName, int varSize, int varOffset) { - /* Special buffer: Custom Variable/Custom Pointer */ - if ((btClass == CustomVariableBuffer.class || btClass == CustomPointerBuffer.class) - && varName == null) { - String d = (btClass == CustomVariableBuffer.class)?"Variable":"Pointer"; - /* Read variable name */ - String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); - String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "8"); - String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); - VariableInfoComponent infoComponent = - new VariableInfoComponent(suggestName, suggestSize, suggestOffset); - - int result = JOptionPane.showConfirmDialog(BufferListener.this, - infoComponent.getComponent(), - d + " info", - JOptionPane.OK_CANCEL_OPTION); - if (result != JOptionPane.OK_OPTION) { - /* Abort */ - return; - } - varName = infoComponent.getName(); - if (varName == null) { - /* Abort */ - return; - } - try { - varSize = Integer.parseInt(infoComponent.getSize()); - } catch (RuntimeException e) { - logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); - /* Abort */ - return; - } - if (varSize < 1 || varSize > MAX_BUFFER_SIZE) { - /* Abort */ - logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); - return; - } - try { - varOffset = Integer.parseInt(infoComponent.getOffset()); - } catch (RuntimeException e) { - logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); - /* Abort */ - return; - } - } - - /* Generate buffer type */ - Buffer bt = null; + private static Buffer createBufferInstance(Class btClass) { try { - bt = btClass.newInstance(); + return btClass.newInstance(); } catch (InstantiationException e) { logger.warn("Could not create buffer type: " + e.getMessage(), e); - return; + return null; } catch (IllegalAccessException e) { logger.warn("Could not create buffer type: " + e.getMessage(), e); + return null; + } + } + + private void setBuffer(Buffer buffer) { + if (buffer == null) { return; } - /* Special buffer: Custom Variable/Custom Pointer */ - if (btClass == CustomVariableBuffer.class) { - ((CustomVariableBuffer)bt).setInfo(varName, varSize, varOffset); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", varName); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + varSize); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + varOffset); - } else if (btClass == CustomPointerBuffer.class) { - ((CustomPointerBuffer)bt).setInfo(varName, varSize, varOffset); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", varName); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + varSize); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + varOffset); - } - - buffer = bt; + this.buffer = buffer; /* Reregister memory monitors */ for (Mote m: simulation.getMotes()) { stopObserving(m); } for (Mote m: simulation.getMotes()) { - /* TODO Check return values */ - startObserving(m); + try { + startMonitoring(m); + } catch (Exception e) { + logger.warn("Could not monitor buffer on: " + m, e); + } } /* Clear previous buffers, update gui */ @@ -1457,7 +1409,7 @@ public class BufferListener extends VisPlugin { updateTitle(); repaint(); } - + public static interface Parser { /** * @param mm Memory monitor @@ -1465,11 +1417,11 @@ public class BufferListener extends VisPlugin { * @param ba Buffer Access object * @return String or custom graphical object */ - public Object parse(MemoryMonitor mm, int address, BufferAccess ba); + public Object parse(BufferAccess ba); } public static abstract class GraphicalParser implements Parser { BufferAccess ba = null; - public Object parse(MemoryMonitor mm, int address, BufferAccess ba) { + public Object parse(BufferAccess ba) { this.ba = ba; return ba; } @@ -1478,28 +1430,71 @@ public class BufferListener extends VisPlugin { } public static abstract class StringParser implements Parser { - public Object parse(MemoryMonitor mm, int address, BufferAccess ba) { - return parseString(mm,address,ba); + public Object parse(BufferAccess ba) { + return parseString(ba); } - /** - * @param mm Memory monitor - * @param address Address that changed. May not contain all changes - * @param ba Buffer Access object - * @return String representation - */ - public abstract String parseString(MemoryMonitor mm, int address, BufferAccess ba); + public abstract String parseString(BufferAccess ba); } + public static interface Buffer { public int getAddress(Mote mote); public int getSize(Mote mote); - - } - public static interface PointerBuffer extends Buffer { - public int getAddress(Mote mote); - public int getSize(Mote mote); - public int getPointerAddress(Mote mote); + public String getStatusString(); + + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception; + + /* + * Called when buffer is created by user to allow user input (AWT thread) + */ + public boolean configure(BufferListener bl); + + /* + * Called when buffer is created from config + */ + public void applyConfig(Element element); + + public void writeConfig(Element element); + } + public static abstract class AbstractBuffer implements Buffer { + public String getStatusString() { + return null; + } + public void writeConfig(Element element) { + } + public void applyConfig(Element element) { + } + public boolean configure(BufferListener bl) { + return true; + } + } + + public static abstract class PointerBuffer extends AbstractBuffer { + public abstract int getPointerAddress(Mote mote); + + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception { + return new PointerMemoryMonitor( + bl, + mote, + getPointerAddress(mote), + mote.getMemory().getIntegerLength(), + getSize(mote) + ); + } + } + public static abstract class SegmentBuffer extends AbstractBuffer { + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception { + return new SegmentMemoryMonitor( + bl, + mote, + getAddress(mote), + getSize(mote) + ); + } } public static boolean registerBufferParser(Class bpClass) { @@ -1523,10 +1518,10 @@ public class BufferListener extends VisPlugin { public static void unregisterBufferType(Class btClass) { bufferTypes.remove(btClass); } - + @ClassDescription("Byte array") public static class ByteArrayParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { boolean[] diff = ba.getAccessedBitpattern(); if (diff == null) { return StringUtils.toHex(ba.mem, 4); /* 00112233 00112233 .. */ @@ -1537,7 +1532,6 @@ public class BufferListener extends VisPlugin { int group = 0; for (int i=0; i < ba.mem.length; i++) { if (inRed == diff[i]) { - //logger.debug("same " + i); sb.append(StringUtils.toHex(ba.mem[i])); } else if (!inRed) { /* Diff begins */ @@ -1565,27 +1559,28 @@ public class BufferListener extends VisPlugin { return sb.toString(); } } - + @ClassDescription("Integer array") public static class IntegerParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { StringBuilder sb = new StringBuilder(); - boolean[] diff = ba.getAccessedBitpattern(); - + + int intLen = ba.mote.getMemory().getIntegerLength(); sb.append(""); - for (int i=0; i+1 < ba.mem.length;) { - int val = 0; + for (int i=0; i < ba.mem.length/intLen; i++) { + byte[] mem = Arrays.copyOfRange(ba.mem, i*intLen,(i+1)*intLen); + boolean[] diff = Arrays.copyOfRange(ba.getAccessedBitpattern(), i*intLen,(i+1)*intLen); + int val = ba.mote.getMemory().parseInt(mem); + boolean red = false; - if (diff != null && (diff[i] || diff[i+1])) { - red = true; + for (boolean changed: diff) { + if (changed) red = true; } - val += ((ba.mem[i++] & 0xFF)) << 8; - val += ((ba.mem[i++] & 0xFF)) << 0; - + if (red) { sb.append(""); } - sb.append((Integer.reverseBytes(val) >> 16) + " "); + sb.append(val + " "); if (red) { sb.append(""); } @@ -1597,7 +1592,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("Terminated string") public static class TerminatedStringParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ int i; for (i=0; i < ba.mem.length; i++) { @@ -1613,7 +1608,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("Printable characters") public static class PrintableCharactersParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ return new String(ba.mem).replaceAll("[^\\p{Print}]", ""); } @@ -1621,7 +1616,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("IPv6 address") public static class IPv6AddressParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ if (ba.mem.length < 16) { return "[must monitor at least 16 bytes]"; @@ -1639,7 +1634,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("IPv4 address") public static class IPv4AddressParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ if (ba.mem.length < 4) { return "[must monitor at least 4 bytes]"; @@ -1655,7 +1650,7 @@ public class BufferListener extends VisPlugin { return sb.toString(); } } - + static class GrapicalParserPanel extends JPanel { private static final long serialVersionUID = -8375160571675638467L; static final int XOFFSET = 0; @@ -1672,7 +1667,7 @@ public class BufferListener extends VisPlugin { public void paintComponent(Graphics g) { super.paintComponent(g); g.translate(XOFFSET, 0); - + if (getWidth() > getPreferredSize().width + 10 || getWidth() < getPreferredSize().width - 10) { double scale = 1.0*getWidth()/getPreferredSize().width; @@ -1683,7 +1678,7 @@ public class BufferListener extends VisPlugin { } }; private GrapicalParserPanel graphicalParserPanel = new GrapicalParserPanel(); - + @ClassDescription("Graphical: Height") public static class GraphicalHeight4BitsParser extends GraphicalParser { public int getUnscaledWidth() { @@ -1709,7 +1704,7 @@ public class BufferListener extends VisPlugin { } } } - + @ClassDescription("Graphical: Grayscale") public static class GraphicalGrayscale4BitsParser extends GraphicalParser { public int getUnscaledWidth() { @@ -1732,141 +1727,276 @@ public class BufferListener extends VisPlugin { } } } - + @ClassDescription("Variable: node_id") - public static class NodeIDBuffer implements Buffer { + public static class NodeIDBuffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("node_id")) { + if (!mote.getMemory().variableExists("node_id")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("node_id"); + return mote.getMemory().getVariableAddress("node_id"); } public int getSize(Mote mote) { - return 2; + return mote.getMemory().getIntegerLength(); } + } - + @ClassDescription("Queuebuf 0 RAM") - public static class Queuebuf0Buffer implements Buffer { + public static class Queuebuf0Buffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("buframmem")) { + if (!mote.getMemory().variableExists("buframmem")) { return -1; } int offset = 0; - return ((AddressMemory)mote.getMemory()).getVariableAddress("buframmem") + offset; + return mote.getMemory().getVariableAddress("buframmem") + offset; } public int getSize(Mote mote) { return 128; } } - + @ClassDescription("packetbuf_aligned") - public static class PacketbufBuffer implements Buffer { + public static class PacketbufBuffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbuf_aligned")) { + if (!mote.getMemory().variableExists("packetbuf_aligned")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("packetbuf_aligned"); + return mote.getMemory().getVariableAddress("packetbuf_aligned"); } public int getSize(Mote mote) { return 128; } } - + @ClassDescription("*packetbufptr") - public static class PacketbufPointerBuffer implements PointerBuffer { + public static class PacketbufPointerBuffer extends PointerBuffer { public int getPointerAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbufptr")) { + if (!mote.getMemory().variableExists("packetbufptr")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("packetbufptr"); + return mote.getMemory().getVariableAddress("packetbufptr"); } public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbufptr")) { + if (!mote.getMemory().variableExists("packetbufptr")) { return -1; } - return ((AddressMemory)mote.getMemory()).getIntValueOf("packetbufptr"); + return mote.getMemory().getIntValueOf("packetbufptr"); } public int getSize(Mote mote) { return 128; } } - - @ClassDescription("Custom pointer") - public static class CustomPointerBuffer implements PointerBuffer { + + @ClassDescription("Pointer...") + public static class CustomPointerBuffer extends PointerBuffer { public String variable; public int size; public int offset; - public void setInfo(String variable, int size, int offset) { - this.variable = variable; - this.size = size; - this.offset = offset; - } - public String getVariable() { - return variable; - } - public int getSize() { - return size; - } - public int getOffset() { - return offset; - } - public int getPointerAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress(variable); + return mote.getMemory().getVariableAddress(variable); } public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getIntValueOf(variable)+offset; + return mote.getMemory().getIntValueOf(variable)+offset; } public int getSize(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } return size; } + + public String getStatusString() { + if (offset > 0) { + return "Pointer *" + variable + "[" + offset + "] (" + size + ")"; + } else { + return "Pointer *" + variable + " (" + size + ")"; + } + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + element.setAttribute("size", "" + size); + element.setAttribute("offset", "" + offset); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + size = Integer.parseInt(element.getAttributeValue("size")); + offset = Integer.parseInt(element.getAttributeValue("offset")); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2"); + String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); + BufferInput infoComponent = + new BufferInput(suggestName, suggestSize, suggestOffset); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + try { + size = Integer.parseInt(infoComponent.getSize()); + if (size < 1 || size > MAX_BUFFER_SIZE) { + /* Abort */ + logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); + return false; + } + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); + return false; + } + try { + offset = Integer.parseInt(infoComponent.getOffset()); + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); + /* Abort */ + return false; + } + + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + size); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + offset); + return true; + } } - - @ClassDescription("Custom variable") - public static class CustomVariableBuffer implements Buffer { + + @ClassDescription("Symbol...") + public static class CustomVariableBuffer extends SegmentBuffer { public String variable; public int size; public int offset; - public void setInfo(String variable, int size, int offset) { - this.variable = variable; - this.size = size; - this.offset = offset; - } - public String getVariable() { - return variable; - } - public int getSize() { - return size; - } - public int getOffset() { - return offset; - } - public boolean isPointer() { - return false; - } - public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress(variable)+offset; + return mote.getMemory().getVariableAddress(variable)+offset; } public int getSize(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } return size; } + + public String getStatusString() { + if (offset > 0) { + return "Symbol &" + variable + "[" + offset + "] (" + size + ")"; + } else { + return "Symbol " + variable + " (" + size + ")"; + } + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + element.setAttribute("size", "" + size); + element.setAttribute("offset", "" + offset); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + size = Integer.parseInt(element.getAttributeValue("size")); + offset = Integer.parseInt(element.getAttributeValue("offset")); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2"); + String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); + BufferInput infoComponent = + new BufferInput(suggestName, suggestSize, suggestOffset); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + try { + size = Integer.parseInt(infoComponent.getSize()); + if (size < 1 || size > MAX_BUFFER_SIZE) { + /* Abort */ + logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); + return false; + } + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); + return false; + } + try { + offset = Integer.parseInt(infoComponent.getOffset()); + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); + /* Abort */ + return false; + } + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + size); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + offset); + return true; + } + } + + @ClassDescription("Integer...") + public static class CustomIntegerBuffer extends SegmentBuffer { + public String variable; + public int getAddress(Mote mote) { + if (!mote.getMemory().variableExists(variable)) { + return -1; + } + return mote.getMemory().getVariableAddress(variable); + } + public int getSize(Mote mote) { + return mote.getMemory().getIntegerLength(); + } + + public String getStatusString() { + return "Integer " + variable; + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + BufferInput infoComponent = + new BufferInput(suggestName, null, null); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + return true; + } } - }