1) Fixed breakpoint with skip count (or hit count).
[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.IOException;
7 import java.util.List;
8
9 import javax.xml.parsers.DocumentBuilder;
10 import javax.xml.parsers.DocumentBuilderFactory;
11 import javax.xml.parsers.ParserConfigurationException;
12
13 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
14 import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
15 import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
16 import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
17 import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
18 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
19 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
20 import net.sourceforge.phpeclipse.xdebug.core.XDebugProxy;
21 import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
22
23 import org.eclipse.core.resources.IMarker;
24 import org.eclipse.core.resources.IMarkerDelta;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.Path;
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(),
332                                                                                                                  ((ILineBreakpoint)breakpoint).getLineNumber(),
333                                                                                                                  marker.getAttribute (XDebugBreakpoint.HIT_COUNT, -1),
334                                                                              marker.getAttribute (XDebugBreakpoint.CONDITION_ENABLED, false),
335                                                                                                                  marker.getAttribute (XDebugBreakpoint.CONDITION, ""));
336                                                                         XDebugResponse dr = getResponse(id);
337
338                                                                         String bpid = dr.getAttributeValue("id");
339
340                                                                         if (!"".equals(bpid))
341                                                                                 marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
342                                                                 }
343                                                         }
344                                                 } catch (DebugException e) {
345                                                         e.printStackTrace();
346                                                 } catch (CoreException e) {
347                                                         e.printStackTrace();
348                                                 }
349                                         }
350                                 }
351                         }
352                 }
353         }
354
355         /* (non-Javadoc)
356          * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
357          */
358         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
359                 IMarker marker   = breakpoint.getMarker();                  // Get the breakpoints marker info (It's the local workspace path)
360
361                 if (supportsBreakpoint(breakpoint)) {
362                         int id = marker.getAttribute (XDebugLineBreakpoint.BREAKPOINT_ID, -1);
363
364             if (id > 0) {
365                 fDebugConnection.breakpointRemove(id);
366             }
367                 }
368         }
369
370         /* (non-Javadoc)
371          * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
372          */
373         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
374        IMarker oldmarker = breakpoint.getMarker ();
375
376        if (supportsBreakpoint(breakpoint)) {
377                         try {
378                                 if (breakpoint.isEnabled ()     &&                                                                      // Check if breakpoint state changed from disabled to enabled
379                                         !delta.getAttribute ("org.eclipse.debug.core.enabled", false)) {
380                                         breakpointAdded (breakpoint);
381                                 }
382                                 else if (!breakpoint.isEnabled () &&                                                    // Check if breakpoint state changed from enabled to disabled
383                                     delta.getAttribute ("org.eclipse.debug.core.enabled", true)) {
384                                         breakpointRemoved (breakpoint, null);
385                                 }
386                                 else if (oldmarker.getAttribute (XDebugLineBreakpoint.CHANGE_ID, 1) !=
387                                          delta.getAttribute (XDebugLineBreakpoint.CHANGE_ID, 0)) {
388                                         if (breakpoint.isEnabled ()) {                                                          // If the breakpoint is already enabled
389                                                 breakpointRemoved (breakpoint, null);                                   // we remove this breakpoint first
390                                                 breakpointAdded (breakpoint);                                                   // and then we add again (else XDebug would have two breakpoints!).
391                                         }
392                                         else {
393                                                 breakpointRemoved (breakpoint, null);
394                                         }
395                                 }
396                         } catch (CoreException e) {
397                                 // Do nothing
398                         }
399                 }
400         }
401
402         /* (non-Javadoc)
403          * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
404          */
405         public boolean canDisconnect() {
406                 return false;
407         }
408
409         /* (non-Javadoc)
410          * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
411          */
412         public void disconnect() throws DebugException {
413         }
414
415         /* (non-Javadoc)
416          * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
417          */
418         public boolean isDisconnected() {
419                 return (false);
420         }
421
422         /* (non-Javadoc)
423          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
424          */
425         public boolean supportsStorageRetrieval() {
426                 return false;
427         }
428
429         /* (non-Javadoc)
430          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
431          */
432         public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
433                 return null;
434         }
435
436         /**
437          * Notification we have connected to the PHP debugger and it has been started.
438          * Resume the the debugger.
439          */
440         public void started() throws DebugException {
441                 fThread.setBreakpoints(null);
442                 fThread.setStepping(false);
443
444                 int id = fDebugConnection.featureGet("detach");
445
446                 XDebugResponse response = getResponse(id);
447
448                 Integer.parseInt(response.getValue());
449                 System.out.println("in Target.started()");
450
451                 // Dirty hack
452                 // Need to refactory plugin to get variables in lazy mode.
453                 int id1 = fDebugConnection.featureSet("max_depth", "1024" );
454                 XDebugResponse response1 = getResponse(id1);
455                 if (response1.getAttributeValue("success").equals("1") ) {
456                         System.out.println("Set depth to 1024 (hack)");
457                 }
458                 int id2 = fDebugConnection.featureSet("max_children", "1024" );
459                 XDebugResponse response2 = getResponse(id2);
460                 if (response2.getAttributeValue("success").equals("1") ) {
461                         System.out.println("Set children to 1024 (hack)");
462                 }
463
464                 installDeferredBreakpoints();
465                 try {
466                         resume();
467                 } catch (DebugException e) {
468                         e.printStackTrace();
469                 }
470         }
471
472         /**
473          * Install breakpoints that are already registered with the breakpoint
474          * manager.
475          */
476         private void installDeferredBreakpoints() {
477                 IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
478                 for (int i = 0; i < breakpoints.length; i++) {
479                         breakpointAdded(breakpoints[i]);
480                 }
481         }
482
483         /**
484          * Returns the current stack frames in the target.
485          *
486          * @return the current stack frames in the target
487          * @throws DebugException if unable to perform the request
488          */
489         public XDebugResponse getStackFrames() throws DebugException {
490                 int id = fDebugConnection.stackGet();
491                 XDebugResponse lastResponse = getResponse(id);
492                 return lastResponse;
493         }
494
495         /**
496          * Single step the interpreter.
497          *
498          * @throws DebugException if the request fails
499          */
500         protected void step_over() throws DebugException {
501                 fThread.setStepping(true);
502                 resumed(DebugEvent.STEP_OVER);
503                 fDebugConnection.stepOver();
504         }
505
506         /**
507          * Single step the interpreter.
508          *
509          * @throws DebugException if the request fails
510          */
511         protected void step_into() throws DebugException {
512                 fThread.setStepping(true);
513                 resumed(DebugEvent.STEP_INTO);
514                 fDebugConnection.stepInto();
515         }
516
517         /**
518          * Single step the interpreter.
519          *
520          * @throws DebugException if the request fails
521          */
522         protected void step_out() throws DebugException {
523                 fThread.setStepping(true);
524                 resumed(DebugEvent.STEP_RETURN);
525                 fDebugConnection.stepOut();
526         }
527
528         public boolean setVarValue(String name, String value) {
529                 int id = fDebugConnection.setVarValue(name,value);
530                 XDebugResponse response = getResponse(id);
531
532                 if ((response.getAttributeValue("success")).equals("1")) {
533                         return true;
534                 } else {
535                         return false;
536                 }
537         }
538
539         public Node eval(String expression) throws DebugException {
540                 Node evalProperty = null;
541                 if (fDebugConnection != null) {
542                         int id = fDebugConnection.eval(expression);
543                         //Node evalProperty = new Node("");
544                         //if (id > 0) {
545                                 XDebugResponse response = getResponse(id);
546
547                                 Node evalResponse = response.getParentNode();
548                                 /*Node*/ evalProperty = evalResponse.getFirstChild();
549                         //} /*else {
550
551                         //}*/
552                 } else {
553                         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
554                         DocumentBuilder builder = null;
555                         Document doc = null;
556
557                         try {
558                                 builder = factory.newDocumentBuilder();
559                         } catch (ParserConfigurationException e) {
560                                 e.printStackTrace();
561                         }
562                         //try {
563                                 doc =  builder.newDocument(); // .parse("");
564                                 evalProperty = doc.createElement("value");
565                         /*} catch (SAXException e) {
566                                 e.printStackTrace();
567                         } catch (IOException e) {
568                                 e.printStackTrace();
569                         }*/
570                 }
571
572                 return evalProperty;
573         }
574
575         public void handleDebugEvents(DebugEvent[] events) {
576                 for (int i = 0; i < events.length; i++) {
577                         DebugEvent event = events[i];
578
579                         if (fResponseListener != null) {
580                                 Object s = null;
581                                 s = event.getSource();
582                                 if (s instanceof ResponseListener) {
583                                         if (!fResponseListener.equals((ResponseListener) s)) {
584                                                 return;
585                                         }
586                                 }
587                         } else {
588                                 return;
589                         }
590
591                         if (event.getKind() == DebugEvent.MODEL_SPECIFIC) {
592                                 switch (event.getDetail()) {
593                                         case IPHPDebugEvent.BREAKPOINT_HIT:
594                                                 int id = fDebugConnection.stackGet();
595                                                 XDebugResponse lastResponse = getResponse(id);
596
597                                                 IBreakpoint breakpoint = breakpointHit(lastResponse.getParentNode());
598
599                                                 if (breakpoint != null) {
600                                                         fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
601                                                         fThread.incrementStepCounter();
602                                                         suspended(DebugEvent.BREAKPOINT);
603                                                 } else {
604                                                         try {
605                                                                 resume();
606                                                         } catch (DebugException e ) {
607                                                                 ; //nothing to do
608                                                         }
609                                                 }
610                                                 break;
611                                         case IPHPDebugEvent.STEP_END:
612                                                 fThread.incrementStepCounter();
613                                                 suspended(DebugEvent.STEP_END);
614                                                 break;
615                                         case IPHPDebugEvent.STOPPED:
616                                                 stopped();
617                                                 break;
618                                 }
619                         }
620                 }
621         }
622
623         public void stopped() {
624                 if(fDebugConnection == null) {
625                         return;
626                 }
627
628                 resumed(DebugEvent.TERMINATE);
629
630                 stopListener();
631                 fDebugConnection.close();
632
633                 fSuspended = false;
634
635                 // Dirty hack to check debugging mode (remote or local)
636                 if (fProcess != null) {
637                         try {
638                                 terminate();
639                         } catch (DebugException e) {
640                                 e.printStackTrace();
641                         }
642                 } else {
643                         fDebugConnection = null;
644                         fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
645                 }
646
647                 fThread.removeEventListeners();
648                 fThread = null;
649                 fThreads = new IThread[0];
650         }
651
652         public void handleProxyEvent(XDebugConnection connection) {
653                 //System.out.println("* New Connection - XDebug.Target: " + fDebugConnection.getSessionID());
654
655                 if (setDebugConnection(connection)) {
656                         fThread = new XDebugThread(this);
657                         fThreads = new IThread[] {fThread};
658                         fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CHANGE));
659                         try {
660                                 started();
661                         } catch( DebugException e ){
662                                 e.printStackTrace();
663                         }
664                 }
665         }
666
667         private boolean setDebugConnection(XDebugConnection connection) {
668                 if (connection != null && fDebugConnection == null) {
669                         fDebugConnection = connection;
670                         fResponseListener = new ResponseListener(connection);
671                         startListener();
672
673                         return true;
674                 } else {
675                         connection.close();
676
677                         return false;
678                 }
679         }
680
681         /**
682          * @return Returns the fDebugConnection.
683          */
684         public XDebugConnection getDebugConnection() {
685                 return fDebugConnection;
686         }
687
688         public void addProcess(IProcess p) {
689                 fProcess = p;
690
691         }
692         public Node getLocalVariables(int level) throws DebugException {
693                 int id = fDebugConnection.contextGet(level, 0);
694                 XDebugResponse response = getResponse(id);
695
696                 return response.getParentNode();
697         }
698
699         public Node getGlobalVariables(int level) throws DebugException {
700                 int id = fDebugConnection.contextGet(level, 1);
701                 XDebugResponse response = getResponse(id);
702
703                 return response.getParentNode();
704         }
705
706         public void stop() {
707                 fDebugConnection.stop();
708         }
709
710         protected IBreakpoint breakpointHit(Node node) {
711                 Node child = node.getFirstChild();
712                 if (child.getNodeName().equals("stack")) {
713                         int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "lineno"));
714                         String filename = PHPDebugUtils.getAttributeValue(child, "filename");
715                         IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
716                         for (int i = 0; i < breakpoints.length; i++) {
717                                 IBreakpoint breakpoint = breakpoints[i];
718                                 if (supportsBreakpoint(breakpoint)) {
719                                         if (breakpoint instanceof ILineBreakpoint) {
720                                                 ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
721                                                 try {
722                                                         if (breakpoint.isEnabled()) {
723                                                                 IMarker marker = breakpoint.getMarker();
724                                                                 if (marker != null) {
725                                                                         String endfilename;
726
727                                                                         if (getProcess() == null) {
728                                                                                 endfilename = marker.getResource().getLocation().lastSegment();
729                                                                         } else {
730                                                                                 endfilename = marker.getResource().getLocation().toOSString();
731                                                                         }
732
733                                                                         int id = fDebugConnection.breakpointGet(marker.getAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,-1));
734                                                                         XDebugResponse dr = getResponse(id);
735
736                                                                         Node hitCo = dr.getParentNode().getFirstChild();
737                                                                         int hitCount = 0;
738                                                                         if (hitCo.hasAttributes()) {
739                                                                                 NamedNodeMap listAttribute = hitCo.getAttributes();
740                                                                                 Node attribute = listAttribute.getNamedItem("hit_count");
741                                                                                 if (attribute !=null) {
742                                                                                         hitCount = Integer.parseInt(attribute.getNodeValue());
743                                                                                 }
744                                                                         }
745
746                                                                         Path path1 = new Path (PHPDebugUtils.unescapeString (filename));
747                                                                         Path path2 = new Path (endfilename);
748
749                                                                         if (path1.toString ().endsWith (path2.toString ())
750 //                                                                      if (strPath1.endsWith (strPath2)
751                                                                         //if(PHPDebugUtils.unescapeString(filename).endsWith(endfilename)
752                                                                                         && (lineBreakpoint.getLineNumber() == lineNumber) ) {
753                                                                                 if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) > 0) {
754                                                                                         if (marker.getAttribute(XDebugLineBreakpoint.HIT_COUNT, 0) == hitCount) {
755                                                                                                 return (breakpoint);
756                                                                                         }
757                                                                                 } else {
758                                                                                         return (breakpoint);
759                                                                                 }
760                                                                         }
761                                                                 }
762                                                         }
763                                                 } catch (CoreException e) {
764                                                 }
765                                         }
766                                 }
767                         }
768                 }
769
770                 return null;
771         }
772
773         public void startListener() {
774                 fResponseListener.schedule();
775         }
776
777         public void stopListener() {
778                 fResponseListener.cancel();
779         }
780         public XDebugResponse getResponse(int id) {
781                 XDebugResponse response = fResponseListener.getResponse(id);
782
783                 return response;
784         }
785 }