refactory whole plugin
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / php / model / XDebugTarget.java
index 9f31828..d032172 100644 (file)
@@ -3,12 +3,14 @@
  */
 package net.sourceforge.phpeclipse.xdebug.php.model;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.List;
 
-import net.sourceforge.phpeclipse.xdebug.core.AbstractDebugConnection;
-import net.sourceforge.phpeclipse.xdebug.core.IDebugConnection;
+import net.sourceforge.phpeclipse.xdebug.core.Base64;
 import net.sourceforge.phpeclipse.xdebug.core.IPHPDebugEvent;
 import net.sourceforge.phpeclipse.xdebug.core.IProxyEventListener;
+import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
 import net.sourceforge.phpeclipse.xdebug.core.XDebugProxy;
@@ -28,63 +30,42 @@ import org.eclipse.debug.core.ILaunchListener;
 
 import org.eclipse.debug.core.model.IBreakpoint;
 import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.ILineBreakpoint;
 import org.eclipse.debug.core.model.IMemoryBlock;
 import org.eclipse.debug.core.model.IProcess;
 import org.eclipse.debug.core.model.IStackFrame;
 import org.eclipse.debug.core.model.IThread;
-import org.eclipse.debug.core.model.IValue;
+//import org.eclipse.debug.core.model.IValue;
 import org.eclipse.debug.core.model.IVariable;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
+import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugConnection;
 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener.DebugResponse;
 
 /**
  * @author Christian
  *
  */
-public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunchListener, IDebugEventSetListener, IProxyEventListener{
-       // associated system process (VM)
+public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunchListener, IDebugEventSetListener, IProxyEventListener {
        private IProcess fProcess;
        
-       // containing launch object
        private ILaunch fLaunch;
        
-       // debugPort
        private int fDebugPort;
        
-       // suspend state
        private boolean fSuspended = false;
        
-       // terminated state
        private boolean fTerminated = false;
        
-       // threads
        private XDebugThread fThread;
        private IThread[] fThreads;
        
-       private AbstractDebugConnection fDebugConnection;
+       private XDebugConnection fDebugConnection;
 
        private String fIdeKey;
 
 
-       public XDebugTarget() {
-               super(null);
-       }
-
-       /**
-        * Constructs a new debug target in the given launch and waits until
-        * someone with the ideKey connects to the Debugproxy
-        *  
-        * 
-        * @param launch containing launch
-        * @param process process of the interpreter
-        * @param ideKey 
-        * @exception CoreException if unable to connect to host
-        */
-       
-       public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
-               init(launch, process, ideKey);
-       }
-
        /**
         * Constructs a new debug target in the given launch and waits until
         * someone with the ideKey connects to the Debugproxy
@@ -95,14 +76,8 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @param ideKey 
         * @param pathMap Pathmap for the debug session
         * @exception CoreException if unable to connect to host
-        */
-       
-       /*public XDebugTarget(ILaunch launch, IProcess process, String ideKey, List<String> pathMap) throws CoreException {
-               super(null);
-               init(launch, process, ideKey,pathMap);
-       }*/
-       
-       private void init(ILaunch launch, IProcess process, String ideKey/*,List<String> pathMap*/) {
+        */     
+       public XDebugTarget(ILaunch launch, IProcess process, String ideKey) throws CoreException {
                fLaunch = launch;
                fProcess = process;
                fTarget = this;
@@ -197,8 +172,6 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @see org.eclipse.debug.core.model.ITerminate#terminate()
         */
        public void terminate() throws DebugException {
-               //IThread  t = fThreads.length();
-               //fTerminated=true;
                XDebugProxy proxy=XDebugCorePlugin.getDefault().getXDebugProxy();
                proxy.stop();
                proxy.removeProxyEventListener(this,fIdeKey);
@@ -217,7 +190,6 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
         */
        public boolean canResume() {
-//             return !isTerminated() && isSuspended();
                return false;
        }
 
@@ -225,7 +197,6 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
         */
        public boolean canSuspend() {
-//             return !isTerminated() && !isSuspended();
                return false;
        }
 
@@ -293,18 +264,28 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
                                for (int i = 0; i < pathMap.size(); i++) {
                                        pmi = new PathMapItem((String) pathMap.get(i));
                                        IPath local = (IPath)pmi.getLocalPath().clone();
-                                       local = local./*removeFirstSegments(1).*/makeAbsolute();
+                                       local = local.makeAbsolute();
                                        int matchedSegments = local.segmentCount();
                                        if (local.matchingFirstSegments(cp) == matchedSegments) {
                                                IPath newPath = pmi.getRemotePath();
-                                               //newPath = newPath.removeFirstSegments(1);                                             
                                                newPath = newPath.append(path.removeFirstSegments(matchedSegments));
                                                newPath = newPath.makeAbsolute();
                                                if (supportsBreakpoint(breakpoint)) {
                                                        try {
-                                                               fDebugConnection.addBreakpoint(breakpoint, newPath);
+                                                               if (breakpoint.isEnabled()) {
+                                                                       if (marker != null) {
+                                                                               //fDebugConnection.addBreakpoint(breakpoint, newPath);
+                                                                               DebugResponse dr = fDebugConnection.breakpointSet(newPath.toString(), ((ILineBreakpoint)breakpoint).getLineNumber());
+                                                                               String bpid = dr.getAttributeValue("id");
+                                                                               
+                                                                               if (!"".equals(bpid))
+                                                                                       marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
+                                                                       }
+                                                               }
                                                        } catch (DebugException e) {
                                                                e.printStackTrace();
+                                                       } catch (CoreException e) {
+                                                               e.printStackTrace();
                                                        }
                                                }
                                        }
@@ -312,9 +293,19 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
                        } else {
                                if (supportsBreakpoint(breakpoint)) {
                                        try {
-                                               fDebugConnection.addBreakpoint(breakpoint, path);
+                                               if (breakpoint.isEnabled()) {
+                                                       if (marker != null) {
+                                                               DebugResponse dr = fDebugConnection.breakpointSet(path.toString(), ((ILineBreakpoint)breakpoint).getLineNumber());
+                                                               String bpid = dr.getAttributeValue("id");
+                                                               
+                                                               if (!"".equals(bpid))
+                                                                       marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
+                                                       }
+                                               }
                                        } catch (DebugException e) {
                                                e.printStackTrace();
+                                       } catch (CoreException e) {
+                                               e.printStackTrace();
                                        }
                                }
                        }
@@ -327,7 +318,9 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
        public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
                if (supportsBreakpoint(breakpoint)) {
                        try {
-                               fDebugConnection.removeBreakpoint(breakpoint);
+                               int id =((XDebugLineBreakpoint)breakpoint).getID();
+                               if (id >0)
+                                       fDebugConnection.breakpointRemove(id);
                        } catch (CoreException e) {
                        }
                }
@@ -391,7 +384,7 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
                fThread.setBreakpoints(null);
                fThread.setStepping(false);
 
-               /*boolean CanDisconnect =*/ Integer.parseInt(fDebugConnection.featureGet("detach").getValue()) /*!= 0*/;
+               Integer.parseInt(fDebugConnection.featureGet("detach").getValue());
 
                System.out.println("in Target.started()");
                DebugResponse response = fDebugConnection.featureGet("max_children");
@@ -410,7 +403,6 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
                installDeferredBreakpoints();
                try {
                        resume();
-//                     step();
                } catch (DebugException e) {
                        e.printStackTrace();
                }
@@ -445,8 +437,42 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @return the current stack frames in the target
         * @throws DebugException if unable to perform the request
         */
-       protected IStackFrame[] getStackFrames() throws DebugException {
-               return fDebugConnection.getStackFrames(fThread);
+       public IStackFrame[] getStackFrames() throws DebugException {
+               DebugResponse lastResponse = fDebugConnection.stackGet(0);
+
+               if (lastResponse.isError())
+                       return new IStackFrame[0];
+               Node response = lastResponse.getParentNode();
+               NodeList frames = response.getChildNodes();
+               IStackFrame[] theFrames = new IStackFrame[frames.getLength()];
+               for (int i = 0; i < frames.getLength(); i++) {
+                       Node stackNode = frames.item(i);
+                       XDebugStackFrame frame = new XDebugStackFrame(fThread, i);
+                       String level =PHPDebugUtils.getAttributeValue(stackNode,"level");
+                       if (!"".equals(level))
+                               frame.setLevel(Integer.parseInt(level));
+
+                       frame.setType(PHPDebugUtils.getAttributeValue(stackNode,"type"));
+                       String fileName=PHPDebugUtils.unescapeString(PHPDebugUtils.getAttributeValue(stackNode,"filename"));
+                       String lineNo=PHPDebugUtils.getAttributeValue(stackNode,"lineno");
+
+                       if (!"".equals(lineNo))
+                               frame.setLineNumber(Integer.parseInt(lineNo));
+                       
+                       frame.setWhere(PHPDebugUtils.getAttributeValue(stackNode,"where"));
+                       
+                       try {
+                               frame.setFullName(new URL(fileName));
+                       } catch (MalformedURLException e) {
+                               e.printStackTrace();
+                       }
+
+                       frame.incrementStepCounter();
+                       
+                       theFrames[i] = frame;
+               }
+               
+               return theFrames;
        }
        
        /**
@@ -489,75 +515,75 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
         * @return variable value
         * @throws DebugException if the request fails
         */
-       protected IValue getVariableValue(XDebugVariable variable) throws DebugException {
+       /*protected IValue getVariableValue(XDebugVariable variable) throws DebugException {
                return null;
-       }
+       }*/
        
        /**
         * Returns the values on the data stack (top down)
         * 
         * @return the values on the data stack (top down)
         */
-       public IValue[] getDataStack() throws DebugException {
+       /*public IValue[] getDataStack() throws DebugException {
                return new IValue[0];           
-       }
+       }*/
        
        public boolean setVarValue(String name, String value) {
                return fDebugConnection.setVarValue(name,value);
        }
        
        public void handleDebugEvents(DebugEvent[] events) {
-               for (int i=0;i<events.length;i++) {
-                       DebugEvent event=events[i];
-                       if(event.getKind()==DebugEvent.MODEL_SPECIFIC) {
-                               if (event.getDetail()==IPHPDebugEvent.BREAKPOINT_HIT) {
-                                       IBreakpoint breakpoint = (IBreakpoint) event.getData();
-                                       fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
-                                       fThread.incrementStepCounter();
-                                       suspended(DebugEvent.BREAKPOINT);
-                               } else if (event.getDetail()==IPHPDebugEvent.STEP_END) {
-                                       fThread.incrementStepCounter();
-                                       suspended(DebugEvent.STEP_END);
-                               } else if (event.getDetail()==IPHPDebugEvent.STOPPED) {
-                                       //fDebugConnection.removeBreakpoint(breakpoint);
-                                       fThread.removeEventListeners();
-                                       fThread=null;
-                                       fThreads= new IThread[0];
-                                       fSuspended=false;
-                                       // TODO Dirty hack to check debugging mode (remote or local)
-                                       if (fProcess!=null) {
-                                               try {
-                                                       terminate();
-                                               } catch (DebugException e) {
-                                                       e.printStackTrace();
+               for (int i = 0; i < events.length; i++) {
+                       DebugEvent event = events[i];
+                       if (event.getKind() == DebugEvent.MODEL_SPECIFIC) {
+                               switch (event.getDetail()) {
+                                       case IPHPDebugEvent.BREAKPOINT_HIT:
+                                               DebugResponse lastResponse = ((XDebugConnection) fDebugConnection).stackGet(0);
+
+                                               IBreakpoint breakpoint = breakpointHit(lastResponse.getParentNode());
+       
+                                               fThread.setBreakpoints(new IBreakpoint[]{breakpoint});
+                                               fThread.incrementStepCounter();
+                                               suspended(DebugEvent.BREAKPOINT);
+                                               break;
+                                       case IPHPDebugEvent.STEP_END:
+                                               fThread.incrementStepCounter();
+                                               suspended(DebugEvent.STEP_END);
+                                               break;
+                                       case IPHPDebugEvent.STOPPED:
+                                               fThread.removeEventListeners();
+                                               fThread = null;
+                                               fThreads = new IThread[0];
+
+                                               fDebugConnection.close();
+
+                                               fSuspended = false;
+
+                                               // Dirty hack to check debugging mode (remote or local)
+                                               if (fProcess!=null) {
+                                                       try {
+                                                               terminate();
+                                                       } catch (DebugException e) {
+                                                               e.printStackTrace();
+                                                       }
+                                               } else {
+                                                       fDebugConnection = null;
+                                                       fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
                                                }
-                                       } else {
-                                               fDebugConnection = null;
-                                               fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT));
-                                       }
-                               } else {
-                                       int a = 20;
-                                       a *= 10;
+                                               break;
                                }
-                       } else {
-                               int b = 10;
-                               b *= 1;
                        }
                }
-               
        }
-       
-       public void handleProxyEvent(String ideKey, String initString, AbstractDebugConnection connection) {
+
+       public void handleProxyEvent(String ideKey, String initString, /*AbstractDebugConnection*/ XDebugConnection connection) {
                System.out.println("* New Connection - XDebug.Target: "+ideKey);
                setDebugConnection(connection);
                
                XDebugProxy proxy=XDebugCorePlugin.getDefault().getXDebugProxy();
                fDebugPort=proxy.getProxyPort();
                fireEvent(new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CHANGE));
-
                
-//             proxy.removeProxyEventListener(this,ideKey);
-//             System.out.println("XDebug.Target: ProxyEventlistener removed");
                fThread = new XDebugThread(this);
                fThreads = new IThread[] {fThread};
                try {
@@ -567,7 +593,7 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
                }               
        }
 
-       private void setDebugConnection(AbstractDebugConnection connection) {
+       private void setDebugConnection(XDebugConnection connection) {
                if (connection != null) {
                        fDebugConnection = connection;
                        fDebugConnection.startListener();
@@ -577,7 +603,7 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
        /**
         * @return Returns the fDebugConnection.
         */
-       public IDebugConnection getDebugConnection() {
+       public XDebugConnection getDebugConnection() {
                return fDebugConnection;
        }       
        
@@ -610,7 +636,130 @@ public class XDebugTarget extends XDebugElement implements IDebugTarget, ILaunch
        public void launchChanged(ILaunch launch) {
        }
        
-       public IVariable[] getVariables(XDebugStackFrame StackFrame, int Level) {
-               return fDebugConnection.getVariables(StackFrame, Level);
+       public IVariable[] getVariables(XDebugStackFrame frame, int level)  throws DebugException {
+               IVariable[] variables = null;
+               
+               DebugResponse response = fDebugConnection.contextGet(level, 0);
+               Node responseNode = response.getParentNode();
+               NodeList property = responseNode.getChildNodes();
+               
+               DebugResponse responseGlobal = fDebugConnection.contextGet(level, 1);
+               Node responseGlobalNode = responseGlobal.getParentNode();
+               NodeList propertyGlobal = responseGlobalNode.getChildNodes();
+               
+               variables = new IVariable[property.getLength() + propertyGlobal.getLength()];
+//             variables = new IVariable[property.getLength()]; // + propertyGlobal.getLength()];
+               
+               int length = property.getLength();
+               for (int i = 0; i < length; i++) {
+                       Node propertyNode = property.item(i);
+                       XDebugVariable var=/*fDebugConnection.*/getVariableFromNode(frame,propertyNode);
+                       variables[i]=var;
+               }
+
+               int globalLength = propertyGlobal.getLength();
+               for (int k = 0; k < globalLength; k++) {
+                       Node propertyGlobalNode = propertyGlobal.item(k);
+                       XDebugVariable var=/*fDebugConnection.*/getVariableFromNode(frame,propertyGlobalNode);
+                       variables[k + length]=var;
+               }
+       
+               return variables;
+       }       
+
+       public XDebugVariable getVariableFromNode(XDebugStackFrame frame, Node property) {
+               String varFullName = PHPDebugUtils.getAttributeValue(property, "fullname");
+               String varName = PHPDebugUtils.getAttributeValue(property, "name");
+               String varEncoding = PHPDebugUtils.getAttributeValue(property, "encoding");
+               
+               int varNumChildren = 0;
+               if (PHPDebugUtils.getAttributeValue(property, "numchildren").equals("")) {
+                       varNumChildren = 0;
+               } else {
+                       varNumChildren = Integer.parseInt(PHPDebugUtils.getAttributeValue(property, "numchildren"));
+               }
+
+               String typeName = PHPDebugUtils.getAttributeValue(property,"type");
+
+               XDebugVariable variable = new XDebugVariable(frame,varFullName,varName,typeName);
+               variable.setEncoding(varEncoding);
+               variable.setNumChildren(varNumChildren);
+               XDebugAbstractValue val=null;
+               try {
+                       val = (XDebugAbstractValue) variable.getValue();
+               } catch (DebugException e1) {
+                       // TODO Auto-generated catch block
+                       e1.printStackTrace();
+               }
+               if (val.getType()!= XDebugAbstractValue.VALUETYPE_UNINITIALIZED) {
+                       if (variable.hasChildren()) {
+                               NodeList varNodes = property.getChildNodes();
+                               val.renderValueString(""+varNodes.getLength());
+                               IVariable[] variables = new IVariable[varNodes.getLength()];
+                               for (int i = 0; i<varNodes.getLength(); i++) {
+                                       Node propertyNode = varNodes.item(i);
+                                       variables[i] = getVariableFromNode(frame, propertyNode);
+                               }
+                               val.setChildVariables(variables);
+                       }else {
+                               String str="";
+                               try {
+                                       str=property.getFirstChild().getNodeValue();
+                               } catch (NullPointerException e) {
+                                       str="";
+                               }
+                               if (variable.getEncoding().equals("base64")) {
+                                       if (str.length()!=0)
+                                               str=new String(Base64.decode(str));
+                                       else
+                                               str="";
+                               }
+                               val.renderValueString(str);
+                       }
+                       
+                       String className=PHPDebugUtils.getAttributeValue(property,"classname");
+                       if(!"".equals(className))
+                               val.renderValueString(className);
+               }
+               return variable;
+               
        }
+
+       protected IBreakpoint breakpointHit(Node node) {
+               Node child=node.getFirstChild();
+               if (child.getNodeName().equals("stack")) {
+                       int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "lineno"));
+                       String filename=PHPDebugUtils.getAttributeValue(child, "filename");  
+                       IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
+                       for (int i = 0; i < breakpoints.length; i++) {
+                               IBreakpoint breakpoint = breakpoints[i];
+                               if (supportsBreakpoint(breakpoint)) {
+                                       if (breakpoint instanceof ILineBreakpoint) {
+                                               ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
+                                               try {                                           
+                                                       if (breakpoint.isEnabled()) {
+                                                               IMarker marker = breakpoint.getMarker();
+                                                               if (marker != null) {
+                                                                       String endfilename;
+                                                                       
+                                                                       if (getProcess() == null) {
+                                                                               endfilename = marker.getResource().getLocation().lastSegment(); 
+                                                                       } else {
+                                                                               endfilename = marker.getResource().getLocation().toOSString();
+                                                                       }
+
+                                                                       if(PHPDebugUtils.unescapeString(filename).endsWith(endfilename) && (lineBreakpoint.getLineNumber() == lineNumber) ) {
+                                                                               return (breakpoint);
+                                                                       }
+                                                               }
+                                                       }
+                                               } catch (CoreException e) {
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               return null;
+       }       
 }
\ No newline at end of file