4 package net.sourceforge.phpeclipse.xdebug.php.model;
 
   8 import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
 
   9 import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
 
  10 import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
 
  11 import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
 
  12 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
 
  13 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
 
  14 import net.sourceforge.phpeclipse.xdebug.core.XDebugProxy;
 
  15 import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
 
  17 import org.eclipse.core.resources.IMarker;
 
  18 import org.eclipse.core.resources.IMarkerDelta;
 
  19 import org.eclipse.core.runtime.CoreException;
 
  20 import org.eclipse.core.runtime.IPath;
 
  21 import org.eclipse.debug.core.DebugEvent;
 
  22 import org.eclipse.debug.core.DebugException;
 
  23 import org.eclipse.debug.core.DebugPlugin;
 
  24 import org.eclipse.debug.core.IDebugEventSetListener;
 
  25 import org.eclipse.debug.core.ILaunch;
 
  27 import org.eclipse.debug.core.model.IBreakpoint;
 
  28 import org.eclipse.debug.core.model.IDebugTarget;
 
  29 import org.eclipse.debug.core.model.ILineBreakpoint;
 
  30 import org.eclipse.debug.core.model.IMemoryBlock;
 
  31 import org.eclipse.debug.core.model.IProcess;
 
  32 import org.eclipse.debug.core.model.IThread;
 
  33 import org.w3c.dom.NamedNodeMap;
 
  34 import org.w3c.dom.Node;
 
  36 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener;
 
  37 import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugConnection;
 
  38 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener.XDebugResponse;
 
  44 public class XDebugTarget extends XDebugElement implements IDebugTarget, IDebugEventSetListener, IProxyEventListener {
 
  45         private IProcess fProcess;
 
  47         private ILaunch fLaunch;
 
  49         private int fDebugPort;
 
  51         private boolean fSuspended = false;
 
  53         private boolean fTerminated = false;
 
  55         private XDebugThread fThread;
 
  56         private IThread[] fThreads;
 
  58         private XDebugConnection fDebugConnection;
 
  60         private ResponseListener fResponseListener;
 
  62         private String fIdeKey;
 
  66          * Constructs a new debug target in the given launch and waits until
 
  67          * someone with the ideKey connects to the Debugproxy
 
  70          * @param launch containing launch
 
  71          * @param process process of the interpreter
 
  73          * @param pathMap Pathmap for the debug session
 
  74          * @exception CoreException if unable to connect to host
 
  76         public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
 
  79                 fDebugConnection = null;
 
  81                 fThreads = new IThread[0];
 
  84                 fDebugPort = XDebugCorePlugin.getDefault().getPreferenceStore().getInt(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE);                
 
  85                 if (fDebugPort == 0) {
 
  86                         fDebugPort = IXDebugPreferenceConstants.DEFAULT_DEBUGPORT;
 
  89                 DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
 
  90                 DebugPlugin.getDefault().addDebugEventListener(this);
 
  94          * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
 
  96         public IProcess getProcess() {
 
 101          * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
 
 103         public IThread[] getThreads() throws DebugException {
 
 108          * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
 
 110         public boolean hasThreads() throws DebugException {
 
 111                 return (fThreads.length > 0);
 
 115          * @see org.eclipse.debug.core.model.IDebugTarget#getName()
 
 117         public String getName() throws DebugException {
 
 118                 return "PHP XDebug Client at localhost:" + fDebugPort;
 
 122          * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
 
 124         public boolean supportsBreakpoint(IBreakpoint breakpoint) {
 
 125                 if (breakpoint.getModelIdentifier().equals(IXDebugConstants.ID_PHP_DEBUG_MODEL)) {
 
 132          * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
 
 134         public IDebugTarget getDebugTarget() {
 
 139          * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
 
 141         public ILaunch getLaunch() {
 
 146          * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
 
 148         public boolean canTerminate() {
 
 149                 if (getProcess()!=null)  // ther is no running Process in remote debugging
 
 150                         return getProcess().canTerminate();
 
 155          * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
 
 157         public boolean isTerminated() {
 
 158 //              return getProcess().isTerminated();
 
 163          * @see org.eclipse.debug.core.model.ITerminate#terminate()
 
 165         public void terminate() throws DebugException {
 
 170                 if (XDebugCorePlugin.getDefault() != null) {
 
 171                         XDebugProxy proxy = XDebugCorePlugin.getDefault().getXDebugProxy();
 
 172                         proxy.removeProxyEventListener(this, fIdeKey);
 
 174                         System.out.println("XDebug.Target: ProxyEventlistener removed");
 
 179                         XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
 
 180                         fireTerminateEvent();
 
 181                         DebugPlugin.getDefault().removeDebugEventListener(this);
 
 183                                 fThread.removeEventListeners();*/
 
 188          * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
 
 190         public boolean canResume() {
 
 195          * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
 
 197         public boolean canSuspend() {
 
 202          * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
 
 204         public boolean isSuspended() {
 
 209          * @see org.eclipse.debug.core.model.ISuspendResume#resume()
 
 211         public void resume() throws DebugException {
 
 212                 if (fDebugConnection != null) {
 
 213                         fThread.setBreakpoints(null);
 
 214                         resumed(DebugEvent.RESUME);
 
 215                         fDebugConnection.run();
 
 220          * Notification the target has resumed for the given reason
 
 222          * @param detail reason for the resume
 
 224         private void resumed(int detail) {
 
 226                 fThread.fireResumeEvent(detail);
 
 230          * Notification the target has suspended for the given reason
 
 232          * @param detail reason for the suspend
 
 234         public void suspended(int detail) {
 
 236                 fThread.fireSuspendEvent(detail);
 
 240          * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
 
 242         public void suspend() throws DebugException {
 
 246          * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
 
 248         public void breakpointAdded(IBreakpoint breakpoint) {
 
 249                 IMarker marker = breakpoint.getMarker();
 
 250                 IPath path = marker.getResource().getLocation();
 
 251                 IPath cp = path.removeLastSegments(1);
 
 254                         pathMap = fLaunch.getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP,(List)null);
 
 255                 } catch (CoreException e2) {
 
 256                         // TODO Auto-generated catch block
 
 257                         e2.printStackTrace();
 
 260                 if (fDebugConnection != null)
 
 261                 if (!fDebugConnection.isClosed()) {
 
 262                         if (fProcess == null) {
 
 263                                 PathMapItem pmi = null;
 
 264                                 for (int i = 0; i < pathMap.size(); i++) {
 
 265                                         pmi = new PathMapItem((String) pathMap.get(i));
 
 266                                         IPath local = (IPath)pmi.getLocalPath().clone();
 
 267                                         local = local.makeAbsolute();
 
 268                                         int matchedSegments = local.segmentCount();
 
 269                                         if (local.matchingFirstSegments(cp) == matchedSegments) {
 
 270                                                 IPath newPath = pmi.getRemotePath();
 
 271                                                 newPath = newPath.append(path.removeFirstSegments(matchedSegments));
 
 272                                                 newPath = newPath.makeAbsolute();
 
 273                                                 if (supportsBreakpoint(breakpoint)) {
 
 275                                                                 if (breakpoint.isEnabled()) {
 
 276                                                                         if (marker != null) {
 
 277                                                                                 //XDebugResponse dr = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber());
 
 279                                                                                 int id = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
 
 280                                                                                 XDebugResponse dr = getResponse(id);
 
 282                                                                                 String bpid = dr.getAttributeValue("id");
 
 284                                                                                 if (!"".equals(bpid))
 
 285                                                                                         marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
 
 288                                                         } catch (DebugException e) {
 
 290                                                         } catch (CoreException e) {
 
 297                                 if (supportsBreakpoint(breakpoint)) {
 
 299                                                 if (breakpoint.isEnabled()) {
 
 300                                                         if (marker != null) {
 
 301                                                                 int id = fDebugConnection.breakpointSet(path.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
 
 302                                                                 XDebugResponse dr = getResponse(id);
 
 303                                                                 String bpid = dr.getAttributeValue("id");
 
 305                                                                 if (!"".equals(bpid))
 
 306                                                                         marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
 
 309                                         } catch (DebugException e) {
 
 311                                         } catch (CoreException e) {
 
 320          * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
 
 322         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
 
 323                 if (supportsBreakpoint(breakpoint)) {
 
 325                                 int id =((XDebugLineBreakpoint)breakpoint).getID();
 
 327                                         fDebugConnection.breakpointRemove(id);
 
 328                         } catch (CoreException e) {
 
 334          * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
 
 336         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
 
 337 //              if (supportsBreakpoint(breakpoint)) {
 
 339 //                              if (breakpoint.isEnabled()) {
 
 340 //                                      breakpointAdded(breakpoint);
 
 342 //                                      breakpointRemoved(breakpoint, null);
 
 344 //                      } catch (CoreException e) {
 
 350          * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
 
 352         public boolean canDisconnect() {
 
 357          * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
 
 359         public void disconnect() throws DebugException {
 
 363          * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
 
 365         public boolean isDisconnected() {
 
 367 //              return (fDebugConnection==null);
 
 371          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
 
 373         public boolean supportsStorageRetrieval() {
 
 378          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
 
 380         public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
 
 385          * Notification we have connected to the PHP debugger and it has been started.
 
 386          * Resume the the debugger.
 
 388         public void started() throws DebugException {
 
 389                 fThread.setBreakpoints(null);
 
 390                 fThread.setStepping(false);
 
 392                 int id = fDebugConnection.featureGet("detach");
 
 394                 XDebugResponse response = getResponse(id);
 
 396                 Integer.parseInt(response.getValue());
 
 397                 System.out.println("in Target.started()");
 
 398                 /*XDebugResponse response = fDebugConnection.featureGet("max_children");
 
 399                 String a1 = response.getValue();
 
 400                 System.out.println("max children:"+a1);
 
 401                 XDebugResponse response1 = fDebugConnection.featureGet("max_children");
 
 402                 String a2 = response1.getValue();
 
 403                 System.out.println("max depth:"+a2);*/
 
 406                 int id1 = fDebugConnection.featureSet("max_depth", "1024" );
 
 407                 XDebugResponse response1 = getResponse(id1);
 
 408                 if (response1.getAttributeValue("success").equals("1") ) {
 
 409                         System.out.println("Set depth to 1024 (hack)");
 
 411                 int id2 = fDebugConnection.featureSet("max_children", "1024" );
 
 412                 XDebugResponse response2 = getResponse(id2);
 
 413                 if (response2.getAttributeValue("success").equals("1") ) {
 
 414                         System.out.println("Set children to 1024 (hack)");
 
 417                 installDeferredBreakpoints();
 
 420                 } catch (DebugException e) {
 
 426          * Install breakpoints that are already registered with the breakpoint
 
 429         private void installDeferredBreakpoints() {
 
 430                 IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
 
 431                 for (int i = 0; i < breakpoints.length; i++) {
 
 432                         breakpointAdded(breakpoints[i]);
 
 437          * Returns the current stack frames in the target.
 
 439          * @return the current stack frames in the target
 
 440          * @throws DebugException if unable to perform the request
 
 442         public XDebugResponse getStackFrames() throws DebugException {
 
 443                 int id = fDebugConnection.stackGet();
 
 444                 XDebugResponse lastResponse = getResponse(id);
 
 449          * Single step the interpreter.
 
 451          * @throws DebugException if the request fails
 
 453         protected void step_over() throws DebugException {
 
 454                 fThread.setStepping(true);
 
 455                 resumed(DebugEvent.STEP_OVER);
 
 456                 fDebugConnection.stepOver();
 
 460          * Single step the interpreter.
 
 462          * @throws DebugException if the request fails
 
 464         protected void step_into() throws DebugException {
 
 465                 fThread.setStepping(true);
 
 466                 resumed(DebugEvent.STEP_INTO);
 
 467                 fDebugConnection.stepInto();
 
 471          * Single step the interpreter.
 
 473          * @throws DebugException if the request fails
 
 475         protected void step_out() throws DebugException {
 
 476                 fThread.setStepping(true);
 
 477                 resumed(DebugEvent.STEP_RETURN);
 
 478                 fDebugConnection.stepOut();
 
 481         public boolean setVarValue(String name, String value) {
 
 482                 int id = fDebugConnection.setVarValue(name,value);
 
 483                 XDebugResponse response = getResponse(id);
 
 485                 if ((response.getAttributeValue("success")).equals("1")) {
 
 492         public Node eval(String expression) {
 
 493                 int id = fDebugConnection.eval(expression);
 
 494                 XDebugResponse response = getResponse(id);
 
 496                 Node evalResponse = response.getParentNode();
 
 497                 Node evalProperty = evalResponse.getFirstChild();
 
 502         public void handleDebugEvents(DebugEvent[] events) {
 
 503                 for (int i = 0; i < events.length; i++) {
 
 504                         DebugEvent event = events[i];
 
 506                         if (fResponseListener != null) {
 
 508                                 s = event.getSource();
 
 509                                 if (s instanceof ResponseListener) {
 
 510                                         if (!fResponseListener.equals((ResponseListener) s)) {
 
 518                         if (event.getKind() == DebugEvent.MODEL_SPECIFIC) {
 
 519                                 switch (event.getDetail()) {
 
 520                                         case IPHPDebugEvent.BREAKPOINT_HIT:
 
 521                                                 int id = fDebugConnection.stackGet();
 
 522                                                 XDebugResponse lastResponse = getResponse(id);
 
 524                                                 IBreakpoint breakpoint = breakpointHit(lastResponse.getParentNode());
 
 526                                                 if (breakpoint != null) {
 
 527                                                         fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
 
 528                                                         fThread.incrementStepCounter();
 
 529                                                         suspended(DebugEvent.BREAKPOINT);
 
 533                                                         } catch (DebugException e ) {
 
 538                                         case IPHPDebugEvent.STEP_END:
 
 539                                                 fThread.incrementStepCounter();
 
 540                                                 suspended(DebugEvent.STEP_END);
 
 542                                         case IPHPDebugEvent.STOPPED:
 
 550         public void stopped() {
 
 551                 if(fDebugConnection == null) {
 
 555                 resumed(DebugEvent.TERMINATE);
 
 558                 fDebugConnection.close();
 
 560                 fThread.removeEventListeners();
 
 562                 fThreads = new IThread[0];
 
 565                 fDebugConnection.close();*/
 
 569                 // Dirty hack to check debugging mode (remote or local)
 
 570                 if (fProcess!=null) {
 
 573                         } catch (DebugException e) {
 
 577                         fDebugConnection = null;
 
 578                         fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
 
 582         public void handleProxyEvent(/*String ideKey,*/ XDebugConnection connection) {
 
 583                 setDebugConnection(connection);
 
 584                 System.out.println("* New Connection - XDebug.Target: " + fDebugConnection.getSessionID());
 
 586                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CHANGE));
 
 588                 fThread = new XDebugThread(this);
 
 589                 fThreads = new IThread[] {fThread};
 
 592                 } catch( DebugException e ){
 
 597         private void setDebugConnection(XDebugConnection connection) {
 
 598                 if (connection != null) {
 
 599                         fDebugConnection = connection;
 
 600                         fResponseListener = new ResponseListener(connection);
 
 606          * @return Returns the fDebugConnection.
 
 608         public XDebugConnection getDebugConnection() {
 
 609                 return fDebugConnection;
 
 612         public void addProcess(IProcess p) {
 
 616         public Node getLocalVariables(int level) throws DebugException {
 
 617 //              XDebugResponse response = fDebugConnection.contextGet(level, 0);
 
 618                 int id = fDebugConnection.contextGet(level, 0);
 
 619                 XDebugResponse response = getResponse(id);
 
 621                 return response.getParentNode();
 
 624         public Node getGlobalVariables(int level) throws DebugException {
 
 625                 //XDebugResponse response = fDebugConnection.contextGet(level, 1);
 
 627                 int id = fDebugConnection.contextGet(level, 1);
 
 628                 XDebugResponse response = getResponse(id);
 
 630                 return response.getParentNode();
 
 634                 fDebugConnection.stop();
 
 637         protected IBreakpoint breakpointHit(Node node) {
 
 638                 Node child = node.getFirstChild();
 
 639                 if (child.getNodeName().equals("stack")) {
 
 640                         int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "lineno"));
 
 641                         String filename = PHPDebugUtils.getAttributeValue(child, "filename");  
 
 642                         IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
 
 643                         for (int i = 0; i < breakpoints.length; i++) {
 
 644                                 IBreakpoint breakpoint = breakpoints[i];
 
 645                                 if (supportsBreakpoint(breakpoint)) {
 
 646                                         if (breakpoint instanceof ILineBreakpoint) {
 
 647                                                 ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
 
 649                                                         if (breakpoint.isEnabled()) {
 
 650                                                                 IMarker marker = breakpoint.getMarker();
 
 651                                                                 if (marker != null) {
 
 654                                                                         if (getProcess() == null) {
 
 655                                                                                 endfilename = marker.getResource().getLocation().lastSegment(); 
 
 657                                                                                 endfilename = marker.getResource().getLocation().toOSString();
 
 660                                                                         int id = fDebugConnection.breakpointGet(marker.getAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,-1));
 
 661                                                                         XDebugResponse dr = getResponse(id);
 
 663                                                                         //String bpid = dr.getAttributeValue("command");                                                                        
 
 664                                                                         Node hitCo = dr.getParentNode().getFirstChild();
 
 666                                                                         if (hitCo.hasAttributes()) {
 
 667                                                                                 NamedNodeMap listAttribute = hitCo.getAttributes();
 
 668                                                                                 Node attribute = listAttribute.getNamedItem("hit_count");
 
 669                                                                                 if (attribute !=null) {
 
 670                                                                                         hitCount = Integer.parseInt(attribute.getNodeValue());
 
 674                                                                         //String hitCount = hitCo.getAttributeValue("hit_count");                                                                       
 
 675                                                                         if(PHPDebugUtils.unescapeString(filename).endsWith(endfilename)
 
 676                                                                                         && (lineBreakpoint.getLineNumber() == lineNumber) ) {
 
 677                                                                                 if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) > 0) {
 
 678                                                                                         if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) == hitCount) {
 
 687                                                 } catch (CoreException e) {
 
 697         public void startListener() {
 
 698                 fResponseListener.schedule();
 
 701         public /*boolean*/ void stopListener() {
 
 702                 /*return*/ fResponseListener.cancel(); //done(null); //.cancel();
 
 704         public XDebugResponse getResponse(int id) {
 
 705                 XDebugResponse response = fResponseListener.getResponse(id);