| /******************************************************************************* |
| * Copyright (c) 2009, 2018 R.Dvorak 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: |
| * Radek Dvorak - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.m2m.qvt.oml.debug.core.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.m2m.internal.qvt.oml.common.util.LineNumberProvider; |
| import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit; |
| import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.BreakpointData; |
| import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.NewBreakpointData; |
| import org.eclipse.ocl.utilities.ASTNode; |
| |
| |
| public class VMBreakpointManager { |
| |
| private final Map<EObject, VMBreakpoint> fElement2Breakpoint; |
| |
| private final UnitManager fUnitManager; |
| |
| // 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 |
| long fPrivateBreakpointID = 0; |
| |
| |
| public VMBreakpointManager(CompiledUnit mainUnit) { |
| if(mainUnit == null) { |
| throw new IllegalArgumentException("null main unit"); //$NON-NLS-1$ |
| } |
| |
| fUnitManager = new UnitManager(mainUnit); |
| fElement2Breakpoint = new HashMap<EObject, VMBreakpoint>(); |
| } |
| |
| public UnitManager getUnitManager() { |
| return fUnitManager; |
| } |
| |
| public synchronized List<VMBreakpoint> getBreakpoints(ASTNode e) { |
| VMBreakpoint breakpoint = fElement2Breakpoint.get(e); |
| return (breakpoint != null) ? Collections.singletonList(breakpoint) : Collections.<VMBreakpoint>emptyList(); |
| } |
| |
| |
| public synchronized VMBreakpoint createBreakpoint(NewBreakpointData data) { |
| // FIXME - raise CoreEXxc... for invalid uris |
| URI uri = URI.createURI(data.targetURI); |
| |
| // 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.line; |
| ASTNode targetElement = getBreakpointableElement(uri, line); |
| if(targetElement == null) { |
| return null; |
| } |
| |
| VMBreakpoint vmBreakpoint = new VMBreakpoint(targetElement, data, false); |
| fElement2Breakpoint.put(targetElement, vmBreakpoint); |
| return vmBreakpoint; |
| } |
| |
| |
| public synchronized VMBreakpoint createVMPrivateBreakpoint(URI unitURI, ASTNode element, int line, boolean isTemporary) throws CoreException { |
| NewBreakpointData bpData = new NewBreakpointData(); |
| bpData.ID = --fPrivateBreakpointID; |
| bpData.targetURI = unitURI.toString(); |
| bpData.line = line; |
| |
| VMBreakpoint breakpoint = new VMBreakpoint(element, bpData, isTemporary); |
| fElement2Breakpoint.put(element, breakpoint); |
| return breakpoint; |
| } |
| |
| |
| public synchronized VMBreakpoint[] getAllBreakpoints() { |
| return fElement2Breakpoint.values().toArray(new VMBreakpoint[fElement2Breakpoint.size()]); |
| } |
| |
| public synchronized ASTNode getBreakpointableElement(URI targetURI, int lineNumber) { |
| LineNumberProvider lineNumberProvider = fUnitManager.getLineNumberProvider(targetURI); |
| if(lineNumberProvider == null) { |
| return null; |
| } |
| |
| CompiledUnit unit = fUnitManager.getCompiledModule(targetURI); |
| List<ASTNode> elements = ValidBreakpointLocator.getBreakpointableElementsForLine(unit, lineNumberProvider, lineNumber); |
| if(elements.isEmpty()) { |
| return null; |
| } |
| |
| return elements.get(0); |
| } |
| |
| |
| public boolean removeBreakpoint(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, BreakpointData data) { |
| NewBreakpointData newBreakpointData = null; |
| |
| for(Map.Entry<EObject, VMBreakpoint> entry : fElement2Breakpoint.entrySet()) { |
| VMBreakpoint next = entry.getValue(); |
| if(breakpointID == next.getID()) { |
| fElement2Breakpoint.remove(entry.getKey()); |
| |
| |
| newBreakpointData = new NewBreakpointData( |
| breakpointID, next.getLineNumber(), next.getUri(), data); |
| break; |
| } |
| } |
| |
| if(newBreakpointData != null) { |
| createBreakpoint(newBreakpointData); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| private boolean isPlatformDeployed() { |
| CompiledUnit mainUnit = getUnitManager().getMainUnit(); |
| return mainUnit.getURI().isPlatformPlugin(); |
| } |
| } |