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
 
   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;
 
  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;
 
  19 import net.sourceforge.phpdt.internal.debug.core.breakpoints.PHPLineBreakpoint;
 
  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 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  26 import org.eclipse.core.runtime.CoreException;
 
  27 import org.eclipse.core.runtime.IPath;
 
  28 import org.eclipse.core.runtime.Path;
 
  29 import org.eclipse.debug.core.DebugException;
 
  30 import org.eclipse.debug.core.DebugPlugin;
 
  31 import org.eclipse.debug.core.model.IBreakpoint;
 
  33 public class PHPDBGProxy {
 
  35   private ServerSocket server = null;
 
  37   private Socket socket;
 
  39   private BufferedReader reader = null;
 
  41   private PHPDBGInterface DBGInt = null;
 
  43   private IPHPDebugTarget debugTarget = null;
 
  45   private PHPLoop phpLoop;
 
  47   private PHPThread PHPMainThread;
 
  49   private PHPDBGProxy thisProxy = null;
 
  53   private boolean remote;
 
  55   private boolean pathtranslation;
 
  59   private IPath remoteSourcePath;
 
  61   public PHPDBGProxy() {
 
  65   public PHPDBGProxy(boolean remote, String remoteSourcePath,boolean pathTranslate,Map paths) {
 
  68     this.remoteSourcePath = new Path(remoteSourcePath);
 
  70     this.pathtranslation=pathTranslate;
 
  79     phpLoop.setShouldStop();
 
  81       DBGInt.setShouldStop();
 
  84         getDebugTarget().getProcess().terminate();
 
  85       } catch (DebugException e) {
 
  92   protected ServerSocket getServerSocket() throws IOException {
 
  99   protected void createServerSocket() {
 
 100     port = SocketUtil.findUnusedLocalPort("localhost", 10001, 10101);
 
 103       PHPDebugCorePlugin.log(5, "Cannot find free port!!!!");
 
 107       if (server == null) {
 
 108         server = new ServerSocket(port);
 
 109         //System.out.println("ServerSocket on port: " + port);
 
 111     } catch (IOException e) {
 
 113       PHPDebugCorePlugin.log(e);
 
 118   public Socket getSocket() throws IOException {
 
 122   protected void setDBGInterface(PHPDBGInterface DBGInt) {
 
 123     this.DBGInt = DBGInt;
 
 126   public BufferedReader getReader() throws IOException {
 
 127     if (reader == null) {
 
 128       reader = new BufferedReader(new InputStreamReader(this.getSocket().getInputStream(), "ISO8859_1"));
 
 133   public BufferedReader getReader(Socket socket) throws IOException {
 
 135       return new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO8859_1"));
 
 140   public OutputStream getOutputStream() throws IOException {
 
 141     return this.getSocket().getOutputStream();
 
 144   protected void setBreakPoints() throws IOException, CoreException {
 
 145                 IBreakpoint[] breakpoints = DebugPlugin.getDefault()
 
 146                                 .getBreakpointManager().getBreakpoints();
 
 147                 for (int i = 0; i < breakpoints.length; i++) {
 
 148                         if (breakpoints[i].isEnabled()) {
 
 149                                 addBreakpoint(breakpoints[i]);
 
 154   private String MapPath(PHPLineBreakpoint phpLBP) {
 
 157                         filename = phpLBP.getMarker().getResource()
 
 158                                         .getProjectRelativePath();
 
 159                         filename = remoteSourcePath.append(filename);
 
 161                         filename = phpLBP.getMarker().getResource().getLocation();
 
 162                 String path = filename.toOSString();
 
 163                 if (pathmap != null && remote) {
 
 164                         java.util.Iterator i = pathmap.keySet().iterator();
 
 165                         while (i.hasNext()) {
 
 166                                 String k = (String) i.next();
 
 167                                 if (path.startsWith(k)) {
 
 168                                         path = pathmap.get(k) + path.substring(k.length());
 
 173                 if (pathtranslation && remote) {
 
 174                         if (remoteSourcePath.toString().substring(0, 1).equals("/"))
 
 175                                 path = path.replace('\\', '/');
 
 177                                 path = path.replace('/', '\\');
 
 182   public void addBreakpoint(IBreakpoint breakpoint) {
 
 187       PHPLineBreakpoint phpLBP;
 
 188       if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
 
 189         phpLBP = (PHPLineBreakpoint) breakpoint;
 
 190         //                              bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber());
 
 192         bpNo = DBGInt.addBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber());
 
 193         phpLBP.setDBGBpNo(bpNo);
 
 195     } catch (IOException e) {
 
 196       PHPDebugCorePlugin.log(e);
 
 198     } catch (CoreException e) {
 
 199       PHPDebugCorePlugin.log(e);
 
 204   public void removeBreakpoint(IBreakpoint breakpoint) {
 
 208       PHPLineBreakpoint phpLBP;
 
 209       if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
 
 210         phpLBP = (PHPLineBreakpoint) breakpoint;
 
 212         //                                      bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber());
 
 213         DBGInt.removeBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber(), phpLBP.getDBGBpNo());
 
 215     } catch (IOException e) {
 
 216       PHPDebugCorePlugin.log(e);
 
 218     } catch (CoreException e) {
 
 219       PHPDebugCorePlugin.log(e);
 
 224   public void phpLoopNotify() {
 
 225     phpLoop.notifyWait();
 
 228   public void startPHPLoop() {
 
 229     phpLoop = new PHPLoop();
 
 233   public void resume() {
 
 235       DBGInt.continueExecution();
 
 236       phpLoop.notifyWait();
 
 237     } catch (IOException e) {
 
 238       PHPeclipsePlugin.log("Debugging session ended.", e);
 
 243   public void pause() {
 
 246         DBGInt.pauseExecution();
 
 248         // TODO Make sure the Suspend action is grayed out 
 
 249         // when DBGInt is null
 
 251     } catch (IOException e) {
 
 252       PHPDebugCorePlugin.log(e);
 
 257   protected IPHPDebugTarget getDebugTarget() {
 
 261   public void setDebugTarget(IPHPDebugTarget debugTarget) {
 
 262     this.debugTarget = debugTarget;
 
 263     debugTarget.setPHPDBGProxy(this);
 
 266   public PHPVariable[] readVariables(PHPStackFrame frame) {
 
 268       return DBGInt.getVariables(frame);
 
 269     } catch (IOException ioex) {
 
 270       ioex.printStackTrace();
 
 271       throw new RuntimeException(ioex.getMessage());
 
 272     } catch (DebugException ex) {
 
 273       ex.printStackTrace();
 
 274       throw new RuntimeException(ex.getMessage());
 
 278   public PHPVariable[] eval(PHPStackFrame frame, String evalString) {
 
 280       return DBGInt.evalBlock(frame, evalString);
 
 281       //                        return DBGInt.getVariables(frame);
 
 282     } catch (IOException ioex) {
 
 283       ioex.printStackTrace();
 
 284       throw new RuntimeException(ioex.getMessage());
 
 285     } catch (DebugException ex) {
 
 286       ex.printStackTrace();
 
 287       throw new RuntimeException(ex.getMessage());
 
 291   public void readStepOverEnd(PHPStackFrame stackFrame) {
 
 294       phpLoop.notifyWait();
 
 295     } catch (Exception e) {
 
 296       PHPDebugCorePlugin.log(e);
 
 300   public void readStepReturnEnd(PHPStackFrame stackFrame) {
 
 303       phpLoop.notifyWait();
 
 304     } catch (Exception e) {
 
 305       PHPDebugCorePlugin.log(e);
 
 309   public void readStepIntoEnd(PHPStackFrame stackFrame) {
 
 312       phpLoop.notifyWait();
 
 313     } catch (Exception e) {
 
 314       PHPDebugCorePlugin.log(e);
 
 319    * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new
 
 320    * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { //
 
 321    * PHPDebugCorePlugin.log(e); // return null; //}
 
 325   public void closeSocket() throws IOException {
 
 326     if (socket != null) {
 
 331   public void closeServerSocket() throws IOException {
 
 332     if (server != null) {
 
 337   public int getPort() {
 
 341   class PHPLoop extends Thread {
 
 342     private boolean shouldStop;
 
 346       this.setName("PHPDebuggerLoop");
 
 349     public synchronized void setShouldStop() {
 
 352                         // If the loop thread is blocked on the server socket, 
 
 353                         // forcibly unblock it to avoid leaking the thread, 
 
 354                         // the socket and the port
 
 356                 } catch (IOException x) {
 
 357                         // Log this as a warning?
 
 358                         PHPDebugCorePlugin.log(x);
 
 362     public synchronized void notifyWait() {
 
 368         char[] buf = new char[16];
 
 370         long interval = 200; // 200ms
 
 372         PHPStackFrame[] StackList;
 
 373         boolean endFile = false;
 
 374         boolean newconnect = false;
 
 375         Socket newSocket = null;
 
 376         PHPDBGInterface newDBGInt;
 
 379         //                              synchronized (this) {
 
 383         PHPMainThread = new PHPThread(getDebugTarget(), getPort());
 
 384         PHPMainThread.setName("Thread [main]");
 
 387         //                              while ((getDebugTarget() == null) && (timeout < 100)) {
 
 391         // Be sure debug target is set
 
 392         //                              PHPMainThread.setDebugTarget(getDebugTarget());
 
 393         getDebugTarget().addThread(PHPMainThread);
 
 395         //System.out.println("Waiting for breakpoints.");
 
 396         while (!shouldStop) {
 
 399             newSocket = server.accept();
 
 400             //System.out.println("Accepted! : " + socket.toString());
 
 401           } catch (SocketTimeoutException e) {
 
 402             // no one wants to connect
 
 404           } catch (IOException e) {
 
 405             PHPDebugCorePlugin.log(e);
 
 411               server.setSoTimeout(1);
 
 412             newDBGInt = new PHPDBGInterface(getReader(newSocket), newSocket.getOutputStream(), thisProxy);
 
 413             newDBGInt.waitResponse(1000);
 
 414             newDBGInt.flushAllPackets();
 
 415             // Check version and session ID
 
 416             if ((DBGInt == null) || (DBGInt.getSID() == newDBGInt.getSID())) {
 
 420               } catch (IOException e) {
 
 421                 PHPDebugCorePlugin.log(e);
 
 426               DBGInt.continueExecution();
 
 428               newDBGInt.continueExecution();
 
 433           if (DBGInt.waitResponse(interval)) {
 
 435             DBGInt.flushAllPackets();
 
 437             if (DBGInt.BPUnderHit != 0) {
 
 438               StackList = DBGInt.getStackList();
 
 439               if (StackList.length > 0) {
 
 440                 for (i = 0; i < StackList.length; i++) {
 
 441                   StackList[i].setThread(PHPMainThread);
 
 442                   if (DBGInt.getModByNo(StackList[i].getModNo()).equals("")) {
 
 443                     DBGInt.getSourceTree();
 
 445                   StackList[i].setFile(DBGInt.getModByNo(StackList[i].getModNo()));
 
 447                 PHPMainThread.setStackFrames(StackList);
 
 450               PHPMainThread.suspend();
 
 452               synchronized (this) {
 
 458             if (PHPMainThread.isTerminated()) {
 
 463             if (PHPMainThread.isTerminated() || getDebugTarget().getProcess().isTerminated()) {
 
 469       } catch (Exception ex) {
 
 470         PHPDebugCorePlugin.log(ex);
 
 471         System.out.println(ex);
 
 474           getDebugTarget().terminate();
 
 477         } catch (IOException e) {
 
 478           PHPDebugCorePlugin.log(e);
 
 481         //System.out.println("Socket loop finished.");