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;
16 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
18 import org.eclipse.core.resources.IMarkerDelta;
19 import org.eclipse.debug.core.DebugEvent;
20 import org.eclipse.debug.core.DebugException;
21 import org.eclipse.debug.core.DebugPlugin;
22 import org.eclipse.debug.core.IBreakpointManager;
23 import org.eclipse.debug.core.IDebugEventSetListener;
24 import org.eclipse.debug.core.ILaunch;
25 import org.eclipse.debug.core.ILaunchListener;
26 import org.eclipse.debug.core.model.IBreakpoint;
27 import org.eclipse.debug.core.model.IDebugTarget;
28 import org.eclipse.debug.core.model.IMemoryBlock;
29 import org.eclipse.debug.core.model.IProcess;
30 import org.eclipse.debug.core.model.IThread;
31 import org.eclipse.jface.resource.ImageDescriptor;
32 import org.eclipse.ui.model.IWorkbenchAdapter;
35 * Debug target for PHP debug model.
37 public class PHPDebugTarget implements IPHPDebugTarget, ILaunchListener,
38 IDebugEventSetListener {
40 private IProcess process;
42 private ILaunch launch;
44 private PHPThread[] threads = new PHPThread[0];
46 private PHPDBGProxy phpDBGProxy;
49 private boolean isTerminated = false;
51 private boolean isSuspended = false;
53 boolean isTerminated() {
57 boolean isSuspended() {
61 void setTerminated(boolean terminated) {
62 this.isTerminated = terminated;
65 void setSuspended(boolean suspended) {
67 throw new IllegalStateException();
68 this.isSuspended = suspended;
72 private final State state = new State();
74 public PHPDebugTarget(ILaunch launch, IProcess process) {
75 if (null == launch && null == process)
76 throw new IllegalArgumentException();
78 this.process = process;
79 // TODO XXX remove breakpoint listener at termination to avoid live leak
80 IBreakpointManager manager = DebugPlugin.getDefault()
81 .getBreakpointManager();
82 manager.addBreakpointListener(this);
83 DebugPlugin.getDefault().addDebugEventListener(this);
87 protected synchronized void initialize() {
88 DebugEvent ev = new DebugEvent(this, DebugEvent.CREATE);
89 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
92 public void addThread(PHPThread phpThread) {
94 PHPThread[] updatedThreads = new PHPThread[threads.length + 1];
96 for (i = 0; i < threads.length; i++) {
97 updatedThreads[i] = threads[i];
99 updatedThreads[i] = phpThread;
100 threads = updatedThreads;
103 fireThreadCreateEvent(phpThread);
106 private void fireChangeEvent() {
107 DebugEvent ev = new DebugEvent(this, DebugEvent.CHANGE);
108 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
111 private void fireThreadCreateEvent(PHPThread phpThread) {
112 DebugEvent ev = new DebugEvent(phpThread, DebugEvent.CREATE);
113 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
116 protected PHPThread getThreadById(int id) {
117 for (int i = 0; i < threads.length; i++) {
118 if (threads[i].getId() == id) {
125 public IThread[] getThreads() {
129 public boolean hasThreads() throws DebugException {
130 return threads.length > 0;
133 public String getName() throws DebugException {
134 return "PHP Debugger at localhost:" + getPHPDBGProxy().getPort();
137 public boolean supportsBreakpoint(IBreakpoint arg0) {
138 if (arg0.getModelIdentifier().equals(PHPDebugCorePlugin.PLUGIN_ID)) {
144 public String getModelIdentifier() {
145 return PHPDebugCorePlugin.PLUGIN_ID;
148 public IDebugTarget getDebugTarget() {
152 public ILaunch getLaunch() {
156 public synchronized boolean canTerminate() {
157 return !isTerminated();
160 public synchronized boolean isTerminated() {
161 return state.isTerminated();
164 public synchronized void terminate() {
165 // This method is synchronized to control a race condition between the
166 // UI thread that terminates the debugging session, and the slave
167 // thread that executes PHPLoop.run
169 // Avoid terminating twice...
171 state.setTerminated(true);
173 this.threads = new PHPThread[0];
175 IBreakpointManager manager = DebugPlugin.getDefault()
176 .getBreakpointManager();
177 manager.removeBreakpointListener(this);
178 DebugPlugin.getDefault().removeDebugEventListener(this);
181 public synchronized boolean canResume() {
184 return isSuspended();
187 public synchronized boolean canSuspend() {
190 return !isSuspended();
193 public synchronized boolean isSuspended() {
194 return state.isSuspended();
197 public synchronized void resume() throws DebugException {
200 state.setSuspended(false);
201 this.getPHPDBGProxy().resume();
202 IThread[] threads = getThreads();
203 for (int i = 0; i < threads.length; ++i)
207 public synchronized void suspend() throws DebugException {
210 this.getPHPDBGProxy().pause();
211 state.setSuspended(true);
212 IThread[] threads = getThreads();
213 for (int i = 0; i < threads.length; ++i)
214 threads[i].suspend();
217 public void breakpointAdded(IBreakpoint breakpoint) {
218 this.getPHPDBGProxy().addBreakpoint(breakpoint);
221 public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta arg1) {
222 this.getPHPDBGProxy().removeBreakpoint(breakpoint);
225 public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta arg1) {
226 // is called e.g. after a line has been inserted before a breakpoint
227 // but then the debugger is out of sync with the file anyway, so
229 // should be stopped here.
232 public boolean canDisconnect() {
236 public void disconnect() throws DebugException {
239 public boolean isDisconnected() {
243 public boolean supportsStorageRetrieval() {
247 public IMemoryBlock getMemoryBlock(long arg0, long arg1)
248 throws DebugException {
252 public Object getAdapter(Class arg0) {
253 if (IWorkbenchAdapter.class.equals(arg0)) {
254 return new IWorkbenchAdapter() {
255 public Object[] getChildren(Object o) {
256 Object[] children = null;
257 IThread[] threads = getThreads();
258 if (null != threads) {
259 children = new Object[threads.length];
260 for (int i = 0; i < threads.length; ++i)
261 children[i] = threads[i];
266 public ImageDescriptor getImageDescriptor(Object object) {
270 public String getLabel(Object o) {
271 String label = "(Unable to look up name... check error log)";
274 } catch (DebugException x) {
275 PHPeclipsePlugin.log(label, x);
280 public Object getParent(Object o) {
281 return PHPDebugTarget.this.getLaunch();
288 public IProcess getProcess() {
292 public void setProcess(IProcess process) {
293 this.process = process;
296 public PHPDBGProxy getPHPDBGProxy() {
300 public void setPHPDBGProxy(PHPDBGProxy phpDBGProxy) {
301 this.phpDBGProxy = phpDBGProxy;
305 * @see ILaunchListener#launchRemoved(ILaunch)
307 public void launchRemoved(ILaunch launch) {
308 if (!isTerminated()) {
311 if (launch.equals(getLaunch())) {
312 // This target has been deregistered, but it hasn't successfully
314 // Update internal state to reflect that it is disconnected
320 * @see ILaunchListener#launchAdded(ILaunch)
322 public void launchAdded(ILaunch launch) {
326 * @see ILaunchListener#launchChanged(ILaunch)
328 public void launchChanged(ILaunch launch) {
332 * When a debug target or process terminates, terminate DBG Proxy.
334 * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
336 public void handleDebugEvents(DebugEvent[] events) {
337 for (int i = 0; i < events.length; i++) {
338 DebugEvent event = events[i];
339 if (event.getKind() == DebugEvent.TERMINATE) {
340 Object source = event.getSource();
341 if (source instanceof PHPDebugTarget
342 || source instanceof IDebugTarget) {
343 getPHPDBGProxy().stop();
344 } else if (source instanceof IProcess) {
345 if (getDebugTarget().getProcess() == (IProcess) source) {
346 getPHPDBGProxy().stop();
349 } else if (event.getKind() == DebugEvent.SUSPEND) {
350 getPHPDBGProxy().pause();