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.IStackFrame;
31 import org.eclipse.debug.core.model.IThread;
32 import org.eclipse.jface.resource.ImageDescriptor;
33 import org.eclipse.ui.model.IWorkbenchAdapter;
36 * Debug target for PHP debug model.
38 public class PHPDebugTarget implements IPHPDebugTarget, ILaunchListener, IDebugEventSetListener {
40 private IProcess process;
41 private boolean isTerminated;
42 private boolean isSuspended;
43 private ILaunch launch;
44 private PHPThread[] threads;
45 private PHPDBGProxy phpDBGProxy;
47 public PHPDebugTarget(ILaunch launch, IProcess process) {
48 this.isSuspended = false;
50 this.process = process;
51 this.threads = new PHPThread[0];
52 // TODO XXX remove breakpoint listener at termination to avoid live leak
53 IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
54 manager.addBreakpointListener(this);
55 DebugPlugin.getDefault().addDebugEventListener(this);
59 protected synchronized void initialize() {
60 DebugEvent ev = new DebugEvent(this, DebugEvent.CREATE);
61 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
64 public void addThread(PHPThread phpThread) {
66 PHPThread[] updatedThreads = new PHPThread[threads.length + 1];
68 for(i=0; i < threads.length; i++) {
69 updatedThreads[i] = threads[i];
71 updatedThreads[i] = phpThread;
72 threads = updatedThreads;
75 fireThreadCreateEvent(phpThread);
78 private void fireChangeEvent() {
79 DebugEvent ev = new DebugEvent(this, DebugEvent.CHANGE);
80 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
83 private void fireThreadCreateEvent(PHPThread phpThread) {
84 DebugEvent ev = new DebugEvent(phpThread, DebugEvent.CREATE);
85 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { ev });
88 protected PHPThread getThreadById(int id) {
89 for (int i = 0; i < threads.length; i++) {
90 if (threads[i].getId() == id) {
97 public IThread[] getThreads() {
101 public boolean hasThreads() throws DebugException {
102 return threads.length > 0;
105 public String getName() throws DebugException {
106 return "PHP Debugger at localhost:" + getPHPDBGProxy().getPort();
109 public boolean supportsBreakpoint(IBreakpoint arg0) {
110 if(arg0.getModelIdentifier().equals(PHPDebugCorePlugin.PLUGIN_ID)) {
116 public String getModelIdentifier() {
117 return PHPDebugCorePlugin.PLUGIN_ID;
120 public IDebugTarget getDebugTarget() {
124 public ILaunch getLaunch() {
128 public boolean canTerminate() {
129 return !isTerminated;
132 public boolean isTerminated() {
136 public synchronized void terminate() {
137 // This method is synchronized to control a race condition between the
138 // UI thread that terminates the debugging session, and the slave
139 // thread that executes PHPLoop.run
141 // Avoid terminating twice...
144 this.threads = new PHPThread[0];
147 IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
148 manager.removeBreakpointListener(this);
149 DebugPlugin.getDefault().removeDebugEventListener(this);
152 public boolean canResume() {
153 if(isTerminated) return false;
157 public boolean canSuspend() {
158 if(isTerminated) return false;
162 public boolean isSuspended() {
166 public void resume() throws DebugException {
167 this.getPHPDBGProxy().resume();
171 public void suspend() throws DebugException {
172 this.getPHPDBGProxy().pause();
176 public void breakpointAdded(IBreakpoint breakpoint) {
177 this.getPHPDBGProxy().addBreakpoint(breakpoint) ;
180 public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta arg1) {
181 this.getPHPDBGProxy().removeBreakpoint(breakpoint) ;
184 public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta arg1) {
185 // is called e.g. after a line has been inserted before a breakpoint
186 // but then the debugger is out of sync with the file anyway, so debugging
187 // should be stopped here.
190 public boolean canDisconnect() {
194 public void disconnect() throws DebugException {
197 public boolean isDisconnected() {
201 public boolean supportsStorageRetrieval() {
205 public IMemoryBlock getMemoryBlock(long arg0, long arg1) throws DebugException {
209 public Object getAdapter(Class arg0) {
210 if (IWorkbenchAdapter.class.equals(arg0)) {
211 return new IWorkbenchAdapter() {
212 public Object[] getChildren(Object o) {
213 Object[] children = null;
214 IThread[] threads = getThreads();
215 if (null != threads) {
216 children = new Object[threads.length];
217 for (int i = 0; i < threads.length; ++i)
218 children[i] = threads[i];
222 public ImageDescriptor getImageDescriptor(Object object) {
225 public String getLabel(Object o) {
226 String label = "(Unable to look up name... check error log)";
229 } catch (DebugException x) {
230 PHPeclipsePlugin.log(label, x);
234 public Object getParent(Object o) {
235 return PHPDebugTarget.this.getLaunch();
242 public IProcess getProcess() {
246 public void setProcess(IProcess process) {
247 this.process = process;
250 public PHPDBGProxy getPHPDBGProxy() {
254 public void setPHPDBGProxy(PHPDBGProxy phpDBGProxy) {
255 this.phpDBGProxy = phpDBGProxy;
259 * @see ILaunchListener#launchRemoved(ILaunch)
261 public void launchRemoved(ILaunch launch) {
262 if (!isTerminated()) {
265 if (launch.equals(getLaunch())) {
266 // This target has been deregistered, but it hasn't successfully terminated.
267 // Update internal state to reflect that it is disconnected
273 * @see ILaunchListener#launchAdded(ILaunch)
275 public void launchAdded(ILaunch launch) {
279 * @see ILaunchListener#launchChanged(ILaunch)
281 public void launchChanged(ILaunch launch) {
285 * When a debug target or process terminates, terminate DBG Proxy.
287 * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
289 public void handleDebugEvents(DebugEvent[] events) {
290 for (int i = 0; i < events.length; i++) {
291 DebugEvent event = events[i];
292 if (event.getKind() == DebugEvent.TERMINATE) {
293 Object source = event.getSource();
294 if (source instanceof PHPDebugTarget || source instanceof IDebugTarget) {
295 getPHPDBGProxy().stop();
296 } else if(source instanceof IProcess) {
297 if(getDebugTarget().getProcess() == (IProcess)source) {
298 getPHPDBGProxy().stop();
301 } else if (event.getKind() == DebugEvent.SUSPEND) {
302 getPHPDBGProxy().pause();