From 1385e5e84da91b77f0ac875d25a80a3fe6490c82 Mon Sep 17 00:00:00 2001 From: eutarass Date: Fri, 25 Apr 2008 18:39:50 +0000 Subject: Bug 227874: [tcf][api] breakpoint event and capabilities changes --- .../internal/tcf/debug/ui/launch/TCFSelfTest.java | 45 +++++++++++++++- .../tcf/debug/model/TCFBreakpointsModel.java | 8 --- .../tcf/debug/model/TCFBreakpointsStatus.java | 42 ++++++++++----- .../tcf/services/remote/BreakpointsProxy.java | 41 ++++++++++++-- .../org/eclipse/tm/tcf/services/IBreakpoints.java | 63 ++++++++++++++++++++-- 5 files changed, 169 insertions(+), 30 deletions(-) (limited to 'plugins') diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java index d3942284b..8a456610d 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/launch/TCFSelfTest.java @@ -259,6 +259,7 @@ class TCFSelfTest { private final Map get_state_cmds = new HashMap(); private final Map> regs = new HashMap>(); + private final Map> bp_list = new HashMap>(); private String context_id; // Test process context ID private IRunControl.RunControlContext context; @@ -287,6 +288,43 @@ class TCFSelfTest { this.params = params; } } + + private final IBreakpoints.BreakpointsListener bp_listener = new IBreakpoints.BreakpointsListener() { + + public void breakpointStatusChanged(String id, Map status) { + } + + public void contextAdded(Map[] bps) { + for (Map m0 : bps) { + String id = (String)m0.get(IBreakpoints.PROP_ID); + Map m1 = bp_list.get(id); + if (!checkBPData(m0, m1)) return; + } + } + + public void contextChanged(Map[] bps) { + for (Map m0 : bps) { + String id = (String)m0.get(IBreakpoints.PROP_ID); + Map m1 = bp_list.get(id); + if (!checkBPData(m0, m1)) return; + } + } + + public void contextRemoved(String[] ids) { + } + + private boolean checkBPData(Map m0, Map m1) { + if (m1 == null) return true; + m0 = new HashMap(m0); + if (m0.get(IBreakpoints.PROP_ENABLED) == null) m0.put(IBreakpoints.PROP_ENABLED, Boolean.FALSE); + if (m1.get(IBreakpoints.PROP_ENABLED) == null) m1.put(IBreakpoints.PROP_ENABLED, Boolean.FALSE); + if (!m1.equals(m0)) { + exit(new Exception("Invalid data in Breakpoints event")); + return false; + } + return true; + } + }; TestRCBP1(IChannel channel, int channel_id) { this.channel_id = channel_id; @@ -307,6 +345,7 @@ class TCFSelfTest { else { diag.getTestList(this); } + if (bp != null) bp.addListener(bp_listener); } public void doneGetTestList(IToken token, Throwable error, String[] list) { @@ -397,6 +436,7 @@ class TCFSelfTest { m[i].put(IBreakpoints.PROP_ADDRESS, "tcf_test_func2"); break; } + bp_list.put((String)m[i].get(IBreakpoints.PROP_ID), m[i]); } bp.set(m, new IBreakpoints.DoneCommand() { public void doneCommand(IToken token, Exception error) { @@ -511,7 +551,7 @@ class TCFSelfTest { if (threads.size() == 0) return; done_starting_test_process = true; final String bp_id = "TcfTestBP3" + channel_id; - Map m = new HashMap(); + final Map m = new HashMap(); m.put(IBreakpoints.PROP_ID, bp_id); m.put(IBreakpoints.PROP_ENABLED, Boolean.FALSE); m.put(IBreakpoints.PROP_ADDRESS, "tcf_test_func2"); @@ -523,6 +563,7 @@ class TCFSelfTest { bf.append('"'); } m.put(IBreakpoints.PROP_CONDITION, bf.toString()); + bp_list.put(bp_id, m); bp.change(m, new IBreakpoints.DoneCommand() { public void doneCommand(IToken token, Exception error) { if (error != null) exit(error); @@ -530,6 +571,7 @@ class TCFSelfTest { }); Protocol.sync(new Runnable() { public void run() { + m.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); bp.enable(new String[]{ bp_id }, new IBreakpoints.DoneCommand() { public void doneCommand(IToken token, Exception error) { if (error != null) exit(error); @@ -1032,6 +1074,7 @@ class TCFSelfTest { if (x != null) errors.add(x); if (rc != null) rc.removeListener(this); } + if (bp != null) bp.removeListener(bp_listener); done(this); } } diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsModel.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsModel.java index ee091ca4e..7993267f4 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsModel.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsModel.java @@ -195,7 +195,6 @@ public class TCFBreakpointsModel implements IBreakpointListener, IBreakpointMana done = new IBreakpoints.DoneCommand() { public void doneCommand(IToken token, Exception error) { if (error != null) channel.terminate(error); - else done(launch); } }; update(); @@ -210,9 +209,6 @@ public class TCFBreakpointsModel implements IBreakpointListener, IBreakpointMana }); }; - void done(TCFLaunch launch) { - } - abstract void update(); } @@ -297,10 +293,6 @@ public class TCFBreakpointsModel implements IBreakpointListener, IBreakpointMana void update() { service.remove(new String[]{ (String)tcf_attrs.get(PROP_ID) }, done); } - @Override - void done(TCFLaunch launch) { - launch.getBreakpointsStatus().removeStatus((String)tcf_attrs.get(PROP_ID)); - } }.exec(); } catch (Throwable x) { diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java index aeed30228..0785e2050 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFBreakpointsStatus.java @@ -27,7 +27,6 @@ public class TCFBreakpointsStatus { private final IBreakpoints service; private final Map> status = new HashMap>(); private final Set listeners = new HashSet(); - private final Set removed = new HashSet(); private static final Map status_not_supported = new HashMap(); @@ -41,26 +40,49 @@ public class TCFBreakpointsStatus { if (service != null) { service.addListener(new IBreakpoints.BreakpointsListener() { - public void breakpointStatusChanged(String id, Map status) { + public void breakpointStatusChanged(String id, Map m) { assert Protocol.isDispatchThread(); - if (removed.contains(id)) return; - TCFBreakpointsStatus.this.status.put(id, status); + if (status.get(id) == null) return; + status.put(id, m); for (Iterator i = listeners.iterator(); i.hasNext();) { i.next().breakpointStatusChanged(id); } } + + public void contextAdded(Map[] bps) { + for (Map bp : bps) { + String id = (String)bp.get(IBreakpoints.PROP_ID); + if (status.get(id) != null) continue; + status.put(id, new HashMap()); + for (Iterator i = listeners.iterator(); i.hasNext();) { + i.next().breakpointStatusChanged(id); + } + } + } + + public void contextChanged(Map[] bps) { + } + + public void contextRemoved(String[] ids) { + for (String id : ids) { + if (status.remove(id) == null) continue; + for (Iterator i = listeners.iterator(); i.hasNext();) { + i.next().breakpointRemoved(id); + } + } + } }); } } - public Map getStatus(String id) { + public Map getStatus(String id) { assert id != null; assert Protocol.isDispatchThread(); if (service == null) return status_not_supported; return status.get(id); } - public Map getStatus(IBreakpoint bp) { + public Map getStatus(IBreakpoint bp) { if (!bp.getModelIdentifier().equals(ITCFConstants.ID_TCF_DEBUG_MODEL)) return status_not_supported; IMarker marker = bp.getMarker(); if (marker == null) return null; @@ -68,14 +90,6 @@ public class TCFBreakpointsStatus { ITCFConstants.ID_TCF_DEBUG_MODEL + '.' + IBreakpoints.PROP_ID, null)); } - public void removeStatus(String id) { - status.remove(id); - removed.add(id); - for (Iterator i = listeners.iterator(); i.hasNext();) { - i.next().breakpointRemoved(id); - } - } - public void addListener(ITCFBreakpointListener listener) { assert Protocol.isDispatchThread(); listeners.add(listener); diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/BreakpointsProxy.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/BreakpointsProxy.java index 3a7ac8ef7..577681ca8 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/BreakpointsProxy.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/internal/tcf/services/remote/BreakpointsProxy.java @@ -32,7 +32,7 @@ public class BreakpointsProxy implements IBreakpoints { this.channel = channel; } - public IToken set(Map[] properties, final DoneCommand done) { + public IToken set(Map[] properties, final DoneCommand done) { return new Command(channel, this, "set", new Object[]{ properties }) { @Override public void done(Exception error, Object[] args) { @@ -45,7 +45,7 @@ public class BreakpointsProxy implements IBreakpoints { }.token; } - public IToken add(Map properties, final DoneCommand done) { + public IToken add(Map properties, final DoneCommand done) { return new Command(channel, this, "add", new Object[]{ properties }) { @Override public void done(Exception error, Object[] args) { @@ -58,7 +58,7 @@ public class BreakpointsProxy implements IBreakpoints { }.token; } - public IToken change(Map properties, final DoneCommand done) { + public IToken change(Map properties, final DoneCommand done) { return new Command(channel, this, "change", new Object[]{ properties }) { @Override public void done(Exception error, Object[] args) { @@ -157,6 +157,22 @@ public class BreakpointsProxy implements IBreakpoints { }.token; } + public IToken getCapabilities(String id, final DoneGetCapabilities done) { + return new Command(channel, this, "getCapabilities", new Object[]{ id }) { + @SuppressWarnings("unchecked") + @Override + public void done(Exception error, Object[] args) { + Map map = null; + if (error == null) { + assert args.length == 3; + error = toError(args[0], args[1]); + map = (Map)args[2]; + } + done.doneGetCapabilities(token, error, map); + } + }.token; + } + public String getName() { return NAME; } @@ -168,6 +184,13 @@ public class BreakpointsProxy implements IBreakpoints { return (String[])c.toArray(new String[c.size()]); } + @SuppressWarnings("unchecked") + private Map[] toBreakpointArray(Object o) { + Collection> c = (Collection>)o; + if (c == null) return new Map[0]; + return (Map[])c.toArray(new Map[c.size()]); + } + public void addListener(final BreakpointsListener listener) { IChannel.IEventListener l = new IChannel.IEventListener() { @@ -179,6 +202,18 @@ public class BreakpointsProxy implements IBreakpoints { assert args.length == 2; listener.breakpointStatusChanged((String)args[0], (Map)args[1]); } + else if (name.equals("contextAdded")) { + assert args.length == 1; + listener.contextAdded(toBreakpointArray(args[0])); + } + else if (name.equals("contextChanged")) { + assert args.length == 1; + listener.contextChanged(toBreakpointArray(args[0])); + } + else if (name.equals("contextRemoved")) { + assert args.length == 1; + listener.contextRemoved(toStringArray(args[0])); + } else { throw new IOException("Breakpoints service: unknown event: " + name); } diff --git a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IBreakpoints.java b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IBreakpoints.java index ec1477341..c29e100e3 100644 --- a/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IBreakpoints.java +++ b/plugins/org.eclipse.tm.tcf/src/org/eclipse/tm/tcf/services/IBreakpoints.java @@ -20,11 +20,11 @@ import org.eclipse.tm.tcf.protocol.IToken; * Breakpoint is represented by unique identifier and set of properties. * Breakpoint identifier (String id) needs to be unique across all hosts and targets. * - * Breakpoint properties (Map) is extendable collection of named attributes, + * Breakpoint properties (Map) is extendible collection of named attributes, * which define breakpoint location and behavior. This module defines some common * attribute names (see PROP_*), host tools and target agents may support additional attributes. * - * For each breakpoint a target agent maintains another extendable collection of named attributes: + * For each breakpoint a target agent maintains another extendible collection of named attributes: * breakpoint status (Map, see STATUS_*). While breakpoint properties are * persistent and represent user input, breakpoint status reflects dynamic target agent reports * about breakpoint current state, like actual addresses where breakpoint is planted or planting errors. @@ -58,6 +58,16 @@ public interface IBreakpoints extends IService { STATUS_LINE = "Line", // Number STATUS_COLUMN = "Column"; // Number + /** + * Breakpoint service capabilities. + */ + static final String + CAPABILITY_CONTEXT_ID = "ID", // String + CAPABILITY_HAS_CHILDREN = "HasChildren", // Boolean + CAPABILITY_ADDRESS = "Address", // Boolean + CAPABILITY_CONDITION = "Condition", // Boolean + CAPABILITY_FILE_LINE = "FileLine"; // Boolean + /** * Call back interface for breakpoint service commands. */ @@ -92,7 +102,7 @@ public interface IBreakpoints extends IService { IToken change(Map properties, DoneCommand done); /** - * Tell target to change (only) PROP_ENABLED breakpoint property 'true'. + * Tell target to change (only) PROP_ENABLED breakpoint property to 'true'. * @param ids - array of enabled breakpoint identifiers. * @param done - command result call back object. */ @@ -106,7 +116,7 @@ public interface IBreakpoints extends IService { IToken disable(String[] ids, DoneCommand done); /** - * Tell target to remove breakpoint. + * Tell target to remove breakpoints. * @param id - unique breakpoint identifier. * @param done - command result call back object. */ @@ -144,8 +154,27 @@ public interface IBreakpoints extends IService { void doneGetStatus(IToken token, Exception error, Map status); } + /** + * Report breakpoint service capabilities to clients so they + * can adjust to different implementations of the service. + * When called with a null ("") context ID the global capabilities are returned, + * otherwise context specific capabilities are returned. A special capability + * property is used to indicate that all child contexts have the same + * capabilities. + * @param id - a context ID or null. + * @param done - command result call back object. + */ + IToken getCapabilities(String id, DoneGetCapabilities done); + + interface DoneGetCapabilities { + void doneGetCapabilities(IToken token, Exception error, Map capabilities); + } + /** * Breakpoints service events listener. + * Note that contextAdded, contextChanged and contextRemoved events carry exactly same set + * of breakpoint properties that was sent by a client to a target. The purpose of these events is to + * let all clients know about breakpoints that were created by other clients. */ interface BreakpointsListener { @@ -155,9 +184,35 @@ public interface IBreakpoints extends IService { * @param status - breakpoint status. */ void breakpointStatusChanged(String id, Map status); + + /** + * Called when a new breakpoints are added. + * @param bps - array of breakpoints. + */ + void contextAdded(Map[] bps); + + /** + * Called when breakpoint properties change. + * @param bps - array of breakpoints. + */ + void contextChanged(Map[] bps); + + /** + * Called when breakpoints are removed . + * @param ids - array of breakpoint IDs. + */ + void contextRemoved(String[] ids); } + /** + * Add breakpoints service event listener. + * @param listener - object that implements BreakpointsListener interface. + */ void addListener(BreakpointsListener listener); + /** + * Remove breakpoints service event listener. + * @param listener - object that implements BreakpointsListener interface. + */ void removeListener(BreakpointsListener listener); } -- cgit v1.2.3