fefd85ebfcf5cc8ab6da8b239647ff49672d316a
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / model / PHPThread.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.phpeclipse.PHPeclipsePlugin;
15
16 import org.eclipse.debug.core.DebugEvent;
17 import org.eclipse.debug.core.DebugException;
18 import org.eclipse.debug.core.DebugPlugin;
19 import org.eclipse.debug.core.ILaunch;
20 import org.eclipse.debug.core.model.IBreakpoint;
21 import org.eclipse.debug.core.model.IDebugTarget;
22 import org.eclipse.debug.core.model.IStackFrame;
23 import org.eclipse.debug.core.model.IThread;
24 import org.eclipse.jface.resource.ImageDescriptor;
25 import org.eclipse.ui.model.IWorkbenchAdapter;
26
27 public class PHPThread extends PHPDebugElement implements IThread {
28
29         private PHPStackFrame[] frames;         // The stackframes which belongs to this thread
30         private PHPDebugTarget  target;     //
31         private String                  name;       //
32         private int                     id;         // The port number through which we communicate to DBG
33
34         private class State {
35                 private boolean isSuspended  = false;
36                 private boolean isTerminated = false;
37                 private boolean isStepping       = false;
38
39                 boolean isSuspended () {
40                         return isSuspended;
41                 }
42
43                 boolean isTerminated () {
44                         return isTerminated;
45                 }
46
47                 boolean isStepping () {
48                         return isStepping;
49                 }
50
51                 void setSuspended (boolean suspended) {
52                         if (isTerminated ()) {
53                                 throw new IllegalStateException();
54                         }
55
56                         if (suspended && isStepping ()) {
57                                 throw new IllegalStateException ();
58                         }
59
60                         isSuspended = suspended;
61                 }
62
63                 void setStepping (boolean stepping) {
64                         if (stepping && !isSuspended ()) {
65                                 throw new IllegalStateException ();
66                         }
67
68                         if (isTerminated ()) {
69                                 throw new IllegalStateException ();
70                         }
71
72                         isStepping = stepping;
73                 }
74
75                 void setTerminated(boolean terminated) {
76                         isTerminated = terminated;
77                 }
78         }
79
80         private final State state = new State ();
81
82         /**
83          * @param target
84          * @param id            The port number through which we communicate to DBG
85          */
86         public PHPThread (PHPDebugTarget target, int id) {
87                 super (target);
88
89                 this.target = target;
90                 this.setId (id);
91         }
92
93         /**
94          *
95          */
96         public IStackFrame[] getStackFrames () throws DebugException {
97                 if (isSuspended()) {
98                         return ((PHPDebugTarget)getDebugTarget()).getStackFrames();
99                 } else {
100                         return new IStackFrame[0];
101                 }
102         }
103
104         public int getStackFramesSize () {
105                 return frames.length;
106         }
107
108         public boolean hasStackFrames () {
109                 if (frames == null) {
110                         return false;
111                 }
112
113                 return frames.length > 0;
114         }
115
116         public int getPriority () throws DebugException {
117                 return 0;
118         }
119
120         public IStackFrame getTopStackFrame () throws DebugException {
121                 if (frames == null || frames.length == 0) {
122                         return null;
123                 }
124                 return (IStackFrame) frames[0];
125         }
126
127         public IBreakpoint[] getBreakpoints() {
128                 return new IBreakpoint[0];
129         }
130
131         public String getModelIdentifier() {
132                 return this.getDebugTarget().getModelIdentifier();
133         }
134
135         public IDebugTarget getDebugTarget() {
136                 return target;
137         }
138
139         public void setDebugTarget(PHPDebugTarget target) {
140                 this.target = target;
141         }
142
143         public ILaunch getLaunch() {
144                 return this.getDebugTarget().getLaunch();
145         }
146
147         public synchronized boolean canResume() {
148                 return isSuspended();
149         }
150
151         public synchronized boolean canSuspend() {
152                 return !isSuspended();
153         }
154
155         public synchronized boolean isSuspended() {
156                 return state.isSuspended;
157         }
158
159         /**
160          *
161          * Is called from PHPstackframe whenever a stepInto, stepOver or stepReturn is
162          * to be performed
163          *
164          * @param de
165          */
166         protected void prepareForResume (int de) {
167                 DebugEvent ev;
168
169                 state.setSuspended (false);                                 // We will leave the suspended state
170                 this.frames = null;                                         // Reset the stackframes
171                 ev          = new DebugEvent (this, DebugEvent.RESUME, de); // Create an event resume by stepping
172
173                 DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev });  // Fire the event
174         }
175
176         /**
177          *
178          */
179         public synchronized void resume () throws DebugException {
180                 if (!isSuspended ()) {                                                                          // Is the thread in suspended state?
181                         return;                                                                                                 // No, leave here
182                 }
183
184                 this.prepareForResume (DebugEvent.STEP_OVER);               // Use a STEP_OVER here because a 0 leads to a collapsing variable tree in UI
185
186                 ((PHPDebugTarget) this.getDebugTarget ()).getPHPDBGProxy ().resume ();
187         }
188
189         /*
190          * public void doSuspend(SuspensionPoint suspensionPoint) { //
191          * this.getPHPDebuggerProxy().readFrames(this);
192          * this.createName(suspensionPoint) ; this.suspend() ; }
193          */
194
195         public synchronized void suspend () throws DebugException {
196                 DebugEvent ev;
197
198                 if (isSuspended ()) {                                                                           // Is the thread in suspend state?
199                         return;                                                                                                 // Yes, leave here
200                 }
201
202                 state.setSuspended (true);                                  // Set thread to suspended state
203                 state.setStepping (false);                                  // Reset thread from stepping state
204
205                 getDebugTarget ().suspend ();                                                           //
206
207                 ev = new DebugEvent (this, DebugEvent.SUSPEND, DebugEvent.BREAKPOINT);
208
209                 DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev });
210         }
211
212         /**
213          *
214          */
215         public boolean canStepInto () {
216                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
217                            isStepping () &&                                     // and ???
218                            this.hasStackFrames ();                              // and does this thread have stack frames?
219         }
220
221         /**
222          *
223          */
224         public boolean canStepOver () {
225                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
226                            isStepping () &&                                     // and ???
227                            this.hasStackFrames ();                              // and does this thread have stack frames?
228         }
229
230         /**
231          *
232          */
233         public boolean canStepReturn () {
234                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
235                            isStepping () &&                                     // and ???
236                            this.hasStackFrames ();                              // and does this thread have stack frames?
237         }
238
239         /**
240          *
241          */
242         public boolean isStepping () {
243                 return state.isStepping ();
244         }
245
246         /**
247          *
248          */
249         public void stepInto () throws DebugException {
250                 try {
251                         state.setStepping (true);                               // Store the info about what we do
252                 }
253                 catch (IllegalStateException x) {
254                         throw new DebugException (PHPeclipsePlugin.error (x));
255                 }
256
257                 this.frames = null;
258
259                 frames[0].stepInto ();
260         }
261
262         /**
263          *
264          */
265         public void stepOver () throws DebugException {
266                 state.setStepping (true);
267
268                 this.frames = null;
269
270                 frames[0].stepOver ();
271         }
272
273         /**
274          *
275          */
276         public void stepReturn () throws DebugException {
277         }
278
279         /**
280          *
281          */
282         public boolean canTerminate () {
283                 return !isTerminated ();
284         }
285
286         /**
287          *
288          */
289         public boolean isTerminated () {
290                 return state.isTerminated ();
291         }
292
293         /**
294          *
295          */
296         public synchronized void terminate () throws DebugException {
297                 if (isTerminated ()) {
298                         return;
299                 }
300
301                 state.setTerminated (true);
302                 this.frames = null;
303                 getDebugTarget ().terminate ();
304                 fireTerminateEvent ();
305         }
306
307         /**
308          *
309          * @param arg0
310          * @return
311          */
312         public Object getAdapter (Class arg0) {
313                 if (IWorkbenchAdapter.class.equals (arg0)) {
314                         return new IWorkbenchAdapter() {
315                                 public Object[] getChildren(Object o) {
316                                         try {
317                                                 return getStackFrames ();
318                                         } catch (DebugException x) {
319                                                 PHPeclipsePlugin.log ("Unable to get stack frames.", x);
320                                         }
321
322                                         return new Object[0];
323                                 }
324
325                                 public ImageDescriptor getImageDescriptor(Object object) {
326                                         return null;
327                                 }
328
329                                 public String getLabel(Object o) {
330                                         throw new UnsupportedOperationException();
331                                 }
332
333                                 public Object getParent(Object o) {
334                                         return getDebugTarget();
335                                 }
336                         };
337                 }
338                 return super.getAdapter(arg0);
339         }
340
341         /**
342          *
343          */
344         public void setStackFrames(PHPStackFrame[] frames) {
345                 this.frames = frames;
346         }
347
348         /**
349          *
350          */
351         public String getName () {
352                 String name;
353
354                 name = this.name;
355
356                 if (isSuspended ()) {
357                         name = name + " (suspended)";
358                 }
359
360                 return name;
361         }
362
363         public void setName (String name) {
364                 this.name = name;
365         }
366
367         /*
368          * protected void createName(SuspensionPoint suspensionPoint) { this.name =
369          * "PHP Thread - " + this.getId() ; if (suspensionPoint != null) { this.name += " (" +
370          * suspensionPoint + ")" ; } }
371          */
372
373         public int getId() {
374                 return id;
375         }
376
377         public void setId(int id) {
378                 this.id = id;
379         }
380
381 }