+++ /dev/null
-/***********************************************************************************************************************************
- * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
- * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors: IBM Corporation - Initial implementation Vicente Fernando - www.alfersoft.com.ar Christian Perkonig - remote debug
- **********************************************************************************************************************************/
-package net.sourceforge.phpdt.internal.debug.core;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.util.Map;
-import java.util.Vector;
-
-import net.sourceforge.phpdt.internal.debug.core.breakpoints.PHPLineBreakpoint;
-import net.sourceforge.phpdt.internal.debug.core.model.PHPDebugTarget;
-import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
-import net.sourceforge.phpdt.internal.debug.core.model.PHPThread;
-import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
-import net.sourceforge.phpeclipse.PHPeclipsePlugin;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.model.IBreakpoint;
-
-public class PHPDBGProxy {
-
- private ServerSocket server = null;
- private BufferedReader reader = null;
- private PHPDBGInterface DBGInt = null; // The DBG interface which is linked with the proxy
- private PHPDebugTarget debugTarget = null;
- private PHPDBGProxy thisProxy = null;
- private PHPLoop phpLoop;
- private PHPThread PHPMainThread;
- private Socket socket;
- private int port;
- private boolean remote;
- private boolean pathtranslation;
- private Map pathmap;
- private IPath remoteSourcePath;
-
- /**
- */
- public PHPDBGProxy () {
- thisProxy = this;
- }
-
- /**
- * @param remote
- * @param remoteSourcePath
- * @param pathTranslate
- * @param paths
- */
- public PHPDBGProxy (boolean remote, String remoteSourcePath, boolean pathTranslate, Map paths) {
- thisProxy = this;
- this.remote = remote;
- this.remoteSourcePath = new Path (remoteSourcePath);
- this.pathmap = paths;
- this.pathtranslation = pathTranslate;
- }
-
- /**
- *
- */
- public void start () {
- createServerSocket (); // Create a server socket for communicatio with DBG
-
- this.startPHPLoop (); //
- }
-
- /**
- *
- */
- public void stop () {
- phpLoop.setShouldStop (); // Notify the thread's 'run loop' to stop
-
- if (DBGInt != null) { // If we have a DBG interface linked with this proxy
- DBGInt.setShouldStop (); // Notify the DBG interface to stop the waiting for response
- }
-
- if (!remote) { // If it's not a remote proxy session
- try {
- getDebugTarget ().getProcess ().terminate (); //
- } catch (DebugException e) {
- e.printStackTrace ();
- }
- }
-
- phpLoop.notifyWait ();
- }
-
- public void setTerminated () {
- try {
- PHPMainThread.terminate ();
- }
- catch (DebugException e) {
- }
- }
-
- /**
- * TODO Is this method called from anywhere?
- *
- * Returns a already created server socket, or
- * creates a server socket if none exists, and
- * returns the newly created one.
- *
- * @return A server socket
- */
- protected ServerSocket getServerSocket () throws IOException {
- if (server == null) { // Do we have already a server socket
- createServerSocket (); // No, then create one
- }
-
- return server; // Return the server socket
- }
-
- /**
- * Find a free unused port between 10001 and 10101 if the current debug session
- * is for remote debugging, and a unused port 7869 if it is used as non remote debugging.
- *
- * For remote debugging the used port is submitted with the URL.
- * E.g. http://localhost/index.php?DBGSESSID=1@localhost:10001
- * For non remote debugging (if PHPeclipse used e.g. php cli directly) no port
- * can be submitted by parameter, and only the default port (7869) can be used.
- *
- * @note: The free dbg version doesn't allow to set the appropriate port within php.ini!
- *
- *
- */
- protected void createServerSocket () {
- if (this.remote) {
- port = SocketUtil.findUnusedLocalPort ("localhost", 10001, 10101); // Get the first free port in the range from 10001 to 10101
- }
- else {
- port = SocketUtil.findUnusedLocalPort ("localhost", 7869, 7869); // Get the first free port in the range from 7869 to 7869
- }
-
- if (port == -1) { // Did we get a free port?
- PHPDebugCorePlugin.log (5, "Cannot find free port!!!!"); // No, output a error message
-
- return; // And return
- }
- try {
- if (server == null) { // If there is no server socket yet
- server = new ServerSocket (port); // create a server socket for the free port
- //System.out.println("ServerSocket on port: " + port);
- }
- } catch (IOException e) {
- PHPDebugCorePlugin.log (e);
- stop ();
- }
- }
-
- /**
- *
- */
- public Socket getSocket () throws IOException {
- return socket; // Return the socket
- }
-
- /**
- * Set the DBG interface which is linked to this proxy
- *
- * @paran DBGInt The DGB interface which is linked with this proxy
- */
- protected void setDBGInterface (PHPDBGInterface DBGInt) {
- this.DBGInt = DBGInt;
- }
-
- /**
- * Get the DBG interface which is linked to this proxy
- *
- * @paran DBGInt The DGB interface which is linked with this proxy
- */
- public PHPDBGInterface getDBGInterface () {
- return DBGInt;
- }
-
- /**
- * Give back a buffered input stream for the socket which is
- * linked with this proxy
- */
- public BufferedReader getReader () throws IOException {
- if (reader == null) { // Do we already have a buffered input stream
- reader = new BufferedReader (new InputStreamReader (this.getSocket ().getInputStream (),
- "ISO8859_1"));
- }
-
- return reader; // Return the buffered input stream
- }
-
- /**
- *
- */
- public BufferedReader getReader (Socket socket) throws IOException {
- if (socket != null) { // Is a socket provided
- return new BufferedReader (new InputStreamReader (socket.getInputStream (),
- "ISO8859_1")); // Then create a buffered input stream
- }
- else {
- return null; // Without a socket we can't create a input stream
- }
- }
-
- /**
- *
- * @return The output stream for this proxy's socket
- */
- public OutputStream getOutputStream () throws IOException {
- return this.getSocket ().getOutputStream ();
- }
-
- /**
- *
- */
- protected void setBreakPoints () throws IOException, CoreException {
- IBreakpoint[] breakpoints = DebugPlugin.getDefault ().getBreakpointManager ().getBreakpoints ();
-
- for (int i = 0; i < breakpoints.length; i++) {
- if (breakpoints[i].isEnabled ()) {
- addBreakpoint (breakpoints[i]);
- }
- }
- }
-
- /**
- *
- */
- private String MapPath (PHPLineBreakpoint phpLBP) {
- IPath filename;
- IPath remotePath;
- IPath newpath;
- IPath localPath;
- String local;
-
- if (remote) {
- filename = phpLBP.getMarker().getResource().getProjectRelativePath();
- filename = remoteSourcePath.append (filename);
- } else {
- filename = phpLBP.getMarker().getResource().getLocation();
- }
-
- String path = filename.toOSString();
-
- if ((pathmap != null) && remote) {
- java.util.Iterator i = pathmap.keySet().iterator();
-
- while (i.hasNext()) {
- String k = (String) i.next();
- if (path.startsWith(k)) {
- path = pathmap.get(k) + path.substring(k.length());
- break;
- }
- }
- }
-
- if (remoteSourcePath.isEmpty ()) {
- if ((pathmap != null) && remote) {
- java.util.Iterator iterator = pathmap.keySet().iterator();
-
- while (iterator.hasNext ()) {
- local = (String) iterator.next (); // Get the local/client side path of the mapping
- remotePath = new Path ((String) pathmap.get (local)); // Get the remote/server side path of the mapping
- localPath = new Path (local); // Get the remote/server side path of the mapping
-
- if (localPath.isPrefixOf (filename)) { // Starts the remote/server side file path with the remote/server side mapping path
- // dann prefix abhängen und den remote path davorhägen
- newpath = filename.removeFirstSegments (localPath.matchingFirstSegments (filename));
- newpath = remotePath.append (newpath);
- path = newpath.toString ();
-
- if (path.substring (0, 1).equals ("/")) {
- path = path.replace ('\\', '/');
- }
- else {
- path = path.replace ('/', '\\');
- }
-
- return path;
- }
- }
- }
- }
- else {
- if (pathtranslation && remote) {
- if (remoteSourcePath.toString ().substring (0, 1).equals ("/")) {
- path = path.replace ('\\', '/');
- }
- else {
- path = path.replace ('/', '\\');
- }
- }
- }
-
- return path;
- }
-
- /**
- *
- */
- public void addBreakpoint (IBreakpoint breakpoint) {
- if (DBGInt == null) {
- return;
- }
-
- int bpNo = 0;
-
- try {
- PHPLineBreakpoint phpLBP;
-
- if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
- phpLBP = (PHPLineBreakpoint) breakpoint;
-
- // bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber());
- if (phpLBP.isConditionEnabled ()) {
- bpNo = DBGInt.addBreakpoint (MapPath(phpLBP),
- phpLBP.getLineNumber(),
- phpLBP.getHitCount(),
- phpLBP.getCondition ());
- }
- else {
- bpNo = DBGInt.addBreakpoint (MapPath(phpLBP),
- phpLBP.getLineNumber(),
- phpLBP.getHitCount(),
- "");
- }
-
- phpLBP.setDBGBpNo(bpNo);
- }
- } catch (IOException e) {
- PHPDebugCorePlugin.log(e);
- stop();
- } catch (CoreException e) {
- PHPDebugCorePlugin.log(e);
- stop();
- }
- }
-
- /**
- *
- */
- public void removeBreakpoint (IBreakpoint breakpoint) {
- if (DBGInt == null) {
- return;
- }
-
- try {
- PHPLineBreakpoint phpLBP;
-
- if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier ()) {
- phpLBP = (PHPLineBreakpoint) breakpoint;
-
- // bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber());
-
- DBGInt.removeBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber(), phpLBP.getDBGBpNo());
- }
- } catch (IOException e) {
- PHPDebugCorePlugin.log (e);
- stop ();
- } catch (CoreException e) {
- PHPDebugCorePlugin.log (e);
- stop ();
- }
- }
-
- /**
- *
- */
- public void phpLoopNotify () {
- phpLoop.notifyWait ();
- }
-
- /**
- *
- */
- public void startPHPLoop () {
- phpLoop = new PHPLoop (); // Create a DBG communication loop object
-
- phpLoop.start (); // And start the communication loop
- }
-
- /**
- *
- */
- public void resume () {
- try {
- DBGInt.continueExecution();
- phpLoop.notifyWait();
- } catch (IOException e) {
- PHPeclipsePlugin.log("Debugging session ended.", e);
- stop();
- }
- }
-
- /**
- *
- */
- public void pause () {
- try {
- if (null != DBGInt) {
- DBGInt.pauseExecution();
- }
- else {
- // TODO Make sure the Suspend action is grayed out
- // when DBGInt is null
- }
- } catch (IOException e) {
- PHPDebugCorePlugin.log (e);
- stop ();
- }
- }
-
- /**
- *
- */
- protected PHPDebugTarget getDebugTarget() {
- return debugTarget;
- }
-
- /**
- * Is called by the DebuggerRunner
- *
- * @param debugTarget
- */
- public void setDebugTarget (PHPDebugTarget debugTarget) {
- this.debugTarget = debugTarget;
- debugTarget.setPHPDBGProxy(this);
- }
-
- /**
- * This method is called by a stackframe.
- * It reads the variables from PHP via DBG
- *
- * @param frame The stackframe which wants the variables.
- * @return The list of variables for this stackframe.
- */
- public Vector readVariables (PHPStackFrame frame) {
- try {
- return DBGInt.getVariables (frame); // Get the variables from DBG interface
- } catch (IOException ioex) {
- ioex.printStackTrace ();
- throw new RuntimeException (ioex.getMessage ());
- } catch (DebugException ex) {
- ex.printStackTrace ();
- throw new RuntimeException (ex.getMessage ());
- }
- }
-
- /**
- *
- * @param frame
- * @param evalString
- * @return
- */
- public PHPVariable[] eval (PHPStackFrame frame, String evalString) {
- try {
- return DBGInt.evalBlock (frame, evalString);
- //return DBGInt.getVariables(frame);
- } catch (IOException ioex) {
- ioex.printStackTrace();
- throw new RuntimeException(ioex.getMessage());
- } catch (DebugException ex) {
- ex.printStackTrace();
- throw new RuntimeException(ex.getMessage());
- }
- }
-
- public void readStepOverEnd (PHPStackFrame stackFrame) {
- try {
- DBGInt.stepOver();
- phpLoop.notifyWait();
- } catch (Exception e) {
- PHPDebugCorePlugin.log(e);
- }
- }
-
- public void readStepReturnEnd (PHPStackFrame stackFrame) {
- try {
- DBGInt.stepOut();
- phpLoop.notifyWait();
- } catch (Exception e) {
- PHPDebugCorePlugin.log(e);
- }
- }
-
- public void readStepIntoEnd (PHPStackFrame stackFrame) {
- try {
- DBGInt.stepInto();
- phpLoop.notifyWait();
- } catch (Exception e) {
- PHPDebugCorePlugin.log(e);
- }
- }
-
- /*
- * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new
- * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { //
- * PHPDebugCorePlugin.log(e); // return null; //}
- * }
- */
-
- public void closeSocket() throws IOException {
- if (socket != null) {
- socket.close();
- }
- }
-
- public void closeServerSocket() throws IOException {
- if (server != null) {
- server.close();
- }
- }
-
- public int getPort() {
- return port;
- }
-
- /**
- *
- *
- */
- class PHPLoop extends Thread {
- private boolean shouldStop;
-
- public PHPLoop () {
- shouldStop = false;
- this.setName ("PHPDebuggerLoop");
- }
-
- /**
- *
- */
- public synchronized void setShouldStop () {
- shouldStop = true; // The run loop should stop
-
- try {
- // If the loop thread is blocked on the server socket,
- // forcibly unblock it to avoid leaking the thread,
- // the socket and the port
- closeServerSocket ();
- } catch (IOException x) {
- // Log this as a warning?
- PHPDebugCorePlugin.log (x);
- }
- }
-
- /**
- *
- */
- public synchronized void notifyWait () {
- notify ();
- }
-
- /**
- *
- *
- */
- public void run () {
- try {
- int i;
- int timeout;
- long interval = 200; // Wait 200 ms maximum for a DBG response
- boolean newconnect = false; //
- Socket newSocket = null;
- PHPStackFrame[] StackList;
- PHPDBGInterface newDBGInt;
-
- // synchronized (this) {
- // wait();
- // }
-
- PHPMainThread = new PHPThread (getDebugTarget (), getPort ());
- PHPMainThread.setName ("Thread [main]");
- timeout = 0;
-
- // while ((getDebugTarget() == null) && (timeout < 100)) {
- // sleep(100);
- // timeout++;
- // }
- // Be sure debug target is set
- // PHPMainThread.setDebugTarget(getDebugTarget());
-
- getDebugTarget ().addThread (PHPMainThread);
-
- //System.out.println("Waiting for breakpoints.");
-
- while (!shouldStop) { // As long as nobody will stop us
- newconnect = true; // The first time
-
- try {
- newSocket = server.accept(); // Waits until DBG want to connect
- //System.out.println("Accepted! : " + socket.toString());
- } catch (SocketTimeoutException e) {
- newconnect = false; // No one wants to connect (connection already done)
- } catch (IOException e) {
- PHPDebugCorePlugin.log(e);
- return;
- }
-
- if (newconnect) { // Is it just after a new connection
- if (DBGInt == null) { // Do we have a DBG interface?
- server.setSoTimeout(1); // ???
- }
-
- newDBGInt = new PHPDBGInterface (getReader (newSocket), // Create a new interface
- newSocket.getOutputStream (),
- thisProxy);
- newDBGInt.waitResponse (1000); // Wait for the initial DBG response
- newDBGInt.flushAllPackets (); // Read and process the DBG response
-
- // Check version and session ID
- if ((DBGInt == null) || // If we have no interface
- (DBGInt.getSID () == newDBGInt.getSID ())) {// or the new session ID is different to the old one
- DBGInt = newDBGInt; // Set the new interface as current one
-
- try {
- closeSocket ();
- }
- catch (IOException e) {
- PHPDebugCorePlugin.log (e);
- shouldStop = true;
- }
-
- socket = newSocket;
- setBreakPoints ();
- DBGInt.continueExecution (); // Notify DBG that PHP should continue
- }
- else {
- newDBGInt.continueExecution (); // Notify DBG that PHP should continue
- newSocket.close ();
- }
- }
-
- if (DBGInt.waitResponse (interval)) { // Wait for a DBG response (200 ms)
- DBGInt.flushAllPackets (); // If we got something, read and process it
-
- if (DBGInt.BPUnderHit != 0) { // ???
- StackList = DBGInt.getStackList (); // Get the stack list from DBGInterface
-
- if (StackList.length > 0) { // If there is something in stack list
- for (i = 0; i < StackList.length; i++) { // For all stack list
- StackList[i].setThread (PHPMainThread); // Set the PHPTread for all PHPStackFrames
-
- if (DBGInt.getModByNo (StackList[i].getModNo ()).equals ("")) {
- DBGInt.getSourceTree ();
- }
-
- StackList[i].setFile (DBGInt.getModByNo (StackList[i].getModNo ()));
- }
-
- PHPMainThread.setStackFrames (StackList);
- }
-
- PHPMainThread.suspend (); // Fire debug event
-
- synchronized (this) {
- wait ();
- }
- }
- }
-
- if (remote) {
- if (PHPMainThread.isTerminated ()) {
- shouldStop = true;
-
- break; // Go for terminating the thread
- }
- } else {
- if (PHPMainThread.isTerminated () ||
- getDebugTarget ().getProcess ().isTerminated ()) {
- shouldStop = true;
-
- break; // Go for terminating the thread
- }
- }
- }
- } catch (Exception ex) {
- PHPDebugCorePlugin.log (ex);
- System.out.println (ex);
- } finally {
- try {
- getDebugTarget ().terminate ();
- closeSocket();
- closeServerSocket ();
- } catch (IOException e) {
- PHPDebugCorePlugin.log (e);
-
- return;
- }
-
- //System.out.println("Socket loop finished.");
- }
- }
- }
-}