1 /**********************************************************************
 
   2 Copyright (c) 2000, 2002 IBM Corp. and others.
 
   3 All rights reserved. This program and the accompanying materials
 
   4 are made available under the terms of the Common Public License v1.0
 
   5 which accompanies this distribution, and is available at
 
   6 http://www.eclipse.org/legal/cpl-v10.html
 
   9     IBM Corporation - Initial implementation
 
  10     Vicente Fernando - www.alfersoft.com.ar
 
  11 **********************************************************************/
 
  12 package net.sourceforge.phpdt.internal.debug.core.model;
 
  14 import net.sourceforge.phpdt.internal.debug.core.PHPDBGProxy;
 
  15 import net.sourceforge.phpdt.internal.debug.core.PHPDebugCorePlugin;
 
  17 import org.eclipse.core.resources.IMarkerDelta;
 
  18 import org.eclipse.debug.core.DebugEvent;
 
  19 import org.eclipse.debug.core.DebugException;
 
  20 import org.eclipse.debug.core.DebugPlugin;
 
  21 import org.eclipse.debug.core.IBreakpointManager;
 
  22 import org.eclipse.debug.core.IDebugEventSetListener;
 
  23 import org.eclipse.debug.core.ILaunch;
 
  24 import org.eclipse.debug.core.ILaunchListener;
 
  25 import org.eclipse.debug.core.model.IBreakpoint;
 
  26 import org.eclipse.debug.core.model.IDebugTarget;
 
  27 import org.eclipse.debug.core.model.IMemoryBlock;
 
  28 import org.eclipse.debug.core.model.IProcess;
 
  29 import org.eclipse.debug.core.model.IThread;
 
  32  * Debug target for PHP debug model.
 
  34 public class PHPDebugTarget implements IPHPDebugTarget, ILaunchListener, IDebugEventSetListener {
 
  36         private IProcess process;
 
  37         private boolean isTerminated;
 
  38         private boolean isSuspended;
 
  39         private ILaunch launch;
 
  40         private PHPThread[] threads;
 
  41         private PHPDBGProxy phpDBGProxy;
 
  43         public PHPDebugTarget(ILaunch launch, IProcess process) {
 
  44                 this.isSuspended = false;
 
  46                 this.process = process;
 
  47                 this.threads = new PHPThread[0];
 
  48                 // TODO XXX remove breakpoint listener at termination to avoid live leak
 
  49                 IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
 
  50                 manager.addBreakpointListener(this);
 
  51                 DebugPlugin.getDefault().addDebugEventListener(this);
 
  55         protected synchronized void initialize() {
 
  56                 DebugEvent ev = new DebugEvent(this, DebugEvent.CREATE);
 
  57                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });    
 
  60         public void addThread(PHPThread phpThread) {
 
  62                 PHPThread[] updatedThreads = new PHPThread[threads.length + 1];
 
  64                 for(i=0; i < threads.length; i++) {
 
  65                         updatedThreads[i] = threads[i];
 
  67                 updatedThreads[i] = phpThread;
 
  68                 threads = updatedThreads;
 
  73         private void fireChangeEvent() {
 
  74                 DebugEvent ev = new DebugEvent(this, DebugEvent.CHANGE);
 
  75                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
 
  78         protected PHPThread getThreadById(int id) {
 
  79                 for (int i = 0; i < threads.length; i++) {
 
  80                         if (threads[i].getId() == id) {
 
  87         public IThread[] getThreads() {
 
  91         public boolean hasThreads() throws DebugException {
 
  92                 return threads.length > 0;
 
  95         public String getName() throws DebugException {
 
  96                 return "PHP Debugger at localhost:" + getPHPDBGProxy().getPort();
 
  99         public boolean supportsBreakpoint(IBreakpoint arg0) {
 
 100             if(arg0.getModelIdentifier().equals(PHPDebugCorePlugin.PLUGIN_ID)) {
 
 106         public String getModelIdentifier() {
 
 107                 return PHPDebugCorePlugin.PLUGIN_ID;
 
 110         public IDebugTarget getDebugTarget() {
 
 114         public ILaunch getLaunch() {
 
 118         public boolean canTerminate() {
 
 119                 return !isTerminated;
 
 122         public boolean isTerminated() {
 
 126         public synchronized void terminate() {
 
 127                 // This method is synchronized to control a race condition between the 
 
 128                 // UI thread that terminates the debugging session, and the slave 
 
 129                 // thread that executes PHPLoop.run
 
 131                         // Avoid terminating twice...
 
 134                 this.threads = new PHPThread[0];
 
 139         public boolean canResume() {
 
 140                 if(isTerminated) return false;
 
 144         public boolean canSuspend() {
 
 145                 if(isTerminated) return false;
 
 149         public boolean isSuspended() {
 
 153         public void resume() throws DebugException {
 
 154                 this.getPHPDBGProxy().resume();
 
 158         public void suspend() throws DebugException {
 
 159                 this.getPHPDBGProxy().pause();
 
 163         public void breakpointAdded(IBreakpoint breakpoint) {
 
 164                 this.getPHPDBGProxy().addBreakpoint(breakpoint) ;
 
 167         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta arg1) {
 
 168                 this.getPHPDBGProxy().removeBreakpoint(breakpoint) ;            
 
 171         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta arg1) {
 
 172                 // is called e.g. after a line has been inserted before a breakpoint
 
 173                 // but then the debugger is out of sync with the file anyway, so debugging
 
 174                 // should be stopped here.
 
 177         public boolean canDisconnect() {
 
 181         public void disconnect() throws DebugException {
 
 184         public boolean isDisconnected() {
 
 188         public boolean supportsStorageRetrieval() {
 
 192         public IMemoryBlock getMemoryBlock(long arg0, long arg1) throws DebugException {
 
 196         public Object getAdapter(Class arg0) {
 
 200         public IProcess getProcess() {
 
 204         public void setProcess(IProcess process) {
 
 205                 this.process = process;
 
 208         public PHPDBGProxy getPHPDBGProxy() {
 
 212         public void setPHPDBGProxy(PHPDBGProxy phpDBGProxy) {
 
 213                 this.phpDBGProxy = phpDBGProxy;
 
 217          * @see ILaunchListener#launchRemoved(ILaunch)
 
 219         public void launchRemoved(ILaunch launch) {
 
 220                 if (!isTerminated()) {
 
 223                 if (launch.equals(getLaunch())) {
 
 224                         // This target has been deregistered, but it hasn't successfully terminated.
 
 225                         // Update internal state to reflect that it is disconnected
 
 231          * @see ILaunchListener#launchAdded(ILaunch)
 
 233         public void launchAdded(ILaunch launch) {
 
 237          * @see ILaunchListener#launchChanged(ILaunch)
 
 239         public void launchChanged(ILaunch launch) {
 
 243          * When a debug target or process terminates, terminate DBG Proxy.
 
 245          * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
 
 247         public void handleDebugEvents(DebugEvent[] events) {
 
 248                 for (int i = 0; i < events.length; i++) {
 
 249                         DebugEvent event = events[i];
 
 250                         if (event.getKind() == DebugEvent.TERMINATE) {
 
 251                                 Object source = event.getSource();
 
 252                                 if (source instanceof PHPDebugTarget || source instanceof IDebugTarget) {
 
 253                                         getPHPDBGProxy().stop();
 
 254                                 } else if(source instanceof IProcess) {
 
 255                                         if(getDebugTarget().getProcess() == (IProcess)source) {
 
 256                                                 getPHPDBGProxy().stop();
 
 259                         } else if (event.getKind() == DebugEvent.SUSPEND) {
 
 260                                 getPHPDBGProxy().pause();