4a9dccbc806d1eea16242e3f4f9746f8bbf6fdf6
[phpeclipse.git] /
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                 // 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);
52                 initialize();
53         }
54
55         protected synchronized void initialize() {
56                 DebugEvent ev = new DebugEvent(this, DebugEvent.CREATE);
57                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });    
58         }
59
60         public void addThread(PHPThread phpThread) {
61                 int i;
62                 PHPThread[] updatedThreads = new PHPThread[threads.length + 1];
63                 
64                 for(i=0; i < threads.length; i++) {
65                         updatedThreads[i] = threads[i];
66                 }
67                 updatedThreads[i] = phpThread;
68                 threads = updatedThreads;
69
70                 fireChangeEvent();
71         }
72
73         private void fireChangeEvent() {
74                 DebugEvent ev = new DebugEvent(this, DebugEvent.CHANGE);
75                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
76         }
77
78         protected PHPThread getThreadById(int id) {
79                 for (int i = 0; i < threads.length; i++) {
80                         if (threads[i].getId() == id) {
81                                 return threads[i];
82                         }
83                 }
84                 return null;
85         }
86
87         public IThread[] getThreads() {
88                 return threads;
89         }
90
91         public boolean hasThreads() throws DebugException {
92                 return threads.length > 0;
93         }
94
95         public String getName() throws DebugException {
96                 return "PHP Debugger at localhost:" + getPHPDBGProxy().getPort();
97         }
98
99         public boolean supportsBreakpoint(IBreakpoint arg0) {
100             if(arg0.getModelIdentifier().equals(PHPDebugCorePlugin.PLUGIN_ID)) {
101             return true;
102             }
103                 return false;
104         }
105
106         public String getModelIdentifier() {
107                 return PHPDebugCorePlugin.PLUGIN_ID;
108         }
109
110         public IDebugTarget getDebugTarget() {
111                 return this;
112         }
113
114         public ILaunch getLaunch() {
115                 return launch;
116         }
117
118         public boolean canTerminate() {
119                 return !isTerminated;
120         }
121
122         public boolean isTerminated() {
123                 return isTerminated;
124         }
125
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
130                 if (isTerminated)
131                         // Avoid terminating twice...
132                         return;
133                 phpDBGProxy.stop();
134                 this.threads = new PHPThread[0];
135                 isTerminated = true;
136                 fireChangeEvent();
137         }
138
139         public boolean canResume() {
140                 if(isTerminated) return false;
141                 return isSuspended;
142         }
143
144         public boolean canSuspend() {
145                 if(isTerminated) return false;
146                 return !isSuspended;
147         }
148
149         public boolean isSuspended() {
150                 return isSuspended;
151         }
152
153         public void resume() throws DebugException {
154                 this.getPHPDBGProxy().resume();
155                 isSuspended= false;
156         }
157
158         public void suspend() throws DebugException {
159                 this.getPHPDBGProxy().pause();
160                 isSuspended= true;
161         }
162
163         public void breakpointAdded(IBreakpoint breakpoint) {
164                 this.getPHPDBGProxy().addBreakpoint(breakpoint) ;
165         }
166
167         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta arg1) {
168                 this.getPHPDBGProxy().removeBreakpoint(breakpoint) ;            
169         }
170
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.
175         }
176
177         public boolean canDisconnect() {
178                 return false;
179         }
180
181         public void disconnect() throws DebugException {
182         }
183
184         public boolean isDisconnected() {
185                 return false;
186         }
187
188         public boolean supportsStorageRetrieval() {
189                 return false;
190         }
191
192         public IMemoryBlock getMemoryBlock(long arg0, long arg1) throws DebugException {
193                 return null;
194         }
195
196         public Object getAdapter(Class arg0) {
197                 return null;
198         }
199
200         public IProcess getProcess() {
201                 return process;
202         }
203
204         public void setProcess(IProcess process) {
205                 this.process = process;
206         }
207
208         public PHPDBGProxy getPHPDBGProxy() {
209                 return phpDBGProxy;
210         }
211
212         public void setPHPDBGProxy(PHPDBGProxy phpDBGProxy) {
213                 this.phpDBGProxy = phpDBGProxy;
214         }
215         
216         /**
217          * @see ILaunchListener#launchRemoved(ILaunch)
218          */
219         public void launchRemoved(ILaunch launch) {
220                 if (!isTerminated()) {
221                         return;
222                 }
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
226                         terminate();
227                 }
228         }
229         
230         /**
231          * @see ILaunchListener#launchAdded(ILaunch)
232          */
233         public void launchAdded(ILaunch launch) {
234         }
235         
236         /**
237          * @see ILaunchListener#launchChanged(ILaunch)
238          */
239         public void launchChanged(ILaunch launch) {
240         }
241         
242         /**
243          * When a debug target or process terminates, terminate DBG Proxy.
244          * 
245          * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
246          */
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();
257                                         }
258                                 }
259                         } else if (event.getKind() == DebugEvent.SUSPEND) {
260                                 getPHPDBGProxy().pause();
261                         }
262                 }
263         }
264 }
265