c6508e8af491f12f63e1adce90b7c8b37e6e5254
[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                 return frames;
98         }
99
100         public int getStackFramesSize () {
101                 return frames.length;
102         }
103
104         public boolean hasStackFrames () {
105                 if (frames == null) {
106                         return false;
107                 }
108
109                 return frames.length > 0;
110         }
111
112         public int getPriority () throws DebugException {
113                 return 0;
114         }
115
116         public IStackFrame getTopStackFrame () throws DebugException {
117                 if (frames == null || frames.length == 0) {
118                         return null;
119                 }
120                 return (IStackFrame) frames[0];
121         }
122
123         public IBreakpoint[] getBreakpoints() {
124                 return null;
125         }
126
127         public String getModelIdentifier() {
128                 return this.getDebugTarget().getModelIdentifier();
129         }
130
131         public IDebugTarget getDebugTarget() {
132                 return target;
133         }
134
135         public void setDebugTarget(PHPDebugTarget target) {
136                 this.target = target;
137         }
138
139         public ILaunch getLaunch() {
140                 return this.getDebugTarget().getLaunch();
141         }
142
143         public synchronized boolean canResume() {
144                 return isSuspended();
145         }
146
147         public synchronized boolean canSuspend() {
148                 return !isSuspended();
149         }
150
151         public synchronized boolean isSuspended() {
152                 return state.isSuspended;
153         }
154
155         /**
156          *
157          * Is called from PHPstackframe whenever a stepInto, stepOver or stepReturn is
158          * to be performed
159          *
160          * @param de
161          */
162         protected void prepareForResume (int de) {
163                 DebugEvent ev;
164
165                 state.setSuspended (false);                                 // We will leave the suspended state
166                 this.frames = null;                                         // Reset the stackframes
167         ev          = new DebugEvent (this, DebugEvent.RESUME, de); // Create an event resume by stepping
168
169                 DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev });  // Fire the event
170         }
171
172         /**
173          *
174          */
175         public synchronized void resume () throws DebugException {
176                 if (!isSuspended ()) {                                                                          // Is the thread in suspended state?
177                         return;                                                                                                 // No, leave here
178                 }
179
180                 this.prepareForResume (DebugEvent.STEP_OVER);               // Use a STEP_OVER here because a 0 leads to a collapsing variable tree in UI
181
182                 ((PHPDebugTarget) this.getDebugTarget ()).getPHPDBGProxy ().resume ();
183         }
184
185         /*
186          * public void doSuspend(SuspensionPoint suspensionPoint) { //
187          * this.getPHPDebuggerProxy().readFrames(this);
188          * this.createName(suspensionPoint) ; this.suspend() ; }
189          */
190
191         public synchronized void suspend () throws DebugException {
192                 DebugEvent ev;
193
194                 if (isSuspended ()) {                                                                           // Is the thread in suspend state?
195                         return;                                                                                                 // Yes, leave here
196                 }
197
198                 state.setSuspended (true);                                  // Set thread to suspended state
199                 state.setStepping (false);                                  // Reset thread from stepping state
200
201                 getDebugTarget ().suspend ();                                                           //
202
203                 ev = new DebugEvent (this, DebugEvent.SUSPEND, DebugEvent.BREAKPOINT);
204
205                 DebugPlugin.getDefault ().fireDebugEventSet (new DebugEvent[] { ev });
206         }
207
208         /**
209          *
210          */
211         public boolean canStepInto () {
212                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
213                        isStepping () &&                                     // and ???
214                            this.hasStackFrames ();                              // and does this thread have stack frames?
215         }
216
217         /**
218          *
219          */
220         public boolean canStepOver () {
221                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
222                        isStepping () &&                                     // and ???
223                            this.hasStackFrames ();                              // and does this thread have stack frames?
224         }
225
226         /**
227          *
228          */
229         public boolean canStepReturn () {
230                 return isSuspended () &&                                    // Is the thread in suspended mode (stopped)
231                        isStepping () &&                                     // and ???
232                            this.hasStackFrames ();                              // and does this thread have stack frames?
233         }
234
235         /**
236          *
237          */
238         public boolean isStepping () {
239                 return state.isStepping ();
240         }
241
242         /**
243          *
244          */
245         public void stepInto () throws DebugException {
246                 try {
247                         state.setStepping (true);                               // Store the info about what we do
248                 }
249                 catch (IllegalStateException x) {
250                         throw new DebugException (PHPeclipsePlugin.error (x));
251                 }
252
253                 this.frames = null;
254
255                 frames[0].stepInto ();
256         }
257
258         /**
259          *
260          */
261         public void stepOver () throws DebugException {
262                 state.setStepping (true);
263
264                 this.frames = null;
265
266                 frames[0].stepOver ();
267         }
268
269         /**
270          *
271          */
272         public void stepReturn () throws DebugException {
273         }
274
275         /**
276          *
277          */
278         public boolean canTerminate () {
279                 return !isTerminated ();
280         }
281
282         /**
283          *
284          */
285         public boolean isTerminated () {
286                 return state.isTerminated ();
287         }
288
289         /**
290          *
291          */
292         public synchronized void terminate () throws DebugException {
293                 if (isTerminated ()) {
294                         return;
295                 }
296
297                 state.setTerminated (true);
298                 this.frames = null;
299                 getDebugTarget ().terminate ();
300         }
301
302         /**
303          *
304          * @param arg0
305          * @return
306          */
307         public Object getAdapter (Class arg0) {
308                 if (IWorkbenchAdapter.class.equals (arg0)) {
309                         return new IWorkbenchAdapter() {
310                                 public Object[] getChildren(Object o) {
311                                         Object[] children = null;
312
313                                         try {
314                                                 IStackFrame[] frames = getStackFrames();
315
316                                                 if (null != frames) {
317                                                         children = new Object[frames.length];
318                                                         for (int i = 0; i < frames.length; ++i) {
319                                                                 children[i] = frames[i];
320                                                         }
321                                                 }
322                                         } catch (DebugException x) {
323                                                 PHPeclipsePlugin.log ("Unable to get stack frames.", x);
324                                         }
325
326                                         return children;
327                                 }
328
329                                 public ImageDescriptor getImageDescriptor(Object object) {
330                                         return null;
331                                 }
332
333                                 public String getLabel(Object o) {
334                                         throw new UnsupportedOperationException();
335                                 }
336
337                                 public Object getParent(Object o) {
338                                         return getDebugTarget();
339                                 }
340                         };
341                 }
342
343                 return null;
344         }
345
346         /**
347          *
348          */
349         public void setStackFrames(PHPStackFrame[] frames) {
350                 this.frames = frames;
351         }
352
353         /**
354          *
355          */
356         public String getName () {
357                 String name;
358
359                 name = this.name;
360
361                 if (isSuspended ()) {
362                         name = name + " (suspended)";
363                 }
364
365                 return name;
366         }
367
368         public void setName (String name) {
369                 this.name = name;
370         }
371
372         /*
373          * protected void createName(SuspensionPoint suspensionPoint) { this.name =
374          * "PHP Thread - " + this.getId() ; if (suspensionPoint != null) { this.name += " (" +
375          * suspensionPoint + ")" ; } }
376          */
377
378         public int getId() {
379                 return id;
380         }
381
382         public void setId(int id) {
383                 this.id = id;
384         }
385
386 }