blob: 816c99a10f22004cd777ce306b0f37e3b59d3a41 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2012 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.crossfire.jsdi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.debug.core.breakpoints.IJavaScriptBreakpoint;
import org.eclipse.wst.jsdt.debug.core.jsdi.BooleanValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.NullValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.NumberValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.ScriptReference;
import org.eclipse.wst.jsdt.debug.core.jsdi.StringValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.UndefinedValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine;
import org.eclipse.wst.jsdt.debug.core.jsdi.event.EventQueue;
import org.eclipse.wst.jsdt.debug.core.jsdi.request.EventRequestManager;
import org.eclipse.wst.jsdt.debug.core.model.JavaScriptDebugModel;
import org.eclipse.wst.jsdt.debug.internal.core.JavaScriptDebugPlugin;
import org.eclipse.wst.jsdt.debug.internal.core.breakpoints.JavaScriptLineBreakpoint;
import org.eclipse.wst.jsdt.debug.internal.crossfire.Constants;
import org.eclipse.wst.jsdt.debug.internal.crossfire.CrossFirePlugin;
import org.eclipse.wst.jsdt.debug.internal.crossfire.Tracing;
import org.eclipse.wst.jsdt.debug.internal.crossfire.event.CFEventQueue;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.Attributes;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFEventPacket;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFRequestPacket;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFResponsePacket;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.Commands;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.JSON;
import org.eclipse.wst.jsdt.debug.transport.DebugSession;
import org.eclipse.wst.jsdt.debug.transport.exception.DisconnectedException;
import org.eclipse.wst.jsdt.debug.transport.exception.TimeoutException;
/**
* Default CrossFire implementation of {@link VirtualMachine}
*
* @since 1.0
*/
public class CFVirtualMachine extends CFMirror implements VirtualMachine {
private final NullValue nullvalue = new CFNullValue(this);
private final UndefinedValue undefinedvalue = new CFUndefinedValue(this);
private final DebugSession session;
private final CFEventRequestManager ermanager = new CFEventRequestManager(this);
private final CFEventQueue queue = new CFEventQueue(this, ermanager);
private boolean disconnected = false;
private Map threads = null;
private Map scripts = null;
/**
* Constructor
*
* @param session
*/
public CFVirtualMachine(DebugSession session) {
super();
this.session = session;
initializeBreakpoints();
}
/**
* Synchronizes the set of breakpoints between client and server
*/
void initializeBreakpoints() {
IBreakpointManager manager = DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint[] managerBreakpoints = manager.getBreakpoints(JavaScriptDebugModel.MODEL_ID);
Vector allBps = new Vector();
for (int i = 0; i < managerBreakpoints.length; i++) {
IBreakpoint current = managerBreakpoints[i];
try {
if(!current.isRegistered()) {
continue;
}
if (current instanceof JavaScriptLineBreakpoint) {
JavaScriptLineBreakpoint breakpoint = (JavaScriptLineBreakpoint)current;
IResource resource = breakpoint.getMarker().getResource();
QualifiedName qName = new QualifiedName(JavaScriptCore.PLUGIN_ID, "scriptURL"); //$NON-NLS-1$
String url = resource.getPersistentProperty(qName);
if (url == null) {
String path = breakpoint.getScriptPath();
url = JavaScriptDebugPlugin.getExternalScriptPath(new Path(path));
}
if (url != null) {
Map location = new HashMap();
location.put(Attributes.LINE, new Integer(breakpoint.getLineNumber()));
location.put(Attributes.URL, url);
Map attributes = new HashMap();
if (breakpoint.isConditionEnabled()) {
String condition = breakpoint.getCondition();
if (condition != null) {
attributes.put(Attributes.CONDITION, condition);
}
}
attributes.put(Attributes.ENABLED, new Boolean(breakpoint.isEnabled()));
int hitCount = breakpoint.getHitCount();
if (hitCount != -1) {
attributes.put(Attributes.HIT_COUNT, new Integer(hitCount));
}
Map bpMap = new HashMap();
bpMap.put(Attributes.TYPE, Attributes.LINE);
bpMap.put(Attributes.LOCATION, location);
bpMap.put(Attributes.ATTRIBUTES, attributes);
allBps.add(bpMap);
}
}
} catch (CoreException e) {
CrossFirePlugin.log(e);
}
}
if (allBps.size() > 0) {
CFRequestPacket request = new CFRequestPacket(Commands.SET_BREAKPOINTS, null);
request.setArgument(Attributes.BREAKPOINTS, Arrays.asList(allBps.toArray()));
CFResponsePacket response = ((CFVirtualMachine)virtualMachine()).sendRequest(request);
if (response.isSuccess()) {
List list = (List)response.getBody().get(Attributes.BREAKPOINTS);
if (list != null && list.size() > 0) {
for (Iterator i = list.iterator(); i.hasNext();) {
Map bp = (Map)i.next();
if (bp != null) {
RemoteBreakpoint rb = BreakpointTracker.addBreakpoint((CFVirtualMachine) virtualMachine(), bp);
BreakpointTracker.findLocalBreakpoint(rb);
}
}
}
}
else if(TRACE) {
Tracing.writeString("VM [failed setbreakpoints request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
CFRequestPacket request = new CFRequestPacket(Commands.GET_BREAKPOINTS, null);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
List list = (List) response.getBody().get(Attributes.BREAKPOINTS);
Map bp = null;
for (Iterator i = list.iterator(); i.hasNext();) {
bp = (Map) i.next();
BreakpointTracker.addBreakpoint(this, bp);
}
}
else if(TRACE) {
Tracing.writeString("VM [failed getbreakpoints request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
/**
* Called via reflection to determine if the VM supports suspend on script loads
* @return <code>true</code> if this VM can suspend when a script loads <code>false</code> otherwise
*/
public boolean supportsSuspendOnScriptLoads() {
return false;
}
/**
* Adds or removes the breakpoint from the cache based on the <code>isset</code> attribute
*
* @param json the JSON map, cannot be <code>null</code>
*/
public void toggleBreakpoint(Map json) {
if(json != null) {
Boolean isset = (Boolean)json.get(Attributes.SET);
if(isset != null && isset.booleanValue()) {
Map bp = (Map) json.get(Attributes.BREAKPOINT);
RemoteBreakpoint rb = BreakpointTracker.updateBreakpoint(bp);
if(rb == null) {
BreakpointTracker.createLocalBreakpoint(this, bp);
}
}
else {
Map bp = (Map) json.get(Attributes.BREAKPOINT);
Number handle = (Number) bp.get(Attributes.HANDLE);
BreakpointTracker.removeLocalBreakpoint(this, handle);
}
}
}
/**
* @return the 'readiness' of the VM - i.e. is it in a state to process requests, etc
*/
boolean ready() {
return !disconnected;
}
/**
* Sends an <code>createcontext</code> request for the given URL and returns the status of the request.
*
* @param url the URL to open / update in the remote target, <code>null</code> is not accepted
* @return <code>true</code> if the request was successful, <code>false</code> otherwise
*/
boolean createContext(String url) {
if(url != null && ready()) {
CFRequestPacket request = new CFRequestPacket(Commands.CREATE_CONTEXT, null);
request.getArguments().put(Attributes.URL, url);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
return true;
}
else if(TRACE) {
Tracing.writeString("VM [failed createcontext request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return false;
}
/**
* Sends the frame request
* @param contextid
* @param index
* @param includescopes
* @return
*/
CFStackFrame getFrame(String contextid, int index, boolean includescopes) {
if(index > -1) {
CFThreadReference thread = findThread(contextid);
if(thread != null) {
CFRequestPacket request = new CFRequestPacket(Commands.FRAME, thread.id());
request.setArgument(Attributes.INDEX, new Integer(index));
request.setArgument(Attributes.INCLUDE_SCOPES, new Boolean(includescopes));
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
return new CFStackFrame(this, thread, response.getBody());
}
else if(TRACE) {
Tracing.writeString("VM [failed frame request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
}
return null;
}
/**
* Sends a request to enable the tool with the given name in the remote Crossfire server
*
* @param tools the array of tool names to enable, <code>null</code> is not allowed
* @return <code>true</code> if the server reports the tool became enabled, <code>false</code> otherwise
*/
boolean enableTools(String[] tools) {
if(tools != null && tools.length > 0 && ready()) {
CFRequestPacket request = new CFRequestPacket(Commands.ENABLE_TOOLS, null);
request.getArguments().put(Attributes.TOOLS, Arrays.asList(tools));
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
//TODO handle the tool being enabled
return true;
}
else if(TRACE) {
Tracing.writeString("VM [failed enabletool request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return false;
}
/**
* Sends a request to disable the tool with the given name in the remote Crossfire server
*
* @param tools the array of tool names to disable, <code>null</code> is not allowed
* @return <code>true</code> if the server reports the tool became disabled, <code>false</code> otherwise
*/
boolean disableTools(String[] tools) {
if(tools != null && tools.length > 0 && ready()) {
CFRequestPacket request = new CFRequestPacket(Commands.DISABLE_TOOLS, null);
request.getArguments().put(Attributes.TOOLS, Arrays.asList(tools));
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
//TODO handle the tool being disabled
return true;
}
else if(TRACE) {
Tracing.writeString("VM [failed disabletool request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return false;
}
/**
* Returns the complete listing of tools from Crossfire regardless of their enabled state.
*
* @return the listing of tools or an empty list, never <code>null</code>
*/
List allTools() {
if(ready()) {
CFRequestPacket request = new CFRequestPacket(Commands.GET_TOOLS, null);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
//TODO do we want to make these first-class objects in our model so we can track state, etc for tools?
List tools = (List) response.getBody().get(Attributes.TOOLS);
if(tools != null) {
return tools;
}
}
else if(TRACE) {
Tracing.writeString("VM [failed alltools request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#resume()
*/
public void resume() {
if(ready()) {
if(threads != null) {
Entry entry = null;
for (Iterator iter = threads.entrySet().iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
CFThreadReference thread = (CFThreadReference) entry.getValue();
if(thread.isSuspended()) {
CFRequestPacket request = new CFRequestPacket(Commands.CONTINUE, thread.id());
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
if(thread.isSuspended()) {
thread.markSuspended(false);
}
}
else if(TRACE) {
Tracing.writeString("VM [failed continue request][context: "+thread.id()+"]: "+JSON.serialize(request)); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#suspend()
*/
public void suspend() {
if(ready()) {
if(threads != null) {
Entry entry = null;
for (Iterator iter = threads.entrySet().iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
CFThreadReference thread = (CFThreadReference) entry.getValue();
if(thread.isRunning()) {
CFRequestPacket request = new CFRequestPacket(Commands.SUSPEND, thread.id());
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
if(!thread.isSuspended()) {
thread.markSuspended(true);
}
}
else if(TRACE) {
Tracing.writeString("VM [failed suspend request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#terminate()
*/
public void terminate() {
if(ready()) {
disconnectVM();
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#name()
*/
public String name() {
return Messages.vm_name;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#description()
*/
public String description() {
return Messages.crossfire_vm;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#version()
*/
public synchronized String version() {
if(ready()) {
CFRequestPacket request = new CFRequestPacket(Commands.VERSION, null);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
Map json = response.getBody();
return (String) json.get(Commands.VERSION);
}
if(TRACE) {
Tracing.writeString("VM [failed version request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return Constants.UNKNOWN;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#allThreads()
*/
public synchronized List allThreads() {
if(threads == null) {
threads = new HashMap();
CFRequestPacket request = new CFRequestPacket(Commands.LISTCONTEXTS, null);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
List contexts = (List) response.getBody().get(Attributes.CONTEXTS);
for (Iterator iter = contexts.iterator(); iter.hasNext();) {
Map json = (Map) iter.next();
CFThreadReference thread = new CFThreadReference(this, json);
threads.put(thread.id(), thread);
}
}
else if(TRACE) {
Tracing.writeString("VM [failed allthreads request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
return new ArrayList(threads.values());
}
/**
* Adds a thread to the listing
*
* @param id
* @param url
* @return the new thread
*/
public CFThreadReference addThread(String id, String url) {
if(threads == null) {
allThreads();
}
CFThreadReference thread = new CFThreadReference(this, id, url);
threads.put(thread.id(), thread);
return thread;
}
/**
* Removes the thread with the given id
*
* @param id the id of the thread to remove
*/
public void removeThread(String id) {
if(threads != null) {
Object obj = threads.remove(id);
if(TRACE && obj == null) {
Tracing.writeString("VM [failed to remove thread]: "+id); //$NON-NLS-1$
}
}
}
/**
* Returns the thread with the given id or <code>null</code>
*
* @param id
* @return the thread or <code>null</code>
*/
public synchronized CFThreadReference findThread(String id) {
if(threads == null) {
allThreads();
}
CFThreadReference thread = (CFThreadReference) threads.get(id);
if(TRACE && thread == null) {
Tracing.writeString("VM [failed to find thread]: "+id); //$NON-NLS-1$
}
return thread;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#allScripts()
*/
public synchronized List allScripts() {
if(scripts == null) {
scripts = new HashMap();
List threads = allThreads();
for (Iterator iter = threads.iterator(); iter.hasNext();) {
CFThreadReference thread = (CFThreadReference) iter.next();
CFRequestPacket request = new CFRequestPacket(Commands.SCRIPTS, thread.id());
request.setArgument(Attributes.INCLUDE_SOURCE, Boolean.FALSE);
CFResponsePacket response = sendRequest(request);
if(response.isSuccess()) {
List scriptz = (List) response.getBody().get(Attributes.SCRIPTS);
for (Iterator iter2 = scriptz.iterator(); iter2.hasNext();) {
Map smap = (Map) iter2.next();
if(smap != null) {
CFScriptReference script = new CFScriptReference(this, thread.id(), smap);
scripts.put(script.url(), script);
}
}
}
else if(TRACE) {
Tracing.writeString("VM [failed scripts request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
if(scripts.size() < 1) {
scripts = null;
return Collections.EMPTY_LIST;
}
}
return new ArrayList(scripts.values());
}
/**
* Returns the {@link ScriptReference} with the given URL or <code>null</code>
*
* @param url
* @return the {@link ScriptReference} or <code>null</code>
*/
public synchronized CFScriptReference findScript(String url) {
if(scripts == null) {
allScripts();
}
CFScriptReference script = null;
if(scripts != null) {
//the scripts collection can be null after a call to allScripts()
//when the remote target had no scripts loaded. In this case
//we do not keep the initialized collection so that any successive
//calls the this method or allScripts will cause the remote target
//to be asked for all of its scripts
script = (CFScriptReference) scripts.get(url);
}
//if we find we have a script id that is not cached, we should try a lookup + add in the VM
if(script == null) {
if(TRACE) {
Tracing.writeString("VM [failed to find script]: "+url); //$NON-NLS-1$
}
}
return script;
}
/**
* Adds the given script to the listing
*
* @param context_id
* @param json
*
* @return the new script
*/
public CFScriptReference addScript(String context_id, Map json) {
if(scripts == null) {
allScripts();
}
CFScriptReference script = new CFScriptReference(this, context_id, json);
scripts.put(script.url(), script);
return script;
}
/**
* Removes all {@link CFScriptReference}s from the cache when the associated context is destroyed
*
* @param contextid
*/
public void removeScriptsForContext(String contextid) {
if(scripts != null) {
Entry e = null;
for(Iterator i = scripts.entrySet().iterator(); i.hasNext();) {
e = (Entry) i.next();
if(contextid.equals(((CFScriptReference)e.getValue()).context())) {
i.remove();
}
}
}
}
/**
* Removes the script with the given URL from the listing
*
* @param url the script to remove
*/
public void removeScript(String url) {
if(scripts != null) {
Object obj = scripts.remove(url);
if(TRACE && obj == null) {
Tracing.writeString("VM [failed to remove script]: "+url); //$NON-NLS-1$
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#dispose()
*/
public synchronized void dispose() {
try {
if(TRACE) {
Tracing.writeString("VM [disposing]"); //$NON-NLS-1$
}
queue.dispose();
ermanager.dispose();
}
finally {
//fall-back in case the VM has been disposed but not disconnected
disconnectVM();
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#mirrorOfUndefined()
*/
public UndefinedValue mirrorOfUndefined() {
return undefinedvalue;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#mirrorOfNull()
*/
public NullValue mirrorOfNull() {
return nullvalue;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#mirrorOf(boolean)
*/
public BooleanValue mirrorOf(boolean bool) {
return new CFBooleanValue(this, bool);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#mirrorOf(java.lang.Number)
*/
public NumberValue mirrorOf(Number number) {
return new CFNumberValue(this, number);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#mirrorOf(java.lang.String)
*/
public StringValue mirrorOf(String string) {
return new CFStringValue(this, string);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#eventRequestManager()
*/
public synchronized EventRequestManager eventRequestManager() {
return ermanager;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#eventQueue()
*/
public synchronized EventQueue eventQueue() {
return queue;
}
/**
* Receives an {@link CFEventPacket} from the underlying {@link DebugSession},
* waiting for the {@link VirtualMachine#DEFAULT_TIMEOUT}.
*
* @return the next {@link CFEventPacket} never <code>null</code>
* @throws TimeoutException
* @throws DisconnectedException
*/
public CFEventPacket receiveEvent() throws TimeoutException, DisconnectedException {
return (CFEventPacket) session.receive(CFEventPacket.EVENT, DEFAULT_TIMEOUT);
}
/**
* Receives an {@link CFEventPacket} from the underlying {@link DebugSession},
* waiting for the {@link VirtualMachine#DEFAULT_TIMEOUT}.
* @param timeout
* @return the next {@link CFEventPacket} never <code>null</code>
* @throws TimeoutException
* @throws DisconnectedException
*/
public CFEventPacket receiveEvent(int timeout) throws TimeoutException, DisconnectedException {
return (CFEventPacket) session.receive(CFEventPacket.EVENT, timeout);
}
/**
* Sends a request to the underlying {@link DebugSession}, waiting
* for the {@link VirtualMachine#DEFAULT_TIMEOUT}.
*
* @param request
* @return the {@link CFResponsePacket} for the request
*/
public CFResponsePacket sendRequest(CFRequestPacket request) {
try {
session.send(request);
return (CFResponsePacket) session.receiveResponse(request.getSequence(), 3000);
}
catch(DisconnectedException de) {
disconnectVM();
handleException(de.getMessage(), (de.getCause() == null ? de : de.getCause()));
}
catch(TimeoutException te) {
CrossFirePlugin.log(te);
}
return CFResponsePacket.FAILED;
}
/**
* disconnects the VM
*/
public synchronized void disconnectVM() {
if (disconnected) {
// no-op it is already disconnected
if(TRACE) {
Tracing.writeString("VM [already disconnected]"); //$NON-NLS-1$
}
return;
}
if(TRACE) {
Tracing.writeString("VM [disconnecting]"); //$NON-NLS-1$
}
try {
if(threads != null) {
threads.clear();
}
if(scripts != null) {
scripts.clear();
}
this.queue.dispose();
this.ermanager.dispose();
this.session.dispose();
BreakpointTracker.disconnect(this);
} finally {
disconnected = true;
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#canUpdateBreakpoints()
*/
public boolean canUpdateBreakpoints() {
return true;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine#updateBreakpoint(org.eclipse.wst.jsdt.debug.core.breakpoints.IJavaScriptBreakpoint)
*/
public void updateBreakpoint(IJavaScriptBreakpoint breakpoint) {
RemoteBreakpoint rb = BreakpointTracker.findRemoteBreakpoint(breakpoint);
if(rb != null) {
try {
BreakpointTracker.syncRemoteBreakpoint(rb, breakpoint);
CFRequestPacket request = new CFRequestPacket(Commands.CHANGE_BREAKPOINT, null);
request.setArgument(Attributes.HANDLE, rb.getHandle());
HashMap attributes = new HashMap();
attributes.put(Attributes.ENABLED, Boolean.valueOf(rb.isEnabled()));
attributes.put(Attributes.CONDITION, rb.getCondition());
request.setArgument(Attributes.ATTRIBUTES, attributes);
CFResponsePacket response = sendRequest(request);
if(!response.isSuccess() && TRACE) {
Tracing.writeString("VM [failed changebreakpoint request]: "+JSON.serialize(request)); //$NON-NLS-1$
}
}
catch(CoreException ce) {
//if we could not sync do not send a request
}
}
}
}