X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java new file mode 100644 index 0000000..04099c4 --- /dev/null +++ b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java @@ -0,0 +1,638 @@ +/** + * + */ +package net.sourceforge.phpeclipse.xdebug.php.model; + +import net.sourceforge.phpeclipse.xdebug.core.Base64; +import net.sourceforge.phpeclipse.xdebug.core.DebugConnection; +import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils; +import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin; +import net.sourceforge.phpeclipse.xdebug.core.DebugConnection.DebugResponse; +import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IMarkerDelta; +import org.eclipse.core.runtime.CoreException; +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.ILaunch; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.ILineBreakpoint; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IValue; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author Christian + * + */ +public class XDebugTarget extends XDebugElement implements IDebugTarget, + IDebugEventSetListener { + // associated system process (VM) + private IProcess fProcess; + + // containing launch object + private ILaunch fLaunch; + + // debugPort + private int fDebugPort; + + // program name + // private String fName; + + // suspend state + private boolean fSuspended = true; + + // terminated state + private boolean fTerminated = false; + + // threads + private XDebugThread fThread; + + private IThread[] fThreads; + + // event dispatch job + // private EventDispatchJob fEventDispatch; + + private DebugConnection fDebugConnection; + + // private DebugResponse lastResponse; + + /** + * Constructs a new debug target in the given launch for the associated PDA + * VM process. + * + * @param launch + * containing launch + * @param debugPort + * port to read events from + * @exception CoreException + * if unable to connect to host + */ + public XDebugTarget(ILaunch launch, IProcess process, int debugPort) + throws CoreException { + super(null); + fLaunch = launch; + fProcess = process; + fTarget = this; + fDebugConnection = new DebugConnection(this, debugPort); + fThread = new XDebugThread(this); + fThreads = new IThread[] { fThread }; + DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener( + this); + DebugPlugin.getDefault().addDebugEventListener(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugTarget#getProcess() + */ + public IProcess getProcess() { + return fProcess; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugTarget#getThreads() + */ + public IThread[] getThreads() throws DebugException { + return fThreads; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads() + */ + public boolean hasThreads() throws DebugException { + return (fThreads.length > 0); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugTarget#getName() + */ + public String getName() throws DebugException { + return "PHP XDebug Client at localhost:" + fDebugPort; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint) + */ + public boolean supportsBreakpoint(IBreakpoint breakpoint) { + if (breakpoint.getModelIdentifier().equals( + IXDebugConstants.ID_PHP_DEBUG_MODEL)) { + return true; + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget() + */ + public IDebugTarget getDebugTarget() { + return this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDebugElement#getLaunch() + */ + public ILaunch getLaunch() { + return fLaunch; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ITerminate#canTerminate() + */ + public boolean canTerminate() { + return getProcess().canTerminate(); + // return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ITerminate#isTerminated() + */ + public boolean isTerminated() { + // return getProcess().isTerminated(); + return fTerminated; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ITerminate#terminate() + */ + public void terminate() throws DebugException { + fDebugConnection.sendRequest("stop"); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ISuspendResume#canResume() + */ + public boolean canResume() { + return !isTerminated() && 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 fSuspended; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ISuspendResume#resume() + */ + public void resume() throws DebugException { + fDebugConnection.sendRequest("run"); + } + + /** + * Notification the target has resumed for the given reason + * + * @param detail + * reason for the resume + */ + private void resumed(int detail) { + fSuspended = false; + fThread.fireResumeEvent(detail); + } + + /** + * Notification the target has suspended for the given reason + * + * @param detail + * reason for the suspend + */ + public void suspended(int detail) { + fSuspended = true; + fThread.fireSuspendEvent(detail); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.ISuspendResume#suspend() + */ + public void suspend() throws DebugException { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint) + */ + public void breakpointAdded(IBreakpoint breakpoint) { + + if (supportsBreakpoint(breakpoint)) { + try { + if (breakpoint.isEnabled()) { + IMarker marker = breakpoint.getMarker(); + if (marker != null) { + try { + String fileName = PHPDebugUtils.escapeString(marker + .getResource().getLocation().toString()); + String arg = "-t line -f file:///" + + fileName + + " -n " + + ((ILineBreakpoint) breakpoint) + .getLineNumber(); + int id = fDebugConnection.sendRequest( + "breakpoint_set", arg); + // set the marker Attribute to make later + // idetification possible + // TODO: make sure that attribute is set before + // response from debugger is beeing prosessed + marker.setAttribute( + XDebugLineBreakpoint.BREAKPOINT_ID, id); + + } catch (CoreException e) { + } + } + } + } catch (CoreException e) { + + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, + * org.eclipse.core.resources.IMarkerDelta) + */ + public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) { + if (supportsBreakpoint(breakpoint)) { + try { + int id = ((XDebugLineBreakpoint) breakpoint).getID(); + if (id > 0) + fDebugConnection.sendRequest("breakpoint_remove", "-d " + + id); + } catch (CoreException e) { + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, + * org.eclipse.core.resources.IMarkerDelta) + */ + public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) { + // if (supportsBreakpoint(breakpoint)) { + // try { + // if (breakpoint.isEnabled()) { + // breakpointAdded(breakpoint); + // } else { + // breakpointRemoved(breakpoint, null); + // } + // } catch (CoreException e) { + // } + // } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect() + */ + public boolean canDisconnect() { + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDisconnect#disconnect() + */ + public void disconnect() throws DebugException { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected() + */ + public boolean isDisconnected() { + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval() + */ + public boolean supportsStorageRetrieval() { + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, + * long) + */ + public IMemoryBlock getMemoryBlock(long startAddress, long length) + throws DebugException { + return null; + } + + /** + * Notification we have connected to the PHP debugger and it has started. + * Resume the the debugger. + */ + public void started() { + + fThread.setBreakpoints(null); + fThread.setStepping(false); + + installDeferredBreakpoints(); + try { + resume(); + // step(); + } catch (DebugException e) { + } + } + + /** + * Install breakpoints that are already registered with the breakpoint + * manager. + */ + private void installDeferredBreakpoints() { + IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints(); + for (int i = 0; i < breakpoints.length; i++) { + breakpointAdded(breakpoints[i]); + } + } + + /** + * Called when this debug target terminates. + */ + public void terminated() { + fTerminated = true; + fSuspended = false; + XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this); + fireTerminateEvent(); + DebugPlugin.getDefault().removeDebugEventListener(this); + fThread.removeEventListeners(); + } + + /** + * Returns the current stack frames in the target. + * + * @return the current stack frames in the target + * @throws DebugException + * if unable to perform the request + */ + protected IStackFrame[] getStackFrames() throws DebugException { + int id = fDebugConnection.sendRequest("stack_get"); + DebugResponse lastResponse = fDebugConnection.waitforTransID(id); + if (lastResponse.isError()) + return new IStackFrame[0]; + Node response = lastResponse.getParentNode(); + NodeList frames = response.getChildNodes(); + IStackFrame[] theFrames = new IStackFrame[frames.getLength()]; + for (int i = 0; i < frames.getLength(); i++) { + Node stackNode = frames.item(i); + theFrames[i] = new XDebugStackFrame(fThread, stackNode, i); + } + return theFrames; + } + + /** + * Single step the interpreter. + * + * @throws DebugException + * if the request fails + */ + protected void step_over() throws DebugException { + fThread.setStepping(true); + resumed(DebugEvent.STEP_OVER); + fDebugConnection.sendRequest("step_over"); + } + + /** + * Single step the interpreter. + * + * @throws DebugException + * if the request fails + */ + protected void step_into() throws DebugException { + fThread.setStepping(true); + resumed(DebugEvent.STEP_INTO); + fDebugConnection.sendRequest("step_into"); + } + + /** + * Single step the interpreter. + * + * @throws DebugException + * if the request fails + */ + protected void step_out() throws DebugException { + fThread.setStepping(true); + resumed(DebugEvent.STEP_RETURN); + fDebugConnection.sendRequest("step_out"); + } + + /** + * Returns the current value of the given variable. + * + * @param variable + * @return variable value + * @throws DebugException + * if the request fails + */ + protected IValue getVariableValue(XDebugVariable variable) + throws DebugException { + // synchronized (fDebugSocket) { + // fDebugConnection.sendRequest("var","" + + // variable.getStackFrame().getIdentifier() + " " + variable.getName()); + // try { + // String value = fDebugReader.readLine(); + // //return new XDebugValue(this, value); + // + // } catch (IOException e) { + // abort(MessageFormat.format("Unable to retrieve value for variable + // {0}", new String[]{variable.getName()}), e); + // } + // } + return null; + } + + /** + * Returns the values on the data stack (top down) + * + * @return the values on the data stack (top down) + */ + public IValue[] getDataStack() throws DebugException { + // synchronized (fDebugSocket) { + // fDebugConnection.sendRequest ("data"); + // try { + // String valueString = fDebugReader.readLine(); + // if (valueString != null && valueString.length() > 0) { + // String[] values = valueString.split("\\|"); + // IValue[] theValues = new IValue[values.length]; + // for (int i = 0; i < values.length; i++) { + // String value = values[values.length - i - 1]; + // // theValues[i] = new XDebugValue(this, value); + // } + // return theValues; + // } + // } catch (IOException e) { + // abort("Unable to retrieve data stack", e); + // } + // } + return new IValue[0]; + } + + public boolean setVarValue(String name, String value) { + int id = -1; + String str = Base64.encodeBytes(value.getBytes()); + int len = str.length(); + + try { + id = fDebugConnection.sendRequest("property_set", "-n " + name + + " -l " + len + " -- " + str); + } catch (DebugException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + DebugResponse dr = getResponse(id); + if ((dr.getAttributeValue("success")).equals("1")) + return true; + + return false; + } + + public DebugResponse getResponse(int id) { + return fDebugConnection.waitforTransID(id); + } + + /** + * Sends a request to the Debugengine and waits for an OK. + * + * @param command + * debug command + * @throws DebugException + * if the request fails + */ + + public int sendRequest(String command) throws DebugException { + return fDebugConnection.sendRequest(command, ""); + } + + /** + * Sends a request to the Debugengine and waits for an OK. + * + * @param command + * debug command + * @arguments arguments for the command + * @throws DebugException + * if the request fails + */ + + public int sendRequest(String command, String arguments) + throws DebugException { + return fDebugConnection.sendRequest(command, arguments); + } + + /** + * Notification a breakpoint was encountered. Determine which breakpoint was + * hit and fire a suspend event. + * + * @param event + * debug event + */ + public void breakpointHit(Node node) { + // determine which breakpoint was hit, and set the thread's breakpoint + Node child = node.getFirstChild(); + if (child.getNodeName().equals("stack")) { + int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue( + child, "lineno")); + String filename = PHPDebugUtils + .getAttributeValue(child, "filename").substring(8); // remove + // file:/// + IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints(); + for (int i = 0; i < breakpoints.length; i++) { + IBreakpoint breakpoint = breakpoints[i]; + if (supportsBreakpoint(breakpoint)) { + if (breakpoint instanceof ILineBreakpoint) { + ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint; + try { + if (breakpoint.isEnabled()) { + IMarker marker = breakpoint.getMarker(); + if (marker != null) { + + String name = marker.getResource() + .getLocation().toOSString(); + if (name.equals(PHPDebugUtils + .unescapeString(filename)) + && (lineBreakpoint.getLineNumber() == lineNumber)) { + fThread + .setBreakpoints(new IBreakpoint[] { breakpoint }); + break; + } + } + + } + } catch (CoreException e) { + } + } + } + } + } + suspended(DebugEvent.BREAKPOINT); + } + + public void handleDebugEvents(DebugEvent[] events) { + for (int i = 0; i < events.length; i++) { + DebugEvent event = events[i]; + if ((event.getKind() == DebugEvent.CREATE) + && (event.getSource() instanceof XDebugElement)) { + if (((XDebugElement) event.getSource()).getModelIdentifier() == IXDebugConstants.ID_PHP_DEBUG_MODEL) { + if (event.getKind() == DebugEvent.CREATE) + started(); + } + } + } + + } +} \ No newline at end of file