Patch from Martin Koegler:
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / model / PHPDebugTarget.java
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
7
8 Contributors:
9     IBM Corporation - Initial implementation
10     Vicente Fernando - www.alfersoft.com.ar
11 **********************************************************************/
12 package net.sourceforge.phpdt.internal.debug.core.model;
13
14 import net.sourceforge.phpdt.internal.debug.core.PHPDBGProxy;
15 import net.sourceforge.phpdt.internal.debug.core.PHPDebugCorePlugin;
16
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;
30
31 /**
32  * Debug target for PHP debug model.
33  */
34 public class PHPDebugTarget implements IPHPDebugTarget, ILaunchListener, IDebugEventSetListener {
35                 
36         private IProcess process;
37         private boolean isTerminated;
38         private boolean isSuspended;
39         private ILaunch launch;
40         private PHPThread[] threads;
41         private PHPDBGProxy phpDBGProxy;
42
43         public PHPDebugTarget(ILaunch launch, IProcess process) {
44                 this.isSuspended = false;
45                 this.launch = launch;
46                 this.process = process;
47                 this.threads = new PHPThread[0];
48                 IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
49                 manager.addBreakpointListener(this);
50                 DebugPlugin.getDefault().addDebugEventListener(this);
51                 initialize();
52         }
53
54         protected synchronized void initialize() {
55                 DebugEvent ev = new DebugEvent(this, DebugEvent.CREATE);
56                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });    
57         }
58
59         public void addThread(PHPThread phpThread) {
60                 int i;
61                 PHPThread[] updatedThreads = new PHPThread[threads.length + 1];
62                 
63                 for(i=0; i < threads.length; i++) {
64                         updatedThreads[i] = threads[i];
65                 }
66                 updatedThreads[i] = phpThread;
67                 threads = updatedThreads;
68
69                 fireChangeEvent();
70         }
71
72         private void fireChangeEvent() {
73                 DebugEvent ev = new DebugEvent(this, DebugEvent.CHANGE);
74                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
75         }
76
77         protected PHPThread getThreadById(int id) {
78                 for (int i = 0; i < threads.length; i++) {
79                         if (threads[i].getId() == id) {
80                                 return threads[i];
81                         }
82                 }
83                 return null;
84         }
85
86         public IThread[] getThreads() {
87                 return threads;
88         }
89
90         public boolean hasThreads() throws DebugException {
91                 return threads.length > 0;
92         }
93
94         public String getName() throws DebugException {
95                 return "PHP Debugger at localhost:" + getPHPDBGProxy().getPort();
96         }
97
98         public boolean supportsBreakpoint(IBreakpoint arg0) {
99             if(arg0.getModelIdentifier().equals(PHPDebugCorePlugin.PLUGIN_ID)) {
100             return true;
101             }
102                 return false;
103         }
104
105         public String getModelIdentifier() {
106                 return PHPDebugCorePlugin.PLUGIN_ID;
107         }
108
109         public IDebugTarget getDebugTarget() {
110                 return this;
111         }
112
113         public ILaunch getLaunch() {
114                 return launch;
115         }
116
117         public boolean canTerminate() {
118                 return !isTerminated;
119         }
120
121         public boolean isTerminated() {
122                 return isTerminated;
123         }
124
125         public synchronized void terminate() {
126                 // This method is synchronized to control a race condition between the 
127                 // UI thread that terminates the debugging session, and the slave 
128                 // thread that executes PHPLoop.run
129                 if (isTerminated)
130                         // Avoid terminating twice...
131                         return;
132                 phpDBGProxy.stop();
133                 this.threads = new PHPThread[0];
134                 isTerminated = true;
135                 fireChangeEvent();
136         }
137
138         public boolean canResume() {
139                 if(isTerminated) return false;
140                 return isSuspended;
141         }
142
143         public boolean canSuspend() {
144                 if(isTerminated) return false;
145                 return !isSuspended;
146         }
147
148         public boolean isSuspended() {
149                 return isSuspended;
150         }
151
152         public void resume() throws DebugException {
153                 this.getPHPDBGProxy().resume();
154                 isSuspended= false;
155         }
156
157         public void suspend() throws DebugException {
158                 this.getPHPDBGProxy().pause();
159                 isSuspended= true;
160         }
161
162         public void breakpointAdded(IBreakpoint breakpoint) {
163                 this.getPHPDBGProxy().addBreakpoint(breakpoint) ;
164         }
165
166         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta arg1) {
167                 this.getPHPDBGProxy().removeBreakpoint(breakpoint) ;            
168         }
169
170         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta arg1) {
171                 // is called e.g. after a line has been inserted before a breakpoint
172                 // but then the debugger is out of sync with the file anyway, so debugging
173                 // should be stopped here.
174         }
175
176         public boolean canDisconnect() {
177                 return false;
178         }
179
180         public void disconnect() throws DebugException {
181         }
182
183         public boolean isDisconnected() {
184                 return false;
185         }
186
187         public boolean supportsStorageRetrieval() {
188                 return false;
189         }
190
191         public IMemoryBlock getMemoryBlock(long arg0, long arg1) throws DebugException {
192                 return null;
193         }
194
195         public Object getAdapter(Class arg0) {
196                 return null;
197         }
198
199         public IProcess getProcess() {
200                 return process;
201         }
202
203         public void setProcess(IProcess process) {
204                 this.process = process;
205         }
206
207         public PHPDBGProxy getPHPDBGProxy() {
208                 return phpDBGProxy;
209         }
210
211         public void setPHPDBGProxy(PHPDBGProxy phpDBGProxy) {
212                 this.phpDBGProxy = phpDBGProxy;
213         }
214         
215         /**
216          * @see ILaunchListener#launchRemoved(ILaunch)
217          */
218         public void launchRemoved(ILaunch launch) {
219                 if (!isTerminated()) {
220                         return;
221                 }
222                 if (launch.equals(getLaunch())) {
223                         // This target has been deregistered, but it hasn't successfully terminated.
224                         // Update internal state to reflect that it is disconnected
225                         terminate();
226                 }
227         }
228         
229         /**
230          * @see ILaunchListener#launchAdded(ILaunch)
231          */
232         public void launchAdded(ILaunch launch) {
233         }
234         
235         /**
236          * @see ILaunchListener#launchChanged(ILaunch)
237          */
238         public void launchChanged(ILaunch launch) {
239         }
240         
241         /**
242          * When a debug target or process terminates, terminate DBG Proxy.
243          * 
244          * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
245          */
246         public void handleDebugEvents(DebugEvent[] events) {
247                 for (int i = 0; i < events.length; i++) {
248                         DebugEvent event = events[i];
249                         if (event.getKind() == DebugEvent.TERMINATE) {
250                                 Object source = event.getSource();
251                                 if (source instanceof PHPDebugTarget || source instanceof IDebugTarget) {
252                                         getPHPDBGProxy().stop();
253                                 } else if(source instanceof IProcess) {
254                                         if(getDebugTarget().getProcess() == (IProcess)source) {
255                                                 getPHPDBGProxy().stop();
256                                         }
257                                 }
258                         } else if (event.getKind() == DebugEvent.SUSPEND) {
259                                 getPHPDBGProxy().pause();
260                         }
261                 }
262         }
263 }
264