blob: c2d92f1609154610ab755a77cf53f45e1daa4fef [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 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.rhino.jsdi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame;
import org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference;
import org.eclipse.wst.jsdt.debug.internal.rhino.RhinoDebugPlugin;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.DisconnectedException;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.JSONConstants;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.Request;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.Response;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.TimeoutException;
/**
* Rhino implementation of {@link ThreadReference}
*
* @since 1.0
*/
public class ThreadReferenceImpl extends MirrorImpl implements ThreadReference {
private Number threadId;
private List frames;
private int status = THREAD_STATUS_RUNNING;
private boolean suspended;
private boolean atBreakpoint = false;
private String name;
private String step;
/**
* Constructor
*
* @param vm
* @param jsonThread
*/
public ThreadReferenceImpl(VirtualMachineImpl vm, Map jsonThread) {
super(vm);
this.threadId = (Number) jsonThread.get(JSONConstants.THREAD_ID);
this.name = (String) jsonThread.get(JSONConstants.NAME);
if (this.name == null) {
// TODO NLS this
this.name = "Rhino - " + threadId; //$NON-NLS-1$
}
this.suspended = JSONConstants.SUSPENDED.equals(jsonThread.get(JSONConstants.STATE));
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#frameCount()
*/
public synchronized int frameCount() {
frames();
return (frames == null ? 0 : frames.size());
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#frame(int)
*/
public synchronized StackFrame frame(int index) {
frames();
return (StackFrame) frames.get(index);
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#frames()
*/
public synchronized List frames() {
if (!suspended || status == THREAD_STATUS_ZOMBIE) {
return Collections.EMPTY_LIST;
}
if (frames != null) {
return frames;
}
Request request = new Request(JSONConstants.FRAMES);
request.getArguments().put(JSONConstants.THREAD_ID, threadId);
try {
Response response = vm.sendRequest(request, 30000);
List frameIds = (List) response.getBody().get(JSONConstants.FRAMES);
if (frameIds.isEmpty()) {
return Collections.EMPTY_LIST;
}
frames = new ArrayList();
for (Iterator iterator = frameIds.iterator(); iterator.hasNext();) {
Long frameId = new Long(((Number) iterator.next()).longValue());
StackFrameImpl frame = createStackFrame(frameId);
frames.add(frame);
}
} catch (DisconnectedException e) {
handleException(e.getMessage(), e);
} catch (TimeoutException e) {
RhinoDebugPlugin.log(e);
}
if(frames != null) {
return frames;
}
return Collections.EMPTY_LIST;
}
/**
* Sends a request to make a new {@link StackFrameReference} in the current debugger.
* Returns a new {@link StackFrameReference} on success, <code>null</code> on failure
*
* @param frameId
* @return a new {@link StackFrameReference} or <code>null</code>
*/
private StackFrameImpl createStackFrame(Long frameId) {
Request request = new Request(JSONConstants.FRAME);
request.getArguments().put(JSONConstants.THREAD_ID, threadId);
request.getArguments().put(JSONConstants.FRAME_ID, frameId);
try {
Response response = vm.sendRequest(request);
Map jsonFrame = (Map) response.getBody().get(JSONConstants.FRAME);
return new StackFrameImpl(vm, jsonFrame);
} catch (DisconnectedException e) {
handleException(e.getMessage(), e);
} catch (TimeoutException e) {
RhinoDebugPlugin.log(e);
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#isAtBreakpoint()
*/
public synchronized boolean isAtBreakpoint() {
return suspended && atBreakpoint;
}
/**
* Marks the current thread reference as suspended
*
* @param atBreakpoint
*/
public synchronized void markSuspended(boolean atBreakpoint) {
this.suspended = true;
this.atBreakpoint = atBreakpoint;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#isSuspended()
*/
public synchronized boolean isSuspended() {
return suspended;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#name()
*/
public String name() {
return name;
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#resume()
*/
public synchronized void resume() {
if (status == THREAD_STATUS_ZOMBIE) {
return;
}
Request request = new Request(JSONConstants.CONTINUE);
request.getArguments().put(JSONConstants.THREAD_ID, threadId);
if (step != null) {
request.getArguments().put(JSONConstants.STEP, step);
}
try {
Response response = vm.sendRequest(request);
if (response.isSuccess()) {
step = null;
frames = null;
suspended = false;
atBreakpoint = false;
}
} catch (DisconnectedException e) {
handleException(e.getMessage(), e);
} catch (TimeoutException e) {
RhinoDebugPlugin.log(e);
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#suspend()
*/
public synchronized void suspend() {
if (status == THREAD_STATUS_ZOMBIE) {
return;
}
Request request = new Request(JSONConstants.SUSPEND);
request.getArguments().put(JSONConstants.THREAD_ID, threadId);
try {
Response response = vm.sendRequest(request);
if(response.isSuccess()) {
markSuspended(false);
}
} catch (DisconnectedException e) {
handleException(e.getMessage(), e);
} catch (TimeoutException e) {
RhinoDebugPlugin.log(e);
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#interrupt()
*/
public void interrupt() {
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.ThreadReference#status()
*/
public synchronized int status() {
return status;
}
/**
* Returns the step type
*
* @return the step type
* @see JSONConstants#STEP_IN
* @see JSONConstants#STEP_NEXT
* @see JSONConstants#STEP_OUT
*/
public synchronized String getStep() {
return step;
}
/**
* Sets the current step type
*
* @param step
* @see JSONConstants#STEP_IN
* @see JSONConstants#STEP_NEXT
* @see JSONConstants#STEP_OUT
*/
public synchronized void setStep(String step) {
this.step = step;
}
}