/* * Created on 23.11.2004 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package net.sourceforge.phpeclipse.xdebug.php.model; import java.util.Arrays; import java.util.Collections; import java.util.Vector; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils; import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugResponse; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.model.IWorkbenchAdapter; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * @author Axel * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class XDebugThread extends XDebugElement implements IThread, IDebugEventSetListener { private XDebugStackFrame[] fStackFrames; private IBreakpoint[] fBreakpoints; private boolean fStepping = false; // Whether this thread is stepping private boolean fTerminated = false; private int fStepCount = 0; private int fCurrentStepCount = 0; private Vector stackListOld = new Vector(); // The 'static' list of stack frames /** * Constructs a new thread for the given target * * @param target VM */ public XDebugThread(XDebugTarget target) { super(target); DebugPlugin.getDefault().addDebugEventListener(this); fStackFrames = null; } /** * */ public void setStackFrames (XDebugStackFrame[] frames) { this.fStackFrames = frames; } public void incrementStepCounter() { fStepCount++; } /** * * @param arg0 * @return */ public Object getAdapter (Class arg0) { if (IWorkbenchAdapter.class.equals (arg0)) { return new IWorkbenchAdapter() { public Object[] getChildren(Object o) { try { return getStackFrames (); } catch (DebugException x) { PHPeclipsePlugin.log ("Unable to get stack frames.", x); } return new Object[0]; } public ImageDescriptor getImageDescriptor(Object object) { return null; } public String getLabel(Object o) { throw new UnsupportedOperationException(); } public Object getParent(Object o) { return getDebugTarget(); } }; } return super.getAdapter(arg0); } /** * Reset the availability flag for all stackframes in the list. * * @param list The list of old stackframes */ private void resetAvailability (Vector list) { int i; for (i = 0; i < list.size (); i++) { ((XDebugStackFrame) list.get(i)).setAvailable (false); // } } /** * Check whether the new stackframe is in the list of old stackframes. * Test for identical stackframe (identical means same description and same line number). * * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list * @param list The list of old stackframes * @return * - true if we have found the identical stackframe within the list * - false if we did not find the identical stackframe within the list */ private boolean isStackFrameInList (XDebugStackFrame stackFrameNew, Vector list) { int i; XDebugStackFrame stackFrameOld; for (i = 0; i < list.size (); i++) { stackFrameOld = (XDebugStackFrame) list.get (i); // if (stackFrameNew.getFullName ().equals (stackFrameOld.getFullName ()) && stackFrameNew.getDescription ().equals (stackFrameOld.getDescription ()) && stackFrameNew.getLineNumber () == stackFrameOld.getLineNumber ()) { // Did we find the sent stackframe within the list of old stackframes? stackFrameOld.setAvailable (true); // We found the new stackframe in the list of old stack frames stackFrameOld.setLevel (stackFrameNew.getLevel ()); stackFrameOld.setUpToDate (false); // Need to update the variables return true; // The stackframe was found in the list } } return false; } /** * Check whether the new stackframe is in the list of old stackframes. * Test for exact stackframe (exact means same description and same line number). * * @param stackFrameNew The stackframe to check whether he is already within the old stackframe list * @param list The list of old stackframes * @return * - true if we have exactly this stackframe within the list * - false if we did not find the exact stackframe within the list */ private void markIdenticalStackFrames (Vector oldList, Vector newList) { int i; XDebugStackFrame stackFrameNew; resetAvailability (oldList); // Reset the availability flag of the old stack frames resetAvailability (newList); // Reset the availability flag of the old stack frames for (i = 0; i < newList.size (); i++) { // For all stackList entries stackFrameNew = (XDebugStackFrame) newList.get (i); if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list stackFrameNew.setAvailable (true); // // // break; } } } /** * * The stackList contains the currently read stackframes which were sent * from DBG. The DBG interface holds a list of the active stack frames. * This method replicates the 'static' stackframe list with the DBG stackframe list * Replication is done in the following way: *
null
* if none.
*
* @param breakpoints the breakpoints this thread is suspended at, or null
* if none
*/
protected void setBreakpoints(IBreakpoint[] breakpoints) {
fBreakpoints = breakpoints;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canResume()
*/
public boolean canResume() {
return isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
*/
public boolean canSuspend() {
return !isTerminated() && !isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
*/
public boolean isSuspended() {
return getDebugTarget().isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#resume()
*/
public void resume() throws DebugException {
fBreakpoints = null;
getDebugTarget().resume();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ISuspendResume#suspend()
*/
public void suspend() throws DebugException {
getDebugTarget().suspend();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepInto()
*/
public boolean canStepInto() {
return isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepOver()
*/
public boolean canStepOver() {
return isSuspended();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepReturn()
*/
public boolean canStepReturn() {
if (fStackFrames != null) {
return (fStackFrames.length > 1);
} else {
return false;
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#isStepping()
*/
public boolean isStepping() {
return fStepping;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepInto()
*/
public void stepInto() throws DebugException {
fBreakpoints = null;
((XDebugTarget) getDebugTarget()).step_into();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepOver()
*/
public void stepOver() throws DebugException {
fBreakpoints = null;
((XDebugTarget) getDebugTarget()).step_over();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepReturn()
*/
public void stepReturn() throws DebugException {
fBreakpoints = null;
((XDebugTarget) getDebugTarget()).step_out();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#canTerminate()
*/
public boolean canTerminate() {
return !isTerminated();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#isTerminated()
*/
public boolean isTerminated() {
return fTerminated;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ITerminate#terminate()
*/
public void terminate() throws DebugException {
((XDebugTarget) getDebugTarget()).getDebugConnection().stop();
fTerminated = true;
}
public void terminated() throws DebugException {
fTerminated = true;
}
/**
* Sets whether this thread is stepping
*
* @param stepping whether stepping
*/
protected void setStepping(boolean stepping) {
fStepping = stepping;
}
public void handleDebugEvents(DebugEvent[] events) {
DebugEvent de = events[0];
System.out.println(de.toString());
}
public void removeEventListeners() {
DebugPlugin.getDefault().removeDebugEventListener(this);
}
/**
* Fires a RESUME
event for this element with
* the given detail.
*
* @param detail event detail code
*/
public void fireResumeEvent(int detail) {
fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
}
/**
* Fires a SUSPEND
event for this element with
* the given detail.
*
* @param detail event detail code
*/
public void fireSuspendEvent (int detail) {
fireEvent (new DebugEvent (this, DebugEvent.SUSPEND, detail));
}
}