/******************************************************************************* * Copyright (c) 2009 R.Dvorak 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: * 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(); } }