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