/*******************************************************************************
* Copyright (c) 2005 - 2007 committers of openArchitectureWare 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:
* committers of openArchitectureWare - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.mwe.internal.ui.debug.model;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
import org.eclipse.emf.mwe.internal.ui.eclipse.launch.MWELaunchConfigurationConstants;
import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
import org.eclipse.emf.mwe.ui.debug.model.MWEBreakpoint;
/**
* MWE Debug Target implementation<br>
* It holds the debug threads. There is only one thread in the MWE debug model.<br>
* It holds also a variable values cache.
* <br>
* For Info: A debug target handles the suspend, resume, terminate commands and the breakpoint handling.
*
*/
public class DebugTarget extends DebugElement implements IDebugTarget {
private IProcess fProcess;
private ILaunch fLaunch;
private DebugThread fThread;
private DebugModelManager dmm;
private Map<Integer, DebugValue> valueCache = new HashMap<Integer, DebugValue>();
protected boolean suspended;
public static DebugTarget newDebugTarget(final ILaunch launch, final IProcess process, final Connection conn)
throws CoreException {
final DebugTarget[] target = new DebugTarget[1];
IWorkspaceRunnable r = new IWorkspaceRunnable() {
public void run(IProgressMonitor m) throws DebugException {
target[0] = new DebugTarget(launch, process, conn);
}
};
try {
// run as atomic unit of work; fire resource change events only once
ResourcesPlugin.getWorkspace().run(r, null, 0, null);
} catch (CoreException e) {
Activator.logError(e);
Activator.showError(e.getStatus());
throw e;
}
launch.addDebugTarget(target[0]);
return target[0];
}
private DebugTarget(ILaunch launch, IProcess process, Connection conn) throws DebugException {
super(null);
fLaunch = launch;
target = this;
fProcess = process;
fThread = new DebugThread(this);
dmm = DebugModelManager.newDebugModelManager(this, conn);
DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
}
// ******************************************** debug model related elements
@Override
public ILaunch getLaunch() {
return fLaunch;
}
public IProcess getProcess() {
return fProcess;
}
public IThread[] getThreads() {
return new IThread[] { fThread };
}
public DebugThread getThread() {
return fThread;
}
public void removeThread() {
fThread = null;
}
public boolean hasThreads() {
return fThread != null;
}
public String getName() {
try {
return "Workflow: "
+ fLaunch.getLaunchConfiguration().getAttribute(
MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, "");
} catch (CoreException e) {
// should not occur
}
return "";
}
@Override
public DebugModelManager getDebugModelManager() {
return dmm;
}
public DebugValue getDebugValue(VarValueTO varTO) {
DebugValue value = null;
int valueId = varTO.valueId;
if (valueId == 0)
// don't cache primitives
value = new DebugValue(this, varTO);
else {
value = valueCache.get(valueId);
if (value == null) {
value = new DebugValue(this, varTO);
valueCache.put(valueId, value);
}
}
return value;
}
public void updateDebugValues(List<VarValueTO> vars) {
for (VarValueTO varTO : vars) {
DebugValue value = valueCache.get(varTO.valueId);
if (value != null && value.isDirty()) {
value.setVarTO(varTO);
}
}
}
// ************************ ISuspendResume implementation and other commands
public boolean canResume() {
return suspended && !isTerminated();
}
public boolean canSuspend() {
return !suspended && !isTerminated();
}
public boolean isSuspended() {
return suspended;
}
public void resume() throws DebugException {
dmm.requireResume();
}
public void suspend() throws DebugException {
dmm.requireSuspend();
}
public void setSuspended(boolean value) {
suspended = value;
}
public void setVariablesDirty() {
for (DebugValue entry : valueCache.values())
if (entry != null)
entry.setDirty(true);
}
// ***************** Breakpoint handling, IBreakpointListener implementation
public void installDeferredBreakpoints() {
IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
MWEBreakpoint.DEBUG_MODEL_ID);
for (IBreakpoint element : breakpoints) {
breakpointAdded(element);
}
}
public boolean supportsBreakpoint(final IBreakpoint breakpoint) {
return breakpoint.getModelIdentifier().equals(MWEBreakpoint.DEBUG_MODEL_ID);
}
public void breakpointAdded(final IBreakpoint breakpoint) {
if (supportsBreakpoint(breakpoint)) {
try {
if (breakpoint.isEnabled()) {
dmm.requireSetBreakpoint((MWEBreakpoint) breakpoint);
}
} catch (CoreException e) {
// in case connection broke
}
}
}
public void breakpointRemoved(final IBreakpoint breakpoint, final IMarkerDelta delta) {
if (supportsBreakpoint(breakpoint)) {
try {
dmm.requireRemoveBreakpoint((MWEBreakpoint) breakpoint);
} catch (CoreException e) {
// in case connection broke
}
}
}
public void breakpointChanged(final IBreakpoint breakpoint, final IMarkerDelta delta) {
if (supportsBreakpoint(breakpoint)) {
try {
if (breakpoint.isEnabled()) {
breakpointAdded(breakpoint);
} else {
breakpointRemoved(breakpoint, null);
}
} catch (CoreException e) {
// in case connection broke
}
}
}
// *********************************************** ITerminate implementation
public boolean canTerminate() {
return getProcess().canTerminate();
}
public boolean isTerminated() {
return getProcess().isTerminated();
}
public void terminate() throws DebugException {
dmm.requireTerminate();
}
// ********************************************** IDisconnect implementation
public boolean canDisconnect() {
return false;
}
public void disconnect() {
// not supported
}
public boolean isDisconnected() {
return false;
}
// ************************************ IMemoryBlockRetrieval implementation
public boolean supportsStorageRetrieval() {
return false;
}
public IMemoryBlock getMemoryBlock(final long startAddress, final long length) {
return null;
}
}