Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java')
-rw-r--r--plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java614
1 files changed, 614 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java
new file mode 100644
index 000000000..b1f66dde4
--- /dev/null
+++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java
@@ -0,0 +1,614 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.internal.tcf.dsf.services;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
+import org.eclipse.dd.dsf.datamodel.ServiceDMContext;
+import org.eclipse.dd.dsf.debug.service.INativeProcesses;
+import org.eclipse.dd.dsf.service.AbstractDsfService;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.tm.internal.tcf.dsf.Activator;
+import org.eclipse.tm.tcf.protocol.IChannel;
+import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.services.IProcesses;
+import org.eclipse.tm.tcf.services.IRunControl;
+import org.eclipse.tm.tcf.services.IProcesses.ProcessContext;
+import org.eclipse.tm.tcf.services.IRunControl.RunControlContext;
+import org.osgi.framework.BundleContext;
+
+
+public class TCFDSFNativeProcesses extends AbstractDsfService implements INativeProcesses {
+
+ private class ProcessDMC extends TCFDSFProcessDMC implements IProcessDMContext {
+
+ final String id;
+
+ ProcessDMC(String id, IDMContext parent) {
+ super(TCFDSFNativeProcesses.this, parent != null ? new IDMContext[]{ parent } : new IDMContext[0]);
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return baseToString() + ".context[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.baseEquals(obj)) return false;
+ String obj_id = ((ProcessDMC)obj).id;
+ if (obj_id == null) return id == null;
+ return obj_id.equals(id);
+ }
+
+ @Override
+ public int hashCode() {
+ if (id == null) return 0;
+ return id.hashCode();
+ }
+ }
+
+ private class ThreadDMC extends TCFDSFThreadDMC implements IThreadDMContext {
+
+ final String id;
+
+ ThreadDMC(String id) {
+ super(TCFDSFNativeProcesses.this, new IDMContext[0]);
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return baseToString() + ".context[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.baseEquals(obj)) return false;
+ String obj_id = ((ThreadDMC)obj).id;
+ if (obj_id == null) return id == null;
+ return obj_id.equals(id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+ }
+
+ private class ProcessData implements IProcessDMData {
+
+ private final IProcesses.ProcessContext ctx;
+
+ ProcessData(IProcesses.ProcessContext ctx) {
+ this.ctx = ctx;
+ }
+
+ public IDMContext getDebugContext() {
+ return getServicesTracker().getService(TCFDSFRunControl.class).getContext(ctx.getID());
+ }
+
+ public String getId() {
+ return ctx.getID();
+ }
+
+ public String getName() {
+ return ctx.getName();
+ }
+
+ public boolean isDebuggerAttached() {
+ return ctx.isAttached();
+ }
+
+ public boolean isValid() {
+ return true;
+ }
+ }
+
+ private class ThreadData implements IThreadDMData {
+
+ private final TCFDSFExecutionDMC ctx;
+
+ ThreadData(TCFDSFExecutionDMC ctx) {
+ this.ctx = ctx;
+ }
+
+ public IDMContext getDebugContext() {
+ return ctx;
+ }
+
+ public String getId() {
+ if (ctx == null) return null;
+ return ctx.getTcfContextId();
+ }
+
+ public String getName() {
+ // TODO thread name
+ return "";
+ }
+
+ public boolean isDebuggerAttached() {
+ return true;
+ }
+
+ public boolean isValid() {
+ return true;
+ }
+ }
+
+ private class ProcessStartedEvent extends AbstractDMEvent<IDMContext> implements IProcessStartedEvent {
+
+ private final IProcessDMContext prs;
+
+ ProcessStartedEvent(IDMContext dmc, IProcessDMContext prs) {
+ super(dmc);
+ this.prs = prs;
+ }
+
+ public IProcessDMContext getProcess() {
+ return prs;
+ }
+ }
+
+ private class ProcessExitedEvent extends AbstractDMEvent<IDMContext> implements IProcessExitedEvent {
+
+ private final IProcessDMContext prs;
+
+ ProcessExitedEvent(IDMContext dmc, IProcessDMContext prs) {
+ super(dmc);
+ this.prs = prs;
+ }
+
+ public IProcessDMContext getProcess() {
+ return prs;
+ }
+ }
+
+ private final org.eclipse.tm.tcf.services.IRunControl.RunControlListener run_listener =
+ new org.eclipse.tm.tcf.services.IRunControl.RunControlListener() {
+
+ public void containerResumed(String[] context_ids) {
+ }
+
+ public void containerSuspended(String context, String pc,
+ String reason, Map<String, Object> params,
+ String[] suspended_ids) {
+ }
+
+ public void contextAdded(RunControlContext[] contexts) {
+ for (RunControlContext ctx : contexts) {
+ String id = ctx.getID();
+ if (id.equals(ctx.getProperties().get(IRunControl.PROP_PROCESS_ID))) {
+ ProcessDMC dmc = new ProcessDMC(id, root_dmc);
+ process_cache.put(id, dmc);
+ getSession().dispatchEvent(new ProcessStartedEvent(root_dmc, dmc), getProperties());
+ }
+ else {
+ ThreadDMC dmc = new ThreadDMC(id);
+ thread_cache.put(id, dmc);
+ }
+ }
+ }
+
+ public void contextChanged(RunControlContext[] contexts) {
+ }
+
+ public void contextException(String context, String msg) {
+ }
+
+ public void contextRemoved(String[] context_ids) {
+ for (String id : context_ids) {
+ ProcessDMC dmc = process_cache.remove(id);
+ if (dmc != null) {
+ getSession().dispatchEvent(new ProcessExitedEvent(root_dmc, dmc), getProperties());
+ }
+ else {
+ thread_cache.remove(id);
+ }
+ }
+ }
+
+ public void contextResumed(String context) {
+ }
+
+ public void contextSuspended(String context, String pc,
+ String reason, Map<String, Object> params) {
+ }
+ };
+
+ private final IProcesses tcf_prs_service;
+ private final org.eclipse.tm.tcf.services.IRunControl tcf_run_service;
+ private final Map<String,ProcessDMC> process_cache = new HashMap<String,ProcessDMC>(); // all attached processes
+ private final Map<String,ThreadDMC> thread_cache = new HashMap<String,ThreadDMC>(); // only some of attached threads
+ private final ProcessDMC root_dmc = new ProcessDMC(null, null);
+ private IDMContext service_dmc;
+
+ public TCFDSFNativeProcesses(DsfSession session, IChannel channel, final RequestMonitor monitor) {
+ super(session);
+ tcf_prs_service = channel.getRemoteService(IProcesses.class);
+ tcf_run_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IRunControl.class);
+ if (tcf_run_service != null) tcf_run_service.addListener(run_listener);
+ service_dmc = new ServiceDMContext(this, "#native_process");
+ initialize(new RequestMonitor(getExecutor(), monitor) {
+ @Override
+ protected void handleOK() {
+ String[] class_names = {
+ INativeProcesses.class.getName(),
+ TCFDSFNativeProcesses.class.getName()
+ };
+ register(class_names, new Hashtable<String,String>());
+ monitor.done();
+ }
+ });
+ }
+
+ @Override
+ public void initialize(final RequestMonitor monitor) {
+ final Collection<String> list = new ArrayList<String>();
+ final Set<IToken> cmds = new HashSet<IToken>();
+ final IProcesses.DoneGetChildren done = new IProcesses.DoneGetChildren() {
+ public void doneGetChildren(IToken token, Exception error, String[] context_ids) {
+ if (cmds.isEmpty()) return;
+ assert cmds.contains(token);
+ cmds.remove(token);
+ if (error != null) {
+ for (IToken t : cmds) t.cancel();
+ cmds.clear();
+ monitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$
+ monitor.done();
+ }
+ else {
+ for (String id : context_ids) {
+ list.add(id);
+ cmds.add(tcf_prs_service.getChildren(id, true, this));
+ }
+ if (cmds.isEmpty()) {
+ for (String id : list) {
+ assert id != null;
+ if (process_cache.get(id) != null) continue;
+ process_cache.put(id, new ProcessDMC(id, root_dmc));
+ }
+ process_cache.put(null, root_dmc);
+ TCFDSFNativeProcesses.super.initialize(monitor);
+ }
+ }
+ }
+ };
+ cmds.add(tcf_prs_service.getChildren(null, true, done));
+ }
+
+ @Override
+ public void shutdown(RequestMonitor monitor) {
+ unregister();
+ super.shutdown(monitor);
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return Activator.getBundleContext();
+ }
+
+ public IDMContext getServiceContext() {
+ return service_dmc;
+ }
+
+ public boolean isValid() {
+ return true;
+ }
+
+ public void attachDebuggerToProcess(IProcessDMContext ctx, final RequestMonitor rm) {
+ if (tcf_prs_service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ else if (ctx instanceof ProcessDMC) {
+ final ProcessDMC p = (ProcessDMC)ctx;
+ tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, ProcessContext context) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$
+ rm.done();
+ }
+ else if (context == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$
+ rm.done();
+ }
+ else {
+ context.attach(new IProcesses.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot attach a process", error)); //$NON-NLS-1$
+ }
+ assert error != null || process_cache.get(p.id) != null;
+ rm.done();
+ }
+ });
+ }
+ }
+ });
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void canTerminate(IDMContext ctx, final DataRequestMonitor<Boolean> rm) {
+ rm.setData(false);
+ if (tcf_prs_service == null) {
+ rm.done();
+ }
+ else if (ctx instanceof ProcessDMC) {
+ ProcessDMC p = (ProcessDMC)ctx;
+ tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, ProcessContext context) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$
+ }
+ else if (context == null) {
+ rm.setData(false);
+ }
+ else {
+ rm.setData(context.canTerminate());
+ }
+ rm.done();
+ }
+ });
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void terminate(IDMContext ctx, final RequestMonitor rm) {
+ if (tcf_prs_service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ else if (ctx instanceof ProcessDMC) {
+ ProcessDMC p = (ProcessDMC)ctx;
+ tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, ProcessContext context) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$
+ rm.done();
+ }
+ else if (context == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$
+ rm.done();
+ }
+ else {
+ context.terminate(new IProcesses.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot terminate a process", error)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+ }
+ });
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void debugNewProcess(String file, final DataRequestMonitor<IProcessDMContext> rm) {
+ if (tcf_prs_service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ else {
+ tcf_prs_service.start(null, file, null, null, true, new IProcesses.DoneStart() {
+ public void doneStart(IToken token, Exception error, ProcessContext process) {
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot start a process", error)); //$NON-NLS-1$
+ }
+ else {
+ ProcessDMC dmc = process_cache.get(process.getID());
+ assert dmc != null;
+ rm.setData(dmc);
+ }
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public void runNewProcess(String file, final DataRequestMonitor<IProcessDMContext> rm) {
+ if (tcf_prs_service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ else {
+ tcf_prs_service.start(null, file, null, null, false, new IProcesses.DoneStart() {
+ public void doneStart(IToken token, Exception error, ProcessContext process) {
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot start a process", error)); //$NON-NLS-1$
+ }
+ else {
+ assert process_cache.get(process.getID()) == null;
+ rm.setData(new ProcessDMC(process.getID(), root_dmc));
+ }
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public IProcessDMContext getProcessForDebugContext(IDMContext ctx) {
+ if (ctx instanceof IProcessDMContext) {
+ return (IProcessDMContext)ctx;
+ }
+ if (ctx instanceof TCFDSFExecutionDMC) {
+ String id = ((TCFDSFExecutionDMC)ctx).getTcfContextId();
+ return process_cache.get(id);
+ }
+ return null;
+ }
+
+ public IThreadDMContext getThreadForDebugContext(IDMContext ctx) {
+ if (ctx instanceof IThreadDMContext) {
+ return (IThreadDMContext)ctx;
+ }
+ if (ctx instanceof TCFDSFExecutionDMC) {
+ String id = ((TCFDSFExecutionDMC)ctx).getTcfContextId();
+ ThreadDMC dmc = thread_cache.get(id);
+ if (dmc == null) dmc = new ThreadDMC(id);
+ return dmc;
+ }
+ return null;
+ }
+
+ public void getProcessesBeingDebugged(DataRequestMonitor<IProcessDMContext[]> rm) {
+ rm.setData(process_cache.values().toArray(new IProcessDMContext[process_cache.size()]));
+ rm.done();
+ }
+
+ public void getRunningProcesses(final DataRequestMonitor<IProcessDMContext[]> rm) {
+ final Collection<String> list = new ArrayList<String>();
+ final Set<IToken> cmds = new HashSet<IToken>();
+ final IProcesses.DoneGetChildren done = new IProcesses.DoneGetChildren() {
+ public void doneGetChildren(IToken token, Exception error, String[] context_ids) {
+ if (cmds.isEmpty()) return;
+ assert cmds.contains(token);
+ cmds.remove(token);
+ if (error != null) {
+ for (IToken t : cmds) t.cancel();
+ cmds.clear();
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$
+ rm.done();
+ }
+ else {
+ for (String id : context_ids) {
+ list.add(id);
+ cmds.add(tcf_prs_service.getChildren(id, false, this));
+ }
+ if (cmds.isEmpty()) {
+ int cnt = 0;
+ IProcessDMContext[] data = new IProcessDMContext[list.size()];
+ for (String id : list) {
+ assert id != null;
+ data[cnt] = process_cache.get(id);
+ if (data[cnt] == null) data[cnt] = new ProcessDMC(id, root_dmc);
+ cnt++;
+ }
+ rm.setData(data);
+ rm.done();
+ }
+ }
+ }
+ };
+ cmds.add(tcf_prs_service.getChildren(null, false, done));
+ }
+
+ @SuppressWarnings("unchecked")
+ public void getModelData(IDMContext dmc, final DataRequestMonitor<?> rm) {
+ if (dmc instanceof ProcessDMC) {
+ getProcessData((ProcessDMC)dmc, (DataRequestMonitor<IProcessDMData>)rm);
+ }
+ else if (dmc instanceof ThreadDMC) {
+ getThreadData((ThreadDMC)dmc, (DataRequestMonitor<IThreadDMData>)rm);
+ }
+ else if (dmc == service_dmc) {
+ ((DataRequestMonitor<TCFDSFNativeProcesses>)rm).setData(this);
+ rm.done();
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getProcessData(IProcessDMContext dmc, final DataRequestMonitor<IProcessDMData> rm) {
+ if (dmc instanceof ProcessDMC) {
+ tcf_prs_service.getContext(((ProcessDMC)dmc).id, new IProcesses.DoneGetContext() {
+
+ @SuppressWarnings("unchecked")
+ public void doneGetContext(IToken token, Exception error, ProcessContext context) {
+ if (rm.isCanceled()) return;
+ if (error != null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$
+ }
+ else if (context == null) {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$
+ }
+ else {
+ rm.setData(new ProcessData(context));
+ }
+ rm.done();
+ }
+ });
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getThreadData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) {
+ if (dmc instanceof ThreadDMC) {
+ String id = ((ThreadDMC)dmc).id;
+ TCFDSFRunControl rc = getServicesTracker().getService(TCFDSFRunControl.class);
+ rm.setData(new ThreadData(rc.getContext(id)));
+ rm.done();
+ }
+ else {
+ rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+}

Back to the top