/*******************************************************************************
* Copyright (c) 2007, 2012 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.tcf.internal.debug.ui.commands;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
import org.eclipse.debug.core.commands.ISuspendHandler;
import org.eclipse.tcf.internal.debug.actions.TCFAction;
import org.eclipse.tcf.internal.debug.model.TCFContextState;
import org.eclipse.tcf.internal.debug.ui.Activator;
import org.eclipse.tcf.internal.debug.ui.model.TCFModel;
import org.eclipse.tcf.internal.debug.ui.model.TCFNode;
import org.eclipse.tcf.internal.debug.ui.model.TCFNodeExecContext;
import org.eclipse.tcf.internal.debug.ui.model.TCFRunnable;
import org.eclipse.tcf.protocol.IToken;
import org.eclipse.tcf.services.IRunControl;
import org.eclipse.tcf.util.TCFDataCache;
public class SuspendCommand implements ISuspendHandler {
private final TCFModel model;
public SuspendCommand(TCFModel model) {
this.model = model;
}
public void canExecute(final IEnabledStateRequest monitor) {
new TCFRunnable(model, monitor) {
public void run() {
if (done) return;
Object[] elements = monitor.getElements();
boolean res = false;
for (int i = 0; i < elements.length; i++) {
TCFNode node = null;
if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i];
else node = model.getRootNode();
while (node != null && !node.isDisposed()) {
IRunControl.RunControlContext ctx = null;
if (node instanceof TCFNodeExecContext) {
TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext();
if (!cache.validate(this)) return;
ctx = cache.getData();
}
if (ctx == null) {
node = node.getParent();
}
else if (model.getActiveAction(ctx.getID()) != null) {
res = true;
break;
}
else {
if (!ctx.canSuspend()) break;
if (ctx.isContainer()) {
TCFNodeExecContext.ChildrenStateInfo s = new TCFNodeExecContext.ChildrenStateInfo();
if (!((TCFNodeExecContext)node).hasSuspendedChildren(s, this)) return;
if (s.running) res = true;
}
if (ctx.hasState()) {
TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState();
if (!state_cache.validate(this)) return;
TCFContextState state_data = state_cache.getData();
if (state_data != null && !state_data.is_suspended && ctx.canSuspend()) res = true;
}
break;
}
}
}
monitor.setEnabled(res);
monitor.setStatus(Status.OK_STATUS);
done();
}
};
}
public boolean execute(final IDebugCommandRequest monitor) {
new TCFRunnable(model, monitor) {
public void run() {
if (done) return;
Object[] elements = monitor.getElements();
Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>();
for (int i = 0; i < elements.length; i++) {
TCFNode node = null;
if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i];
else node = model.getRootNode();
while (node != null && !node.isDisposed()) {
IRunControl.RunControlContext ctx = null;
if (node instanceof TCFNodeExecContext) {
TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext();
if (!cache.validate(this)) return;
ctx = cache.getData();
}
if (ctx == null) {
node = node.getParent();
}
else {
set.add(ctx);
break;
}
}
}
final Set<IToken> cmds = new HashSet<IToken>();
for (Iterator<IRunControl.RunControlContext> i = set.iterator(); i.hasNext();) {
IRunControl.RunControlContext ctx = i.next();
model.getLaunch().removeContextActions(ctx.getID());
final TCFAction action = model.getActiveAction(ctx.getID());
if (action != null) action.abort();
cmds.add(ctx.suspend(new IRunControl.DoneCommand() {
public void doneCommand(IToken token, Exception error) {
assert cmds.contains(token);
cmds.remove(token);
if (error != null && action == null) {
monitor.setStatus(new Status(IStatus.ERROR,
Activator.PLUGIN_ID, IStatus.OK, "Cannot suspend: " + error.getLocalizedMessage(), error));
}
if (cmds.isEmpty()) done();
}
}));
}
}
};
return true;
}
}