blob: 6d68a5f034fa001c3db2ce412de746772e0398b8 [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;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.debug.vm.core.VMDebugCore;
import org.eclipse.ocl.examples.debug.vm.data.VMBreakpointData;
import org.eclipse.ocl.examples.debug.vm.data.VMNewBreakpointData;
import org.eclipse.ocl.examples.debug.vm.utils.CompiledUnit;
import org.eclipse.ocl.examples.debug.vm.utils.LineNumberProvider;
import org.eclipse.ocl.pivot.Element;
public class VMBreakpointManager
{
protected final @NonNull VMVirtualMachine vmVirtualMachine;
private final @NonNull UnitManager fUnitManager;
private final @NonNull Map<EObject, VMBreakpoint> fElement2Breakpoint = new HashMap<EObject, VMBreakpoint>();
// FIXME - Simulates an fBreakpointID that does not come from the VM client
// based on the knowledge that marker long fBreakpointID is used (positive number)
// this one will be negative long
private long fPrivateBreakpointID = 0;
public VMBreakpointManager(@NonNull VMVirtualMachine vmVirtualMachine, @Nullable CompiledUnit mainUnit) {
if(mainUnit == null) {
throw new IllegalArgumentException("null main unit"); //$NON-NLS-1$
}
this.vmVirtualMachine = vmVirtualMachine;
fUnitManager = new UnitManager(mainUnit);
}
public @NonNull VMDebugCore getDebugCore() {
return vmVirtualMachine.getDebugCore();
}
public @NonNull UnitManager getUnitManager() {
return fUnitManager;
}
public synchronized @NonNull List<VMBreakpoint> getBreakpoints(Element e) {
VMBreakpoint breakpoint = fElement2Breakpoint.get(e);
return (breakpoint != null) ? Collections.singletonList(breakpoint) : Collections.<VMBreakpoint>emptyList();
}
public synchronized @Nullable VMBreakpoint createBreakpoint(VMNewBreakpointData data) {
// FIXME - raise CoreEXxc... for invalid uris
URI uri = URI.createURI(data.getTargetURI());
// FIXME - a temp hack to get correct source URI when running a separate VM
if (uri.isPlatformResource() && isPlatformDeployed()) {
uri = URI.createPlatformPluginURI(uri.toPlatformString(true), true);
}
if (fUnitManager.getCompiledModule(uri) == null) {
// FIXME - unify on using encoded form, only UI should receive decoded
uri = URI.createURI(URI.decode(uri.toString()));
}
int line = data.getLine();
Element targetElement = getBreakpointableElement(uri, line);
if(targetElement == null) {
return null;
}
VMBreakpoint vmBreakpoint = vmVirtualMachine.createBreakpoint(targetElement, data, false);
fElement2Breakpoint.put(targetElement, vmBreakpoint);
return vmBreakpoint;
}
public synchronized @NonNull VMBreakpoint createVMPrivateBreakpoint(URI unitURI, @NonNull Element element, int line, boolean isTemporary) throws CoreException {
@SuppressWarnings("null")@NonNull String string = unitURI.toString();
VMBreakpoint breakpoint = vmVirtualMachine.createBreakpoint(element, --fPrivateBreakpointID, line, string, isTemporary);
fElement2Breakpoint.put(element, breakpoint);
return breakpoint;
}
public synchronized VMBreakpoint[] getAllBreakpoints() {
return fElement2Breakpoint.values().toArray(new VMBreakpoint[fElement2Breakpoint.size()]);
}
public synchronized Element getBreakpointableElement(@NonNull URI targetURI, int lineNumber) {
LineNumberProvider lineNumberProvider = fUnitManager.getLineNumberProvider(targetURI);
if (lineNumberProvider == null) {
return null;
}
CompiledUnit unit = fUnitManager.getCompiledModule(targetURI);
if (unit == null) {
return null;
}
List<Element> elements = vmVirtualMachine.getRunnerFactory().getValidBreakpointLocator().getBreakpointableElementsForLine(unit, lineNumberProvider, lineNumber);
if (elements.isEmpty()) {
return null;
}
return elements.get(0);
}
public boolean removeBreakpoint(@NonNull VMBreakpoint breakpoint) {
return removeBreakpoint(breakpoint.getID());
}
public synchronized boolean removeBreakpoint(long breakpointID) {
for(Map.Entry<EObject, VMBreakpoint> entry : fElement2Breakpoint.entrySet()) {
VMBreakpoint next = entry.getValue();
if(breakpointID == next.getID()) {
fElement2Breakpoint.remove(entry.getKey());
return true;
}
}
return false;
}
public synchronized boolean changeBreakpoint(long breakpointID, @Nullable VMBreakpointData data) {
VMNewBreakpointData newBreakpointData = null;
for(Map.Entry<EObject, VMBreakpoint> entry : fElement2Breakpoint.entrySet()) {
VMBreakpoint next = entry.getValue();
if(breakpointID == next.getID()) {
fElement2Breakpoint.remove(entry.getKey());
if (data != null) {
newBreakpointData = new VMNewBreakpointData(data, breakpointID, next.getLineNumber(), next.getUri());
}
break;
}
}
if(newBreakpointData != null) {
createBreakpoint(newBreakpointData);
return true;
}
return false;
}
private boolean isPlatformDeployed() {
CompiledUnit mainUnit = getUnitManager().getMainUnit();
return mainUnit.getURI().isPlatformPlugin();
}
}