d336d7efc08eb82548765ff2f84048d8257c7b84
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.core / src / net / sourceforge / phpdt / internal / debug / core / PHPDBGProxy.java
1 /***********************************************************************************************************************************
2  * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
3  * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
4  * http://www.eclipse.org/legal/cpl-v10.html
5  * 
6  * Contributors: IBM Corporation - Initial implementation Vicente Fernando - www.alfersoft.com.ar Christian Perkonig - remote debug
7  **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.debug.core;
9
10 import java.io.BufferedReader;
11 import java.io.IOException;
12 import java.io.InputStreamReader;
13 import java.io.OutputStream;
14 import java.net.ServerSocket;
15 import java.net.Socket;
16 import java.net.SocketTimeoutException;
17
18 import net.sourceforge.phpdt.internal.debug.core.breakpoints.PHPLineBreakpoint;
19 import net.sourceforge.phpdt.internal.debug.core.logview.LogView;
20 import net.sourceforge.phpdt.internal.debug.core.model.IPHPDebugTarget;
21 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
22 import net.sourceforge.phpdt.internal.debug.core.model.PHPThread;
23 import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
24
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.core.runtime.Path;
28 import org.eclipse.debug.core.DebugException;
29 import org.eclipse.debug.core.DebugPlugin;
30 import org.eclipse.debug.core.model.IBreakpoint;
31 import org.eclipse.ui.IViewPart;
32 import org.eclipse.ui.IWorkbenchPage;
33
34 public class PHPDBGProxy {
35
36   private ServerSocket server = null;
37
38   private Socket socket;
39
40   private BufferedReader reader = null;
41
42   private PHPDBGInterface DBGInt = null;
43
44   private IPHPDebugTarget debugTarget = null;
45
46   private PHPLoop phpLoop;
47
48   private PHPThread PHPMainThread;
49
50   private PHPDBGProxy thisProxy = null;
51
52   private int port;
53
54   private boolean remote;
55
56   private IPath remoteSourcePath;
57
58   public PHPDBGProxy() {
59     thisProxy = this;
60   }
61
62   public PHPDBGProxy(boolean remote, String remoteSourcePath) {
63     thisProxy = this;
64     this.remote = remote;
65     this.remoteSourcePath = new Path(remoteSourcePath);
66   }
67
68   public void start() {
69     createServerSocket();
70     this.startPHPLoop();
71   }
72
73   public void stop() {
74     phpLoop.setShouldStop();
75     if (DBGInt != null)
76       DBGInt.setShouldStop();
77     if (!remote) {
78       try {
79         getDebugTarget().getProcess().terminate();
80       } catch (DebugException e) {
81         e.printStackTrace();
82       }
83     }
84     phpLoop.notifyWait();
85   }
86
87   protected ServerSocket getServerSocket() throws IOException {
88     if (server == null) {
89       createServerSocket();
90     }
91     return server;
92   }
93
94   protected void createServerSocket() {
95     //          port = SocketUtil.findUnusedLocalPort("localhost", 10001, 10101);
96     port = 10001;
97     if (port == -1) {
98       PHPDebugCorePlugin.log(5, "Cannot find free port!!!!");
99       return;
100     }
101     try {
102       if (server == null) {
103         server = new ServerSocket(port);
104         //System.out.println("ServerSocket on port: " + port);
105       }
106     } catch (IOException e) {
107       // IO Error
108       PHPDebugCorePlugin.log(e);
109       stop();
110     }
111   }
112
113   public Socket getSocket() throws IOException {
114     return socket;
115   }
116
117   protected void setDBGInterface(PHPDBGInterface DBGInt) {
118     this.DBGInt = DBGInt;
119   }
120
121   public BufferedReader getReader() throws IOException {
122     if (reader == null) {
123       reader = new BufferedReader(new InputStreamReader(this.getSocket().getInputStream(), "ISO8859_1"));
124     }
125     return reader;
126   }
127
128   public BufferedReader getReader(Socket socket) throws IOException {
129     if (socket != null)
130       return new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO8859_1"));
131     else
132       return null;
133   }
134
135   public OutputStream getOutputStream() throws IOException {
136     return this.getSocket().getOutputStream();
137   }
138
139   protected void setBreakPoints() throws IOException, CoreException {
140     IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
141     for (int i = 0; i < breakpoints.length; i++) {
142       addBreakpoint(breakpoints[i]);
143     }
144   }
145
146   public void addBreakpoint(IBreakpoint breakpoint) {
147     if (DBGInt == null)
148       return;
149     int bpNo = 0;
150     try {
151       PHPLineBreakpoint phpLBP;
152       if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
153         IPath filename;
154         phpLBP = (PHPLineBreakpoint) breakpoint;
155         //                              bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber());
156         if (remote)
157           filename = remoteSourcePath.append(phpLBP.getMarker().getResource().getProjectRelativePath());
158         else
159           filename = phpLBP.getMarker().getResource().getLocation();
160         bpNo = DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber());
161         phpLBP.setDBGBpNo(bpNo);
162       }
163     } catch (IOException e) {
164       PHPDebugCorePlugin.log(e);
165       stop();
166     } catch (CoreException e) {
167       PHPDebugCorePlugin.log(e);
168       stop();
169     }
170   }
171
172   public void removeBreakpoint(IBreakpoint breakpoint) {
173     if (DBGInt == null)
174       return;
175     try {
176       PHPLineBreakpoint phpLBP;
177       if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
178         phpLBP = (PHPLineBreakpoint) breakpoint;
179         IPath filename;
180         if (remote)
181           filename = remoteSourcePath.append(phpLBP.getMarker().getResource().getProjectRelativePath());
182         else
183           filename = phpLBP.getMarker().getResource().getLocation();
184         //                                      bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber());
185         DBGInt.removeBreakpoint(filename.toOSString(), phpLBP.getLineNumber(), phpLBP.getDBGBpNo());
186       }
187     } catch (IOException e) {
188       PHPDebugCorePlugin.log(e);
189       stop();
190     } catch (CoreException e) {
191       PHPDebugCorePlugin.log(e);
192       stop();
193     }
194   }
195
196   public void phpLoopNotify() {
197     phpLoop.notifyWait();
198   }
199
200   public void startPHPLoop() {
201     phpLoop = new PHPLoop();
202     phpLoop.start();
203   }
204
205   public void resume() {
206     try {
207       DBGInt.continueExecution();
208       phpLoop.notifyWait();
209     } catch (IOException e) {
210       PHPDebugCorePlugin.log(e);
211       stop();
212     }
213   }
214
215   public void pause() {
216     try {
217       DBGInt.pauseExecution();
218     } catch (IOException e) {
219       PHPDebugCorePlugin.log(e);
220       stop();
221     }
222   }
223
224   protected IPHPDebugTarget getDebugTarget() {
225     return debugTarget;
226   }
227
228   public void setDebugTarget(IPHPDebugTarget debugTarget) {
229     this.debugTarget = debugTarget;
230     debugTarget.setPHPDBGProxy(this);
231   }
232
233   public PHPVariable[] readVariables(PHPStackFrame frame) {
234     try {
235       return DBGInt.getVariables(frame);
236     } catch (IOException ioex) {
237       ioex.printStackTrace();
238       throw new RuntimeException(ioex.getMessage());
239     } catch (DebugException ex) {
240       ex.printStackTrace();
241       throw new RuntimeException(ex.getMessage());
242     }
243   }
244
245   public PHPVariable[] eval(PHPStackFrame frame, String evalString) {
246     try {
247       return DBGInt.evalBlock(frame, evalString);
248       //                        return DBGInt.getVariables(frame);
249     } catch (IOException ioex) {
250       ioex.printStackTrace();
251       throw new RuntimeException(ioex.getMessage());
252     } catch (DebugException ex) {
253       ex.printStackTrace();
254       throw new RuntimeException(ex.getMessage());
255     }
256   }
257
258   public void readStepOverEnd(PHPStackFrame stackFrame) {
259     try {
260       DBGInt.stepOver();
261       phpLoop.notifyWait();
262     } catch (Exception e) {
263       PHPDebugCorePlugin.log(e);
264     }
265   }
266
267   public void readStepReturnEnd(PHPStackFrame stackFrame) {
268     try {
269       DBGInt.stepOut();
270       phpLoop.notifyWait();
271     } catch (Exception e) {
272       PHPDebugCorePlugin.log(e);
273     }
274   }
275
276   public void readStepIntoEnd(PHPStackFrame stackFrame) {
277     try {
278       DBGInt.stepInto();
279       phpLoop.notifyWait();
280     } catch (Exception e) {
281       PHPDebugCorePlugin.log(e);
282     }
283   }
284
285   /*
286    * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new
287    * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { //
288    * PHPDebugCorePlugin.log(e); // return null; //}
289    *  }
290    */
291
292   public void closeSocket() throws IOException {
293     if (socket != null) {
294       socket.close();
295     }
296   }
297
298   public void closeServerSocket() throws IOException {
299     if (server != null) {
300       server.close();
301     }
302   }
303
304   public int getPort() {
305     return port;
306   }
307
308   class PHPLoop extends Thread {
309     private boolean shouldStop;
310
311     public PHPLoop() {
312       shouldStop = false;
313       this.setName("PHPDebuggerLoop");
314     }
315
316     public synchronized void setShouldStop() {
317       shouldStop = true;
318     }
319
320     public synchronized void notifyWait() {
321       notify();
322     }
323
324     public void run() {
325       try {
326         char[] buf = new char[16];
327         int i, pos, timeout;
328         long interval = 200; // 200ms
329         String line;
330         PHPStackFrame[] StackList;
331         boolean endFile = false;
332         boolean newconnect = false;
333         Socket newSocket = null;
334         PHPDBGInterface newDBGInt;
335         int sid = -1;
336
337         //                              synchronized (this) {
338         //                                      wait();
339         //                              }
340
341         PHPMainThread = new PHPThread(getDebugTarget(), getPort());
342         PHPMainThread.setName("Thread [main]");
343         timeout = 0;
344
345         //                              while ((getDebugTarget() == null) && (timeout < 100)) {
346         //                                      sleep(100);
347         //                                      timeout++;
348         //                              }
349         // Be sure debug target is set
350         //                              PHPMainThread.setDebugTarget(getDebugTarget());
351         getDebugTarget().addThread(PHPMainThread);
352
353         //System.out.println("Waiting for breakpoints.");
354         while (!shouldStop) {
355           newconnect = true;
356           try {
357             newSocket = server.accept();
358             //System.out.println("Accepted! : " + socket.toString());
359           } catch (SocketTimeoutException e) {
360             // no one wants to connect
361             newconnect = false;
362           } catch (IOException e) {
363             PHPDebugCorePlugin.log(e);
364             return;
365           }
366
367           if (newconnect) {
368             if (DBGInt == null)
369               server.setSoTimeout(1);
370             newDBGInt = new PHPDBGInterface(getReader(newSocket), newSocket.getOutputStream(), thisProxy);
371             newDBGInt.waitResponse(1000);
372             newDBGInt.flushAllPackets();
373             // Check version and session ID
374             if ((DBGInt == null) || (DBGInt.getSID() == newDBGInt.getSID())) {
375               DBGInt = newDBGInt;
376               try {
377                 closeSocket();
378               } catch (IOException e) {
379                 PHPDebugCorePlugin.log(e);
380                 shouldStop = true;
381               }
382               socket = newSocket;
383               setBreakPoints();
384               DBGInt.continueExecution();
385             } else {
386               newDBGInt.continueExecution();
387               newSocket.close();
388             }
389           }
390
391           if (DBGInt.waitResponse(interval)) {
392
393             DBGInt.flushAllPackets();
394
395             if (DBGInt.BPUnderHit != 0) {
396               StackList = DBGInt.getStackList();
397               if (StackList.length > 0) {
398                 for (i = 0; i < StackList.length; i++) {
399                   StackList[i].setThread(PHPMainThread);
400                   if (DBGInt.getModByNo(StackList[i].getModNo()).equals("")) {
401                     DBGInt.getSourceTree();
402                   }
403                   StackList[i].setFile(DBGInt.getModByNo(StackList[i].getModNo()));
404                 }
405                 PHPMainThread.setStackFrames(StackList);
406               }
407               // Fire debug event
408               PHPMainThread.suspend();
409
410               synchronized (this) {
411                 wait();
412               }
413             }
414           }
415           if (remote) {
416             if (PHPMainThread.isTerminated()) {
417               shouldStop = true;
418               break;
419             }
420           } else {
421             if (PHPMainThread.isTerminated() || getDebugTarget().getProcess().isTerminated()) {
422               shouldStop = true;
423               break;
424             }
425           }
426         }
427       } catch (Exception ex) {
428         PHPDebugCorePlugin.log(ex);
429         System.out.println(ex);
430       } finally {
431         try {
432           getDebugTarget().terminate();
433           closeSocket();
434           closeServerSocket();
435         } catch (IOException e) {
436           PHPDebugCorePlugin.log(e);
437           return;
438         }
439         //System.out.println("Socket loop finished.");
440       }
441     }
442   }
443 }