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