4 package net.sourceforge.phpeclipse.xdebug.php.model;
 
   8 import net.sourceforge.phpeclipse.xdebug.core.AbstractDebugConnection;
 
   9 import net.sourceforge.phpeclipse.xdebug.core.IDebugConnection;
 
  10 import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
 
  11 import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
 
  12 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
 
  13 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
 
  14 import net.sourceforge.phpeclipse.xdebug.core.XDebugProxy;
 
  15 import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
 
  17 import org.eclipse.core.resources.IMarker;
 
  18 import org.eclipse.core.resources.IMarkerDelta;
 
  19 import org.eclipse.core.runtime.CoreException;
 
  20 import org.eclipse.core.runtime.IPath;
 
  21 import org.eclipse.debug.core.DebugEvent;
 
  22 import org.eclipse.debug.core.DebugException;
 
  23 import org.eclipse.debug.core.DebugPlugin;
 
  24 import org.eclipse.debug.core.IDebugEventSetListener;
 
  25 import org.eclipse.debug.core.ILaunch;
 
  27 import org.eclipse.debug.core.ILaunchListener;
 
  29 import org.eclipse.debug.core.model.IBreakpoint;
 
  30 import org.eclipse.debug.core.model.IDebugTarget;
 
  31 import org.eclipse.debug.core.model.IMemoryBlock;
 
  32 import org.eclipse.debug.core.model.IProcess;
 
  33 import org.eclipse.debug.core.model.IStackFrame;
 
  34 import org.eclipse.debug.core.model.IThread;
 
  35 import org.eclipse.debug.core.model.IValue;
 
  36 import org.eclipse.debug.core.model.IVariable;
 
  38 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener.DebugResponse;
 
  44 public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunchListener, IDebugEventSetListener, IProxyEventListener{
 
  45         // associated system process (VM)
 
  46         private IProcess fProcess;
 
  48         // containing launch object
 
  49         private ILaunch fLaunch;
 
  52         private int fDebugPort;
 
  55         private boolean fSuspended = false;
 
  58         private boolean fTerminated = false;
 
  61         private XDebugThread fThread;
 
  62         private IThread[] fThreads;
 
  64         private AbstractDebugConnection fDebugConnection;
 
  66         private String fIdeKey;
 
  69         public XDebugTarget() {
 
  74          * Constructs a new debug target in the given launch and waits until
 
  75          * someone with the ideKey connects to the Debugproxy
 
  78          * @param launch containing launch
 
  79          * @param process process of the interpreter
 
  81          * @exception CoreException if unable to connect to host
 
  84         public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
 
  85                 init(launch, process, ideKey);
 
  89          * Constructs a new debug target in the given launch and waits until
 
  90          * someone with the ideKey connects to the Debugproxy
 
  93          * @param launch containing launch
 
  94          * @param process process of the interpreter
 
  96          * @param pathMap Pathmap for the debug session
 
  97          * @exception CoreException if unable to connect to host
 
 100         /*public XDebugTarget(ILaunch launch, IProcess process, String ideKey, List<String> pathMap) throws CoreException {
 
 102                 init(launch, process, ideKey,pathMap);
 
 105         private void init(ILaunch launch, IProcess process, String ideKey/*,List<String> pathMap*/) {
 
 109                 fDebugConnection = null;
 
 111                 fThreads = new IThread[0];
 
 114                 XDebugProxy proxy = XDebugCorePlugin.getDefault().getXDebugProxy();
 
 115                 proxy.addProxyEventListener(this,ideKey);
 
 116                 if (!proxy.isRunning())
 
 119                 proxy.setTarget(this);
 
 121                 fDebugPort = proxy.getProxyPort();
 
 123                 DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
 
 124                 DebugPlugin.getDefault().addDebugEventListener(this);
 
 128          * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
 
 130         public IProcess getProcess() {
 
 135          * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
 
 137         public IThread[] getThreads() throws DebugException {
 
 142          * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
 
 144         public boolean hasThreads() throws DebugException {
 
 145                 return (fThreads.length>0);
 
 149          * @see org.eclipse.debug.core.model.IDebugTarget#getName()
 
 151         public String getName() throws DebugException {
 
 152                 return "PHP XDebug Client at localhost:" + fDebugPort;
 
 156          * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
 
 158         public boolean supportsBreakpoint(IBreakpoint breakpoint) {
 
 159                 if (breakpoint.getModelIdentifier().equals(IXDebugConstants.ID_PHP_DEBUG_MODEL)) {
 
 166          * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
 
 168         public IDebugTarget getDebugTarget() {
 
 173          * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
 
 175         public ILaunch getLaunch() {
 
 180          * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
 
 182         public boolean canTerminate() {
 
 183                 if (getProcess()!=null)  // ther is no running Process in remote debugging
 
 184                         return getProcess().canTerminate();
 
 189          * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
 
 191         public boolean isTerminated() {
 
 192 //              return getProcess().isTerminated();
 
 197          * @see org.eclipse.debug.core.model.ITerminate#terminate()
 
 199         public void terminate() throws DebugException {
 
 200                 //IThread  t = fThreads.length();
 
 202                 XDebugProxy proxy=XDebugCorePlugin.getDefault().getXDebugProxy();
 
 204                 proxy.removeProxyEventListener(this,fIdeKey);
 
 205                 System.out.println("XDebug.Target: ProxyEventlistener removed");
 
 207                 //fDisconnected = true;
 
 209                 XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
 
 210                 fireTerminateEvent();
 
 211                 DebugPlugin.getDefault().removeDebugEventListener(this);
 
 213                         fThread.removeEventListeners();
 
 217          * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
 
 219         public boolean canResume() {
 
 220 //              return !isTerminated() && isSuspended();
 
 225          * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
 
 227         public boolean canSuspend() {
 
 228 //              return !isTerminated() && !isSuspended();
 
 233          * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
 
 235         public boolean isSuspended() {
 
 240          * @see org.eclipse.debug.core.model.ISuspendResume#resume()
 
 242         public void resume() throws DebugException {
 
 243                 if (fDebugConnection != null) {
 
 244                         fThread.setBreakpoints(null);
 
 245                         fDebugConnection.run();
 
 250          * Notification the target has resumed for the given reason
 
 252          * @param detail reason for the resume
 
 254         private void resumed(int detail) {
 
 256                 fThread.fireResumeEvent(detail);
 
 260          * Notification the target has suspended for the given reason
 
 262          * @param detail reason for the suspend
 
 264         public void suspended(int detail) {
 
 266                 fThread.fireSuspendEvent(detail);
 
 270          * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
 
 272         public void suspend() throws DebugException {
 
 276          * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
 
 278         public void breakpointAdded(IBreakpoint breakpoint) {
 
 279                 IMarker marker = breakpoint.getMarker();
 
 280                 IPath path = marker.getResource().getLocation();
 
 281                 IPath cp = path.removeLastSegments(1);
 
 284                         pathMap = fLaunch.getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP,(List)null);
 
 285                 } catch (CoreException e2) {
 
 286                         // TODO Auto-generated catch block
 
 287                         e2.printStackTrace();
 
 290                 if (!fDebugConnection.isClosed()) {
 
 291                         if (fProcess == null) {
 
 292                                 PathMapItem pmi = null;
 
 293                                 for (int i = 0; i < pathMap.size(); i++) {
 
 294                                         pmi = new PathMapItem((String) pathMap.get(i));
 
 295                                         IPath local = (IPath)pmi.getLocalPath().clone();
 
 296                                         local = local./*removeFirstSegments(1).*/makeAbsolute();
 
 297                                         int matchedSegments = local.segmentCount();
 
 298                                         if (local.matchingFirstSegments(cp) == matchedSegments) {
 
 299                                                 IPath newPath = pmi.getRemotePath();
 
 300                                                 //newPath = newPath.removeFirstSegments(1);                                             
 
 301                                                 newPath = newPath.append(path.removeFirstSegments(matchedSegments));
 
 302                                                 newPath = newPath.makeAbsolute();
 
 303                                                 if (supportsBreakpoint(breakpoint)) {
 
 305                                                                 fDebugConnection.addBreakpoint(breakpoint, newPath);
 
 306                                                         } catch (DebugException e) {
 
 313                                 if (supportsBreakpoint(breakpoint)) {
 
 315                                                 fDebugConnection.addBreakpoint(breakpoint, path);
 
 316                                         } catch (DebugException e) {
 
 325          * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
 
 327         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
 
 328                 if (supportsBreakpoint(breakpoint)) {
 
 330                                 fDebugConnection.removeBreakpoint(breakpoint);
 
 331                         } catch (CoreException e) {
 
 337          * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
 
 339         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
 
 340 //              if (supportsBreakpoint(breakpoint)) {
 
 342 //                              if (breakpoint.isEnabled()) {
 
 343 //                                      breakpointAdded(breakpoint);
 
 345 //                                      breakpointRemoved(breakpoint, null);
 
 347 //                      } catch (CoreException e) {
 
 353          * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
 
 355         public boolean canDisconnect() {
 
 360          * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
 
 362         public void disconnect() throws DebugException {
 
 366          * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
 
 368         public boolean isDisconnected() {
 
 369                 return (fDebugConnection==null);
 
 373          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
 
 375         public boolean supportsStorageRetrieval() {
 
 380          * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
 
 382         public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
 
 387          * Notification we have connected to the PHP debugger and it has been started.
 
 388          * Resume the the debugger.
 
 390         public void started() throws DebugException {
 
 391                 fThread.setBreakpoints(null);
 
 392                 fThread.setStepping(false);
 
 394                 /*boolean CanDisconnect =*/ Integer.parseInt(fDebugConnection.featureGet("detach").getValue()) /*!= 0*/;
 
 396                 System.out.println("in Target.started()");
 
 397                 DebugResponse response = fDebugConnection.featureGet("max_children");
 
 398                 String a1 = response.getValue();
 
 399                 System.out.println("max children:"+a1);
 
 400                 DebugResponse response1 = fDebugConnection.featureGet("max_children");
 
 401                 String a2 = response1.getValue();
 
 402                 System.out.println("max depth:"+a2);
 
 405                 boolean res = fDebugConnection.featureSet("max_depth", "100" );
 
 407                         System.out.println("Set depth to 100 (hack)");
 
 410                 installDeferredBreakpoints();
 
 414                 } catch (DebugException e) {
 
 420          * Install breakpoints that are already registered with the breakpoint
 
 423         private void installDeferredBreakpoints() {
 
 424                 IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
 
 425                 for (int i = 0; i < breakpoints.length; i++) {
 
 426                         breakpointAdded(breakpoints[i]);
 
 431          * Called when this debug target terminates.
 
 433         public void terminated() {
 
 436                 XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
 
 437                 fireTerminateEvent();
 
 438                 DebugPlugin.getDefault().removeDebugEventListener(this);
 
 439                 fThread.removeEventListeners(); 
 
 443          * Returns the current stack frames in the target.
 
 445          * @return the current stack frames in the target
 
 446          * @throws DebugException if unable to perform the request
 
 448         protected IStackFrame[] getStackFrames() throws DebugException {
 
 449                 return fDebugConnection.getStackFrames(fThread);
 
 453          * Single step the interpreter.
 
 455          * @throws DebugException if the request fails
 
 457         protected void step_over() throws DebugException {
 
 458                 fThread.setStepping(true);
 
 459                 resumed(DebugEvent.STEP_OVER);
 
 460                 fDebugConnection.stepOver();
 
 464          * Single step the interpreter.
 
 466          * @throws DebugException if the request fails
 
 468         protected void step_into() throws DebugException {
 
 469                 fThread.setStepping(true);
 
 470                 resumed(DebugEvent.STEP_INTO);
 
 471                 fDebugConnection.stepInto();
 
 475          * Single step the interpreter.
 
 477          * @throws DebugException if the request fails
 
 479         protected void step_out() throws DebugException {
 
 480                 fThread.setStepping(true);
 
 481                 resumed(DebugEvent.STEP_RETURN);
 
 482                 fDebugConnection.stepOut();
 
 486          * Returns the current value of the given variable.
 
 489          * @return variable value
 
 490          * @throws DebugException if the request fails
 
 492         protected IValue getVariableValue(XDebugVariable variable) throws DebugException {
 
 497          * Returns the values on the data stack (top down)
 
 499          * @return the values on the data stack (top down)
 
 501         public IValue[] getDataStack() throws DebugException {
 
 502                 return new IValue[0];           
 
 505         public boolean setVarValue(String name, String value) {
 
 506                 return fDebugConnection.setVarValue(name,value);
 
 509         public void handleDebugEvents(DebugEvent[] events) {
 
 510                 for (int i=0;i<events.length;i++) {
 
 511                         DebugEvent event=events[i];
 
 512                         if(event.getKind()==DebugEvent.MODEL_SPECIFIC) {
 
 513                                 if (event.getDetail()==IPHPDebugEvent.BREAKPOINT_HIT) {
 
 514                                         IBreakpoint breakpoint = (IBreakpoint) event.getData();
 
 515                                         fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
 
 516                                         fThread.incrementStepCounter();
 
 517                                         suspended(DebugEvent.BREAKPOINT);
 
 518                                 } else if (event.getDetail()==IPHPDebugEvent.STEP_END) {
 
 519                                         fThread.incrementStepCounter();
 
 520                                         suspended(DebugEvent.STEP_END);
 
 521                                 } else if (event.getDetail()==IPHPDebugEvent.STOPPED) {
 
 522                                         //fDebugConnection.removeBreakpoint(breakpoint);
 
 523                                         fThread.removeEventListeners();
 
 525                                         fThreads= new IThread[0];
 
 527                                         // TODO Dirty hack to check debugging mode (remote or local)
 
 528                                         if (fProcess!=null) {
 
 531                                                 } catch (DebugException e) {
 
 535                                                 fDebugConnection = null;
 
 536                                                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
 
 550         public void handleProxyEvent(String ideKey, String initString, AbstractDebugConnection connection) {
 
 551                 System.out.println("* New Connection - XDebug.Target: "+ideKey);
 
 552                 setDebugConnection(connection);
 
 554                 XDebugProxy proxy=XDebugCorePlugin.getDefault().getXDebugProxy();
 
 555                 fDebugPort=proxy.getProxyPort();
 
 556                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CHANGE));
 
 559 //              proxy.removeProxyEventListener(this,ideKey);
 
 560 //              System.out.println("XDebug.Target: ProxyEventlistener removed");
 
 561                 fThread = new XDebugThread(this);
 
 562                 fThreads = new IThread[] {fThread};
 
 565                 } catch( DebugException e ){
 
 570         private void setDebugConnection(AbstractDebugConnection connection) {
 
 571                 if (connection != null) {
 
 572                         fDebugConnection = connection;
 
 573                         fDebugConnection.startListener();
 
 578          * @return Returns the fDebugConnection.
 
 580         public IDebugConnection getDebugConnection() {
 
 581                 return fDebugConnection;
 
 584         public void addProcess(IProcess p) {
 
 589         public void launchRemoved(ILaunch launch) {
 
 593          * Notifies this listener that the specified launch
 
 596          * @param launch the newly added launch
 
 599         public void launchAdded(ILaunch launch){
 
 603          * Notifies this listener that the specified launch
 
 604          * has changed. For example, a process or debug target
 
 605          * has been added to the launch.
 
 607          * @param launch the changed launch
 
 610         public void launchChanged(ILaunch launch) {
 
 613         public IVariable[] getVariables(XDebugStackFrame StackFrame, int Level) {
 
 614                 return fDebugConnection.getVariables(StackFrame, Level);