blob: 7f90fff9fb5d6548e65d4bc1813b7bd81cb174bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* R.Dvorak and others - QVTo debugger framework
* E.D.Willink - revised API for OCL debugger framework
*******************************************************************************/
package org.eclipse.ocl.examples.debug.vm.core;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
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.model.IBreakpoint;
import org.eclipse.debug.core.model.LineBreakpoint;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.examples.debug.vm.DebugVMPlugin;
import org.eclipse.ocl.examples.debug.vm.data.VMBreakpointData;
import org.eclipse.ocl.examples.debug.vm.data.VMNewBreakpointData;
public abstract class VMLineBreakpoint extends LineBreakpoint {
/**
* Family for breakpoint validation job (@see OCLToggleBreakpointAdapter::toggleLineBreakpoints())
*/
public static final @NonNull Object OCL_BREAKPOINT_JOBFAMILY = new Object();
protected static final String HIT_COUNT = DebugVMPlugin.PLUGIN_ID + ".hitCount"; //$NON-NLS-1$
protected static final int HIT_COUNT_UNDEFINED = -1;
/**
* Breakpoint attribute storing a breakpoint's conditional expression
*/
protected static final String CONDITION = DebugVMPlugin.PLUGIN_ID + ".condition"; //$NON-NLS-1$
/**
* Breakpoint attribute storing a breakpoint's condition enablement
*/
protected static final String CONDITION_ENABLED = DebugVMPlugin.PLUGIN_ID + ".conditionEnabled"; //$NON-NLS-1$
/**
* Breakpoint attribute storing a breakpoint's condition suspend policy
*/
protected static final String CONDITION_SUSPEND_ON_TRUE = DebugVMPlugin.PLUGIN_ID + ".conditionSuspendOnTrue"; //$NON-NLS-1$
protected static final String TARGET_URI_ATTR = DebugVMPlugin.PLUGIN_ID + ".unitUri"; //$NON-NLS-1$
protected static final String RUN_TO_LINE = DebugVMPlugin.PLUGIN_ID + ".runToLine"; //$NON-NLS-1$
/*
* Remark: Keep the default constructor to allow the breakpoint manager to create breakpoint from markers
*/
protected VMLineBreakpoint() {
super();
}
protected VMLineBreakpoint(final @NonNull URI sourceURI, int lineNumber, final boolean isRunToLine) throws CoreException {
final IFile sourceFile = getDebugCore().toFile(sourceURI);
final IResource markerResource = (sourceFile != null && !isRunToLine) ? sourceFile : ResourcesPlugin.getWorkspace().getRoot();
final Integer lineNum = Integer.valueOf(lineNumber);
IWorkspaceRunnable wr = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
// create the marker
IMarker marker = markerResource.createMarker(getDebugCore().getBreakpointMarkerId());
setMarker(marker);
// add attributes
final Map<String, Object> attributes = new HashMap<String, Object>();
if(isRunToLine) {
attributes.put(IBreakpoint.PERSISTED, Boolean.FALSE);
attributes.put(VMLineBreakpoint.RUN_TO_LINE, Boolean.TRUE);
}
attributes.put(IBreakpoint.ENABLED, Boolean.TRUE);
attributes.put(IMarker.LINE_NUMBER, lineNum);
attributes.put(IBreakpoint.ID, getModelIdentifier());
if(sourceFile == null || isRunToLine) {
attributes.put(TARGET_URI_ATTR, sourceURI.toString());
}
ensureMarker().setAttributes(attributes);
}
};
run(getMarkerRule(markerResource), wr);
}
public long getID() {
return getMarker().getId();
}
public URI getUnitURI() throws CoreException {
IMarker marker = getMarker();
IResource res = marker.getResource();
if(res.getType() == IResource.FILE) {
return VMDebugCore.getResourceURI(marker.getResource());
}
String uriStr = marker.getAttribute(TARGET_URI_ATTR, null);
assert uriStr != null;
return URI.createURI(uriStr);
}
public @NonNull VMNewBreakpointData createNewBreakpointData() throws CoreException {
@SuppressWarnings("null")@NonNull String string = getUnitURI().toString();
VMNewBreakpointData newBpData = createNewBreakpointData(string);
return newBpData;
}
public @NonNull VMNewBreakpointData createNewBreakpointData(@NonNull String targetURI) throws CoreException {
VMNewBreakpointData newBpData = new VMNewBreakpointData(isConditionEnabled(), getCondition(), isConditionSuspendOnTrue(), getHitCount(),
getID(), getLineNumber(), targetURI);
return newBpData;
}
public @NonNull VMBreakpointData createBreakpointData() throws CoreException {
VMBreakpointData bpData = new VMBreakpointData(isConditionEnabled(), getCondition(), isConditionSuspendOnTrue(), getHitCount());
return bpData;
}
@Override
public @NonNull String getModelIdentifier() {
return getDebugCore().getModelId();
}
protected abstract @NonNull VMDebugCore getDebugCore();
/**
* Add this breakpoint to the breakpoint manager,
* or sets it as unregistered.
*/
public void register(boolean register) throws CoreException {
if (register) {
DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(this);
} else {
setRegistered(false);
}
}
public int getHitCount() throws CoreException {
return ensureMarker().getAttribute(HIT_COUNT, HIT_COUNT_UNDEFINED);
}
public void setHitCount(int count) throws CoreException {
if (getHitCount() != count) {
if (!isEnabled() && count > -1) {
setAttributes(new String[] { ENABLED, HIT_COUNT },
new Object[] { Boolean.TRUE, Integer.valueOf(count) });
} else {
setAttributes(new String[] { HIT_COUNT },
new Object[] { Integer.valueOf(count) });
}
}
}
public boolean isLineToRunBreakpoint() {
return getMarker().getAttribute(VMLineBreakpoint.RUN_TO_LINE, false);
}
public boolean supportsCondition() {
return true;
}
public String getCondition() throws CoreException {
return ensureMarker().getAttribute(CONDITION, null);
}
public void setCondition(String condition) throws CoreException {
if (condition != null && condition.trim().length() == 0) {
condition = null;
}
setAttribute(CONDITION, condition);
}
public boolean isConditionEnabled() {
return getMarker().getAttribute(CONDITION_ENABLED, false);
}
public void setConditionEnabled(boolean conditionEnabled) throws CoreException {
setAttribute(CONDITION_ENABLED, Boolean.valueOf(conditionEnabled));
}
public boolean isConditionSuspendOnTrue() throws DebugException {
return ensureMarker().getAttribute(CONDITION_SUSPEND_ON_TRUE, true);
}
public void setConditionSuspendOnTrue(boolean suspendOnTrue) throws CoreException {
if (isConditionSuspendOnTrue() != suspendOnTrue) {
setAttribute(CONDITION_SUSPEND_ON_TRUE, Boolean.valueOf(suspendOnTrue));
}
}
}