1) Need to syncronize also the type of variable values not only the values (makes...
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / php / model / XDebugTarget.java
1 /**
2  *
3  */
4 package net.sourceforge.phpeclipse.xdebug.php.model;
5
6 //import java.io.ByteArrayInputStream;
7 //import java.io.IOException;
8 import java.util.List;
9
10 import javax.xml.parsers.DocumentBuilder;
11 import javax.xml.parsers.DocumentBuilderFactory;
12 import javax.xml.parsers.ParserConfigurationException;
13
14 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
15 import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
16 import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
17 import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
18 import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
19 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
20 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
21 import net.sourceforge.phpeclipse.xdebug.core.XDebugProxy;
22 import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
23
24 import org.eclipse.core.resources.IMarker;
25 import org.eclipse.core.resources.IMarkerDelta;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IPath;
28 import org.eclipse.debug.core.DebugEvent;
29 import org.eclipse.debug.core.DebugException;
30 import org.eclipse.debug.core.DebugPlugin;
31 import org.eclipse.debug.core.IDebugEventSetListener;
32 import org.eclipse.debug.core.ILaunch;
33
34 import org.eclipse.debug.core.model.IBreakpoint;
35 import org.eclipse.debug.core.model.IDebugTarget;
36 import org.eclipse.debug.core.model.ILineBreakpoint;
37 import org.eclipse.debug.core.model.IMemoryBlock;
38 import org.eclipse.debug.core.model.IProcess;
39 import org.eclipse.debug.core.model.IThread;
40 import org.eclipse.jface.resource.ImageDescriptor;
41 import org.eclipse.ui.model.IWorkbenchAdapter;
42 import org.w3c.dom.Document;
43 import org.w3c.dom.NamedNodeMap;
44 import org.w3c.dom.Node;
45 //import org.xml.sax.SAXException;
46
47 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener;
48 import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugConnection;
49 import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugResponse;
50
51 /**
52  * @author Christian
53  *
54  */
55 public class XDebugTarget extends XDebugElement implements IDebugTarget, IDebugEventSetListener, IProxyEventListener {
56         private IProcess fProcess;
57
58         private ILaunch fLaunch;
59
60         private int fDebugPort;
61
62         private boolean fSuspended = false;
63
64         private boolean fTerminated = false;
65
66         private XDebugThread fThread;
67         private IThread[] fThreads;
68
69         private XDebugConnection fDebugConnection;
70
71         private ResponseListener fResponseListener;
72
73         private String fIdeKey;
74
75
76         /**
77          * Constructs a new debug target in the given launch and waits until
78          * someone with the ideKey connects to the Debugproxy
79          *
80          *
81          * @param launch containing launch
82          * @param process process of the interpreter
83          * @param ideKey
84          * @exception CoreException if unable to connect to host
85          */
86         public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
87                 fLaunch = launch;
88                 fProcess = process;
89                 fDebugConnection = null;
90                 fThread = null;
91                 fThreads = new IThread[0];
92                 fIdeKey = ideKey;
93
94                 fDebugPort = XDebugCorePlugin.getDefault().getPreferenceStore().getInt(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE);
95                 if (fDebugPort == 0) {
96                         fDebugPort = IXDebugPreferenceConstants.DEFAULT_DEBUGPORT;
97                 }
98
99                 DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
100                 DebugPlugin.getDefault().addDebugEventListener(this);
101         }
102
103         public Object getAdapter(Class arg0) {
104            if (IWorkbenchAdapter.class.equals(arg0)) {
105                return new IWorkbenchAdapter() {
106                         public Object[] getChildren(Object o) {
107                             Object[] children = null;
108                             IThread[] threads = getThreads();
109                             if (null != threads) {
110                                 children = new Object[threads.length];
111                                 for (int i = 0; i < threads.length; ++i)
112                                     children[i] = threads[i];
113                             }
114                             return children;
115                         }
116
117                         public ImageDescriptor getImageDescriptor(Object object) {
118                             return null;
119                         }
120
121                         public String getLabel(Object o) {
122                             String label = "(Unable to look up name... check error log)";
123                             try {
124                                 label = getName();
125                             } catch (DebugException x) {
126                                 PHPeclipsePlugin.log(label, x);
127                             }
128                             return label;
129                         }
130
131                         public Object getParent(Object o) {
132                             return XDebugTarget.this.getLaunch();
133                         }
134                     };
135                 }
136                 else {
137                     if (arg0 == XDebugElement.class) {
138                         return this;
139                     }
140
141                     return super.getAdapter(arg0);
142                 }
143             }
144
145         /* (non-Javadoc)
146          * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
147          */
148         public IProcess getProcess() {
149                 return fProcess;
150         }
151
152         /* (non-Javadoc)
153          * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
154          */
155         public IThread[] getThreads() {
156                 return fThreads;
157         }
158
159         /* (non-Javadoc)
160          * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
161          */
162         public boolean hasThreads() throws DebugException {
163                 return (fThreads.length > 0);
164         }
165
166         /* (non-Javadoc)
167          * @see org.eclipse.debug.core.model.IDebugTarget#getName()
168          */
169         public String getName() throws DebugException {
170                 return "PHP XDebug Client at localhost:" + fDebugPort;
171         }
172
173         /* (non-Javadoc)
174          * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
175          */
176         public boolean supportsBreakpoint(IBreakpoint breakpoint) {
177                 if (breakpoint.getModelIdentifier().equals(IXDebugConstants.ID_PHP_BREAKPOINT_MODEL)) {
178                         return true;
179                 }
180                 return false;
181         }
182
183         /* (non-Javadoc)
184          * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
185          */
186         public IDebugTarget getDebugTarget() {
187                 return this;
188         }
189
190         /* (non-Javadoc)
191          * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
192          */
193         public ILaunch getLaunch() {
194                 return fLaunch;
195         }
196
197         /* (non-Javadoc)
198          * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
199          */
200         public boolean canTerminate() {
201                 if (getProcess()!=null)  // ther is no running Process in remote debugging
202                         return getProcess().canTerminate();
203                 return true;
204         }
205
206         /* (non-Javadoc)
207          * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
208          */
209         public boolean isTerminated() {
210 //              return getProcess().isTerminated();
211                 return fTerminated;
212         }
213
214         /* (non-Javadoc)
215          * @see org.eclipse.debug.core.model.ITerminate#terminate()
216          */
217         public void terminate() throws DebugException {
218                 if(fTerminated) {
219                         return;
220                 }
221
222                 if (XDebugCorePlugin.getDefault() != null) {
223                         XDebugProxy proxy = XDebugCorePlugin.getDefault().getXDebugProxy();
224                         proxy.removeProxyEventListener(this, fIdeKey);
225
226                         System.out.println("XDebug.Target: ProxyEventlistener removed");
227
228                         fTerminated = true;
229                         fSuspended = false;
230
231                         XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
232                         fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
233                         DebugPlugin.getDefault().removeDebugEventListener(this);
234                 }
235         }
236
237         /* (non-Javadoc)
238          * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
239          */
240         public boolean canResume() {
241                 return false;
242         }
243
244         /* (non-Javadoc)
245          * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
246          */
247         public boolean canSuspend() {
248                 return false;
249         }
250
251         /* (non-Javadoc)
252          * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
253          */
254         public boolean isSuspended() {
255                 return fSuspended;
256         }
257
258         /* (non-Javadoc)
259          * @see org.eclipse.debug.core.model.ISuspendResume#resume()
260          */
261         public void resume() throws DebugException {
262                 if (fDebugConnection != null) {
263                         fThread.setBreakpoints(null);
264                         resumed(DebugEvent.RESUME);
265                         fDebugConnection.run();
266                 }
267         }
268
269         /**
270          * Notification the target has resumed for the given reason
271          *
272          * @param detail reason for the resume
273          */
274         private void resumed(int detail) {
275                 fSuspended = false;
276                 fThread.fireResumeEvent(detail);
277         }
278
279         /**
280          * Notification the target has suspended for the given reason
281          *
282          * @param detail reason for the suspend
283          */
284         public void suspended(int detail) {
285                 fSuspended = true;
286                 fThread.fireSuspendEvent(detail);
287         }
288
289         /* (non-Javadoc)
290          * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
291          */
292         public void suspend() throws DebugException {
293         }
294
295         /* (non-Javadoc)
296          * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
297          */
298         public void breakpointAdded(IBreakpoint breakpoint) {
299                 IMarker marker   = breakpoint.getMarker();                  // Get the breakpoints marker info (It's the local workspace path)
300                 IPath   path     = marker.getResource().getLocation();      // Get the full path + file for the given breakpoint (It's the local real path)
301                 IPath   cp       = path.removeLastSegments(1);              // Get the full path only (without the file name)
302                 List    pathMap  = null;
303
304                 try {
305                         pathMap = fLaunch.getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP,(List)null);
306                 } catch (CoreException e2) {
307                         // TODO Auto-generated catch block
308                         e2.printStackTrace();
309                 }
310
311                 if ((fDebugConnection != null) &&                           // If there is a connection to XDebug
312                     (!fDebugConnection.isClosed ()) &&                      // and this connection is not closed
313                         (fProcess == null)) {                                   //
314                         PathMapItem pmi = null;
315
316                         for (int i = 0; i < pathMap.size(); i++) {              // For every path map pair the user have set
317                                 pmi                 = new PathMapItem((String) pathMap.get(i));   // Get the path map pair
318                                 IPath local         = (IPath)pmi.getLocalPath().clone();          // Get the local
319                                 local               = local.makeAbsolute();
320                                 int matchedSegments = local.segmentCount();
321
322                                 if (local.matchingFirstSegments(cp) == matchedSegments) {
323                                         IPath newPath = pmi.getRemotePath();
324                                         newPath       = newPath.append(path.removeFirstSegments(matchedSegments));
325                                         newPath       = newPath.makeAbsolute();
326
327                                         if (supportsBreakpoint(breakpoint)) {
328                                                 try {
329                                                         if (breakpoint.isEnabled()) {
330                                                                 if (marker != null) {
331                                                                         int id = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber(), marker.getAttribute(XDebugBreakpoint.HIT_COUNT,-1));
332                                                                         XDebugResponse dr = getResponse(id);
333
334                                                                         String bpid = dr.getAttributeValue("id");
335
336                                                                         if (!"".equals(bpid))
337                                                                                 marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
338                                                                 }
339                                                         }
340                                                 } catch (DebugException e) {
341                                                         e.printStackTrace();
342                                                 } catch (CoreException e) {
343                                                         e.printStackTrace();
344                                                 }
345                                         }
346                                 }
347                         }
348                 } else {
349                         if (supportsBreakpoint(breakpoint)) {
350                                 try {
351                                         if (breakpoint.isEnabled()) {
352                                                 if (marker != null) {
353                                                         int            id   = fDebugConnection.breakpointSet (path.toString(),
354                                                                                                               ((ILineBreakpoint) breakpoint).getLineNumber(),
355                                                                                                                                                                   marker.getAttribute (XDebugBreakpoint.HIT_COUNT, -1));
356                                                         XDebugResponse dr   = getResponse(id);
357                                                         String         bpid = dr.getAttributeValue("id");
358
359                                                         if (!"".equals(bpid)) {
360                                                                 marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
361                                                         }
362                                                 }
363                                         }
364                                 } catch (DebugException e) {
365                                         e.printStackTrace();
366                                 } catch (CoreException e) {
367                                         e.printStackTrace();
368                                 }
369                         }
370                 }
371         }
372
373         /* (non-Javadoc)
374          * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
375          */
376         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
377                 if (supportsBreakpoint(breakpoint)) {
378                         try {
379                                 int id =((XDebugLineBreakpoint)breakpoint).getID();
380                                 if (id >0)
381                                         fDebugConnection.breakpointRemove(id);
382                         } catch (CoreException e) {
383                         }
384                 }
385         }
386
387         /* (non-Javadoc)
388          * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
389          */
390         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
391 //              if (supportsBreakpoint(breakpoint)) {
392 //                      try {
393 //                              if (breakpoint.isEnabled()) {
394 //                                      breakpointAdded(breakpoint);
395 //                              } else {
396 //                                      breakpointRemoved(breakpoint, null);
397 //                              }
398 //                      } catch (CoreException e) {
399 //                      }
400 //              }
401         }
402
403         /* (non-Javadoc)
404          * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
405          */
406         public boolean canDisconnect() {
407                 return false;
408         }
409
410         /* (non-Javadoc)
411          * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
412          */
413         public void disconnect() throws DebugException {
414         }
415
416         /* (non-Javadoc)
417          * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
418          */
419         public boolean isDisconnected() {
420                 return (false);
421         }
422
423         /* (non-Javadoc)
424          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
425          */
426         public boolean supportsStorageRetrieval() {
427                 return false;
428         }
429
430         /* (non-Javadoc)
431          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
432          */
433         public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
434                 return null;
435         }
436
437         /**
438          * Notification we have connected to the PHP debugger and it has been started.
439          * Resume the the debugger.
440          */
441         public void started() throws DebugException {
442                 fThread.setBreakpoints(null);
443                 fThread.setStepping(false);
444
445                 int id = fDebugConnection.featureGet("detach");
446
447                 XDebugResponse response = getResponse(id);
448
449                 Integer.parseInt(response.getValue());
450                 System.out.println("in Target.started()");
451
452                 // Dirty hack
453                 // Need to refactory plugin to get variables in lazy mode.
454                 int id1 = fDebugConnection.featureSet("max_depth", "1024" );
455                 XDebugResponse response1 = getResponse(id1);
456                 if (response1.getAttributeValue("success").equals("1") ) {
457                         System.out.println("Set depth to 1024 (hack)");
458                 }
459                 int id2 = fDebugConnection.featureSet("max_children", "1024" );
460                 XDebugResponse response2 = getResponse(id2);
461                 if (response2.getAttributeValue("success").equals("1") ) {
462                         System.out.println("Set children to 1024 (hack)");
463                 }
464
465                 installDeferredBreakpoints();
466                 try {
467                         resume();
468                 } catch (DebugException e) {
469                         e.printStackTrace();
470                 }
471         }
472
473         /**
474          * Install breakpoints that are already registered with the breakpoint
475          * manager.
476          */
477         private void installDeferredBreakpoints() {
478                 IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
479                 for (int i = 0; i < breakpoints.length; i++) {
480                         breakpointAdded(breakpoints[i]);
481                 }
482         }
483
484         /**
485          * Returns the current stack frames in the target.
486          *
487          * @return the current stack frames in the target
488          * @throws DebugException if unable to perform the request
489          */
490         public XDebugResponse getStackFrames() throws DebugException {
491                 int id = fDebugConnection.stackGet();
492                 XDebugResponse lastResponse = getResponse(id);
493                 return lastResponse;
494         }
495
496         /**
497          * Single step the interpreter.
498          *
499          * @throws DebugException if the request fails
500          */
501         protected void step_over() throws DebugException {
502                 fThread.setStepping(true);
503                 resumed(DebugEvent.STEP_OVER);
504                 fDebugConnection.stepOver();
505         }
506
507         /**
508          * Single step the interpreter.
509          *
510          * @throws DebugException if the request fails
511          */
512         protected void step_into() throws DebugException {
513                 fThread.setStepping(true);
514                 resumed(DebugEvent.STEP_INTO);
515                 fDebugConnection.stepInto();
516         }
517
518         /**
519          * Single step the interpreter.
520          *
521          * @throws DebugException if the request fails
522          */
523         protected void step_out() throws DebugException {
524                 fThread.setStepping(true);
525                 resumed(DebugEvent.STEP_RETURN);
526                 fDebugConnection.stepOut();
527         }
528
529         public boolean setVarValue(String name, String value) {
530                 int id = fDebugConnection.setVarValue(name,value);
531                 XDebugResponse response = getResponse(id);
532
533                 if ((response.getAttributeValue("success")).equals("1")) {
534                         return true;
535                 } else {
536                         return false;
537                 }
538         }
539
540         public Node eval(String expression) throws DebugException {
541                 Node evalProperty = null;
542                 if (fDebugConnection != null) {
543                         int id = fDebugConnection.eval(expression);
544                         //Node evalProperty = new Node("");
545                         //if (id > 0) {
546                                 XDebugResponse response = getResponse(id);
547
548                                 Node evalResponse = response.getParentNode();
549                                 /*Node*/ evalProperty = evalResponse.getFirstChild();
550                         //} /*else {
551
552                         //}*/
553                 } else {
554                         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
555                         DocumentBuilder builder = null;
556                         Document doc = null;
557
558                         try {
559                                 builder = factory.newDocumentBuilder();
560                         } catch (ParserConfigurationException e) {
561                                 e.printStackTrace();
562                         }
563                         //try {
564                                 doc =  builder.newDocument(); // .parse("");
565                                 evalProperty = doc.createElement("value");
566                         /*} catch (SAXException e) {
567                                 e.printStackTrace();
568                         } catch (IOException e) {
569                                 e.printStackTrace();
570                         }*/
571                 }
572
573                 return evalProperty;
574         }
575
576         public void handleDebugEvents(DebugEvent[] events) {
577                 for (int i = 0; i < events.length; i++) {
578                         DebugEvent event = events[i];
579
580                         if (fResponseListener != null) {
581                                 Object s = null;
582                                 s = event.getSource();
583                                 if (s instanceof ResponseListener) {
584                                         if (!fResponseListener.equals((ResponseListener) s)) {
585                                                 return;
586                                         }
587                                 }
588                         } else {
589                                 return;
590                         }
591
592                         if (event.getKind() == DebugEvent.MODEL_SPECIFIC) {
593                                 switch (event.getDetail()) {
594                                         case IPHPDebugEvent.BREAKPOINT_HIT:
595                                                 int id = fDebugConnection.stackGet();
596                                                 XDebugResponse lastResponse = getResponse(id);
597
598                                                 IBreakpoint breakpoint = breakpointHit(lastResponse.getParentNode());
599
600                                                 if (breakpoint != null) {
601                                                         fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
602                                                         fThread.incrementStepCounter();
603                                                         suspended(DebugEvent.BREAKPOINT);
604                                                 } else {
605                                                         try {
606                                                                 resume();
607                                                         } catch (DebugException e ) {
608                                                                 ; //nothing to do
609                                                         }
610                                                 }
611                                                 break;
612                                         case IPHPDebugEvent.STEP_END:
613                                                 fThread.incrementStepCounter();
614                                                 suspended(DebugEvent.STEP_END);
615                                                 break;
616                                         case IPHPDebugEvent.STOPPED:
617                                                 stopped();
618                                                 break;
619                                 }
620                         }
621                 }
622         }
623
624         public void stopped() {
625                 if(fDebugConnection == null) {
626                         return;
627                 }
628
629                 resumed(DebugEvent.TERMINATE);
630
631                 stopListener();
632                 fDebugConnection.close();
633
634                 fSuspended = false;
635
636                 // Dirty hack to check debugging mode (remote or local)
637                 if (fProcess != null) {
638                         try {
639                                 terminate();
640                         } catch (DebugException e) {
641                                 e.printStackTrace();
642                         }
643                 } else {
644                         fDebugConnection = null;
645                         fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
646                 }
647
648                 fThread.removeEventListeners();
649                 fThread = null;
650                 fThreads = new IThread[0];
651         }
652
653         public void handleProxyEvent(XDebugConnection connection) {
654                 //System.out.println("* New Connection - XDebug.Target: " + fDebugConnection.getSessionID());
655
656                 if (setDebugConnection(connection)) {
657                         fThread = new XDebugThread(this);
658                         fThreads = new IThread[] {fThread};
659                         fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CHANGE));
660                         try {
661                                 started();
662                         } catch( DebugException e ){
663                                 e.printStackTrace();
664                         }
665                 }
666         }
667
668         private boolean setDebugConnection(XDebugConnection connection) {
669                 if (connection != null && fDebugConnection == null) {
670                         fDebugConnection = connection;
671                         fResponseListener = new ResponseListener(connection);
672                         startListener();
673
674                         return true;
675                 } else {
676                         connection.close();
677
678                         return false;
679                 }
680         }
681
682         /**
683          * @return Returns the fDebugConnection.
684          */
685         public XDebugConnection getDebugConnection() {
686                 return fDebugConnection;
687         }
688
689         public void addProcess(IProcess p) {
690                 fProcess = p;
691
692         }
693         public Node getLocalVariables(int level) throws DebugException {
694                 int id = fDebugConnection.contextGet(level, 0);
695                 XDebugResponse response = getResponse(id);
696
697                 return response.getParentNode();
698         }
699
700         public Node getGlobalVariables(int level) throws DebugException {
701                 int id = fDebugConnection.contextGet(level, 1);
702                 XDebugResponse response = getResponse(id);
703
704                 return response.getParentNode();
705         }
706
707         public void stop() {
708                 fDebugConnection.stop();
709         }
710
711         protected IBreakpoint breakpointHit(Node node) {
712                 Node child = node.getFirstChild();
713                 if (child.getNodeName().equals("stack")) {
714                         int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "lineno"));
715                         String filename = PHPDebugUtils.getAttributeValue(child, "filename");
716                         IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
717                         for (int i = 0; i < breakpoints.length; i++) {
718                                 IBreakpoint breakpoint = breakpoints[i];
719                                 if (supportsBreakpoint(breakpoint)) {
720                                         if (breakpoint instanceof ILineBreakpoint) {
721                                                 ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
722                                                 try {
723                                                         if (breakpoint.isEnabled()) {
724                                                                 IMarker marker = breakpoint.getMarker();
725                                                                 if (marker != null) {
726                                                                         String endfilename;
727
728                                                                         if (getProcess() == null) {
729                                                                                 endfilename = marker.getResource().getLocation().lastSegment();
730                                                                         } else {
731                                                                                 endfilename = marker.getResource().getLocation().toOSString();
732                                                                         }
733
734                                                                         int id = fDebugConnection.breakpointGet(marker.getAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,-1));
735                                                                         XDebugResponse dr = getResponse(id);
736
737                                                                         Node hitCo = dr.getParentNode().getFirstChild();
738                                                                         int hitCount = 0;
739                                                                         if (hitCo.hasAttributes()) {
740                                                                                 NamedNodeMap listAttribute = hitCo.getAttributes();
741                                                                                 Node attribute = listAttribute.getNamedItem("hit_count");
742                                                                                 if (attribute !=null) {
743                                                                                         hitCount = Integer.parseInt(attribute.getNodeValue());
744                                                                                 }
745                                                                         }
746
747                                                                         if(PHPDebugUtils.unescapeString(filename).endsWith(endfilename)
748                                                                                         && (lineBreakpoint.getLineNumber() == lineNumber) ) {
749                                                                                 if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) > 0) {
750                                                                                         if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) == hitCount) {
751                                                                                                 return (breakpoint);
752                                                                                         }
753                                                                                 } else {
754                                                                                         return (breakpoint);
755                                                                                 }
756                                                                         }
757                                                                 }
758                                                         }
759                                                 } catch (CoreException e) {
760                                                 }
761                                         }
762                                 }
763                         }
764                 }
765
766                 return null;
767         }
768
769         public void startListener() {
770                 fResponseListener.schedule();
771         }
772
773         public void stopListener() {
774                 fResponseListener.cancel();
775         }
776         public XDebugResponse getResponse(int id) {
777                 XDebugResponse response = fResponseListener.getResponse(id);
778
779                 return response;
780         }
781 }