Importing the XDebugProxy code in the HEAD. The repo was tagged with T_BEFORE_XDEBUGP...
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / core / xdebug / XDebugConnection.java
1 /**
2  * 
3  */
4 package net.sourceforge.phpeclipse.xdebug.core.xdebug;
5
6 import java.io.DataInputStream;
7 import java.io.EOFException;
8 import java.io.IOException;
9 import java.io.OutputStreamWriter;
10 //import java.io.UnsupportedEncodingException;
11 import java.net.MalformedURLException;
12 import java.net.Socket;
13 import java.net.URL;
14
15 import net.sourceforge.phpeclipse.xdebug.core.AbstractDebugConnection;
16 import net.sourceforge.phpeclipse.xdebug.core.Base64;
17 import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
18 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
19 import net.sourceforge.phpeclipse.xdebug.core.xdebug.ResponseListener.DebugResponse;
20 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugAbstractValue;
21 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugLineBreakpoint;
22 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
23 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread;
24 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugVariable;
25
26 import org.eclipse.core.resources.IMarker;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.core.runtime.IStatus;
30 //import org.eclipse.core.runtime.Path;
31 import org.eclipse.core.runtime.jobs.Job;
32 import org.eclipse.debug.core.DebugException;
33 import org.eclipse.debug.core.model.IBreakpoint;
34 import org.eclipse.debug.core.model.ILineBreakpoint;
35 import org.eclipse.debug.core.model.IStackFrame;
36 import org.eclipse.debug.core.model.IVariable;
37 import org.w3c.dom.Node;
38 import org.w3c.dom.NodeList;
39
40 /**
41  * @author Christian Perkonig
42  *
43  */
44 public class XDebugConnection extends AbstractDebugConnection {
45         int fTransactionID = 0;
46         private Socket fDebugSocket;
47         private OutputStreamWriter fDebugWriter;
48         private DataInputStream fDebugReader;
49         private ResponseList fResponseList;
50         private ResponseListener fResponseListener;
51
52         
53         public XDebugConnection(Socket debugSocket, DataInputStream reader, OutputStreamWriter writer) {
54                 fResponseList = new ResponseList();
55                 fDebugWriter = writer;
56                 fDebugReader = reader;
57                 fDebugSocket = debugSocket;
58                 fTransactionID = 0;
59                 init();
60         }
61         
62         private void init() {
63                 fInitialized = false;
64                 String initString=readData();
65                 XDebugCorePlugin.log(IStatus.INFO,initString);
66
67                 int startIdx=initString.indexOf("idekey=\"");
68                 if (startIdx==-1)
69                         return;
70                 startIdx+=8;
71                 int endIdx=initString.indexOf('"',startIdx);
72                 if (endIdx==-1)
73                         return;
74                 fSessionID=initString.substring(startIdx,endIdx);
75                 
76                 fInitialized=true;
77                 fIsClosed=false;
78                 fResponseListener=new ResponseListener(this);
79         }
80
81         protected String readData()     {
82         byte byteBuffer[]=null,b;
83                 int count=0;
84                 
85                 try {
86                         while ((b =fDebugReader.readByte()) != 0) {
87                                 count = count * 10 + b - '0';
88 //                              count=count*10+Integer.parseInt(b);
89                         }
90 //                      System.out.println(count);
91                         byteBuffer = new byte[count];
92                         int readCount=0;
93                         int attempts=0;
94                         while ((count >0) && (attempts < 50)) {
95 //                      while ((count >0) && (attempts <5)) {
96                                 int rc=fDebugReader.read(byteBuffer,readCount,count);
97                                 count-=rc;
98                                 readCount+=rc;
99                                 if (count>65530)
100                                         try {
101                                                 Thread.sleep(200);
102                                         } catch (InterruptedException e) {
103                                         }
104                                 else
105                                         attempts++;
106                         }
107                         if((b= fDebugReader.readByte())!=0) // reads the NULL Byte at the end;
108                                 System.out.println("NULL-Byte missing!!"); 
109                 } catch (IOException e) {
110                         // TODO Auto-generated catch block
111                         if (e instanceof EOFException==false)
112                                 e.printStackTrace();
113                         return null;
114                 }
115                 return new String(byteBuffer);
116         }
117         
118         
119         /**
120          * Sends a request to the Debugengine and waits for an OK.
121          * 
122          * @param command debug command
123          * @throws DebugException if the request fails
124          */
125         
126         
127         public int sendRequest(String command) throws DebugException {  
128                 return sendRequest(command,"");
129         }
130         
131         public DebugResponse sendRequestA(String command, String parameter) {
132                 int result = -1;
133                 
134                 try {
135                         result = sendRequest(command, parameter);
136                 } catch( DebugException e ){
137                         e.printStackTrace();            
138                 }
139
140                 DebugResponse response = getResponse(result);
141                 
142                 return response;
143         }
144         
145         /**
146          * Sends a request to the Debugengine.
147          * 
148          * @param command debug command
149          * @arguments arguments for the command
150          * @throws DebugException if the request fails
151          */
152         
153         public synchronized int sendRequest(String command, String arguments) throws DebugException {
154                 
155                 XDebugCorePlugin.log(IStatus.INFO,command+" -i "+fTransactionID+" "+arguments);
156                 synchronized (fDebugSocket) {
157                         try {
158                                 fDebugWriter.write(command);
159                                 fDebugWriter.write(" -i " + fTransactionID);
160                                 if (!"".equals(arguments))
161                                         fDebugWriter.write(" " + arguments);
162                                 fDebugWriter.write(0);
163                                 fDebugWriter.flush();
164                         } catch (IOException e) {
165                                 //e.printStackTrace();
166                 }
167                 }
168                 return fTransactionID++;
169         }
170
171         /* (non-Javadoc)
172          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#featureGet(java.lang.String)
173          */
174         public DebugResponse featureGet(String featureName) {
175                 int id=-1;
176                 
177                 try {
178                         id= sendRequest("feature_get","-n "+featureName);
179                 } catch (DebugException e) {
180                         // TODO Auto-generated catch block
181                         e.printStackTrace();
182                 }
183                 
184                 DebugResponse response = getResponse(id);
185
186                 return response;
187         }
188
189         public boolean featureSet(String featureName, String value) {
190                 int id=-1;
191                 
192                 try {
193                         id= sendRequest("feature_set","-n "+featureName + " -v " + value);
194                 } catch (DebugException e) {
195                         // TODO Auto-generated catch block
196                         e.printStackTrace();
197                 }
198
199                 if (getResponse(id).getAttributeValue("success").equals("1") )
200                         return true;
201                 else
202                         return false;
203         }
204
205         protected DebugResponse getResponse(int id) {
206                 return fResponseList.get(id);
207         }
208
209         protected void addResponse(DebugResponse response, int id) {
210                 fResponseList.add(response,id);
211                 
212         }
213         
214         /* (non-Javadoc)
215          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#addBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
216          */
217         public void addBreakpoint(IBreakpoint breakpoint, IPath filePath) throws DebugException {
218                 try {
219                         if (breakpoint.isEnabled()) {
220                                 IMarker marker = breakpoint.getMarker();
221                                 if (marker != null) {
222                                         try {
223                                                 String arg;
224                                                 
225                                                 arg = "-t line -f file://"+PHPDebugUtils.escapeString(filePath.toString())+" -n "+((ILineBreakpoint)breakpoint).getLineNumber();
226                                                 int id = sendRequest("breakpoint_set", arg);
227                                                 String bpid = getResponse(id).getAttributeValue("id");
228                                                 
229                                                 if (!"".equals(bpid))
230                                                         marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
231                                                 
232                                         } catch (CoreException e) {
233                                                 XDebugCorePlugin.log(IStatus.INFO,"Exception set break point");                                         
234                                         }
235                                 }
236                         }
237                 } catch (CoreException e) {
238                         XDebugCorePlugin.log(IStatus.INFO,"Exception in breakpoint");                                                                   
239                 }
240         }
241
242         /* (non-Javadoc)
243          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#removeBreakpoint(int)
244          */
245         public void removeBreakpoint(IBreakpoint breakpoint) throws DebugException {
246                 try {
247                         int id =((XDebugLineBreakpoint)breakpoint).getID();
248                         if (id >0)
249                                 sendRequest("breakpoint_remove","-d "+id);
250                 } catch (CoreException e) {
251                 }
252         }
253
254         /* (non-Javadoc)
255          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#getStackFrames(net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread)
256          */
257         public IStackFrame[] getStackFrames(XDebugThread thread) throws DebugException {
258                 int id = sendRequest("stack_get");
259                 DebugResponse lastResponse = getResponse(id);
260                 if (lastResponse.isError())
261                         return new IStackFrame[0];
262                 Node response = lastResponse.getParentNode();
263                 NodeList frames = response.getChildNodes();
264                 IStackFrame[] theFrames = new IStackFrame[frames.getLength()];
265                 for (int i = 0; i < frames.getLength(); i++) {
266                         Node stackNode = frames.item(i);
267                         XDebugStackFrame frame = new XDebugStackFrame(thread, i);
268                         String level =PHPDebugUtils.getAttributeValue(stackNode,"level");
269                         if (!"".equals(level))
270                                 frame.setLevel(Integer.parseInt(level));
271
272                         frame.setType(PHPDebugUtils.getAttributeValue(stackNode,"type"));
273                         String fileName=PHPDebugUtils.unescapeString(PHPDebugUtils.getAttributeValue(stackNode,"filename"));
274                         String lineNo=PHPDebugUtils.getAttributeValue(stackNode,"lineno");
275
276                         if (!"".equals(lineNo))
277                                 frame.setLineNumber(Integer.parseInt(lineNo));
278                         
279                         frame.setWhere(PHPDebugUtils.getAttributeValue(stackNode,"where"));
280                         
281                         try {
282                                 frame.setFullName(new URL(fileName));
283                         } catch (MalformedURLException e) {
284                                 e.printStackTrace();
285                         }
286
287                         frame.incrementStepCounter();
288                         
289                         theFrames[i] = frame;
290                 }
291                 
292                 return theFrames;
293         }
294
295         /* (non-Javadoc)
296          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepOver()
297          */
298         public void stepOver() throws DebugException {
299                 sendRequest ("step_over");
300         }
301
302         /* (non-Javadoc)
303          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepInto()
304          */
305         public void stepInto() throws DebugException {
306                 sendRequest("step_into");
307         }
308
309         /* (non-Javadoc)
310          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepOut()
311          */
312         public void stepOut() throws DebugException {
313                 sendRequest ("step_out");
314         }
315
316         /* (non-Javadoc)
317          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#run()
318          */
319         public void run() throws DebugException {
320                 sendRequest ("run");
321         }
322
323         /* (non-Javadoc)
324          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stop()
325          */
326         public void stop() throws DebugException {
327                 sendRequest ("stop");
328         }
329
330         /* (non-Javadoc)
331          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#setResponseListerner(org.eclipse.core.runtime.jobs.Job)
332          */
333         public void setResponseListerner(Job listener) {
334 //              fResponseListener=(ResponseListener)listener;;
335         }
336
337         /* (non-Javadoc)
338          * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#startListener()
339          */
340         public void startListener() {
341                 fResponseListener.schedule();
342         }
343
344         public boolean setVarValue(String name, String value) {
345                 int id=-1;
346                 String str=Base64.encodeBytes(value.getBytes());
347                 int len=str.length();
348
349                 try {
350                         id =sendRequest("property_set","-n "+name+" -l "+len + " -- "+str);
351                 } catch (DebugException e) {
352                         // TODO Auto-generated catch block
353                         e.printStackTrace();
354                 }
355                 DebugResponse dr=getResponse(id);
356                 if ((dr.getAttributeValue("success")).equals("1"))
357                         return true;
358                 
359                 return false;
360
361         }
362         
363         public void close() {
364                 fResponseListener.cancel();
365                 try {
366                         fDebugReader.close();           
367                         fDebugWriter.close();
368                         fDebugSocket.close();
369                 } catch (IOException e) {
370                         e.printStackTrace();
371                 }
372                 fIsClosed=true;
373         }
374
375
376         public XDebugVariable getVariableFromNodeA(XDebugStackFrame frame, Node property) {
377                 String address = PHPDebugUtils.getAttributeValue(property, "address");
378                 String varName;
379                 String Name = PHPDebugUtils.getAttributeValue(property,"name");
380                 if ("".equals(Name)) {
381                         varName = address;              
382                 } else {
383                         varName = Name;
384                 }
385
386                 String varEncoding=PHPDebugUtils.getAttributeValue(property,"encoding");
387                 int varNumChildren = 0;
388                 if (PHPDebugUtils.getAttributeValue(property,"numchildren").equals(""))
389                         varNumChildren = 0;
390                 else
391                         varNumChildren=Integer.parseInt(PHPDebugUtils.getAttributeValue(property,"numchildren"));
392
393                 String typeName=PHPDebugUtils.getAttributeValue(property,"type");
394
395                 XDebugVariable variable = new XDebugVariable(typeName, varName);
396                 variable.setEncoding(varEncoding);
397                 variable.setNumChildren(varNumChildren);
398                 XDebugAbstractValue val=null;
399                 try {
400                         val = (XDebugAbstractValue) variable.getValue();
401                 } catch (DebugException e1) {
402                         e1.printStackTrace();
403                 }
404                 if (val.getType()!= XDebugAbstractValue.VALUETYPE_UNINITIALIZED) {
405                         if (variable.hasChildren()) {
406                                 NodeList varNodes = property.getChildNodes();
407                                 val.renderValueString(""+varNodes.getLength());
408                                 IVariable[] variables = new IVariable[varNodes.getLength()];
409                                 for (int i = 0; i<varNodes.getLength(); i++) {
410                                         Node propertyNode = varNodes.item(i);
411                                         variables[i] = getVariableFromNodeA(frame, propertyNode);
412                                 }
413                                 val.setChildVariables(variables);
414                         }else {
415                                 String str="";
416                                 try {
417                                         str=property.getFirstChild().getNodeValue();
418                                 } catch (NullPointerException e) {
419                                         str="";
420                                 }
421                                 if (variable.getEncoding().equals("base64")) {
422                                         if (str.length()!=0)
423                                                 str=new String(Base64.decode(str));
424                                         else
425                                                 str="";
426                                 }
427                                 val.renderValueString(str);
428                         }
429                         
430                         String className=PHPDebugUtils.getAttributeValue(property,"classname");
431                         if(!"".equals(className))
432                                 val.renderValueString(className);
433                 }
434                 return variable;
435                 
436         }
437         
438         private XDebugVariable getVariableFromNode(XDebugStackFrame frame, Node property) {
439                 String varFullName = PHPDebugUtils.getAttributeValue(property, "fullname");
440                 String varName = PHPDebugUtils.getAttributeValue(property, "name");
441                 String varEncoding = PHPDebugUtils.getAttributeValue(property, "encoding");
442                 
443                 int varNumChildren = 0;
444                 if (PHPDebugUtils.getAttributeValue(property, "numchildren").equals("")) {
445                         varNumChildren = 0;
446                 } else {
447                         varNumChildren = Integer.parseInt(PHPDebugUtils.getAttributeValue(property, "numchildren"));
448                 }
449
450                 String typeName = PHPDebugUtils.getAttributeValue(property,"type");
451
452                 XDebugVariable variable = new XDebugVariable(frame,varFullName,varName,typeName);
453                 variable.setEncoding(varEncoding);
454                 variable.setNumChildren(varNumChildren);
455                 XDebugAbstractValue val=null;
456                 try {
457                         val = (XDebugAbstractValue) variable.getValue();
458                 } catch (DebugException e1) {
459                         // TODO Auto-generated catch block
460                         e1.printStackTrace();
461                 }
462                 if (val.getType()!= XDebugAbstractValue.VALUETYPE_UNINITIALIZED) {
463                         if (variable.hasChildren()) {
464                                 NodeList varNodes = property.getChildNodes();
465                                 val.renderValueString(""+varNodes.getLength());
466                                 IVariable[] variables = new IVariable[varNodes.getLength()];
467                                 for (int i = 0; i<varNodes.getLength(); i++) {
468                                         Node propertyNode = varNodes.item(i);
469                                         variables[i] = getVariableFromNode(frame, propertyNode);
470                                 }
471                                 val.setChildVariables(variables);
472                         }else {
473                                 String str="";
474                                 try {
475                                         str=property.getFirstChild().getNodeValue();
476                                 } catch (NullPointerException e) {
477                                         str="";
478                                 }
479                                 if (variable.getEncoding().equals("base64")) {
480                                         if (str.length()!=0)
481                                                 str=new String(Base64.decode(str));
482                                         else
483                                                 str="";
484                                 }
485                                 val.renderValueString(str);
486                         }
487                         
488                         String className=PHPDebugUtils.getAttributeValue(property,"classname");
489                         if(!"".equals(className))
490                                 val.renderValueString(className);
491                 }
492                 return variable;
493                 
494         }
495
496         public IVariable[] getVariables(XDebugStackFrame frame,int level) {
497                 IVariable[] variables = null;
498                 
499                 int idLocal = -1;
500                 try {
501                         idLocal = sendRequest("context_get", "-d " + level);
502                 } catch (DebugException e) {
503                         e.printStackTrace();
504                 }
505                 DebugResponse response = getResponse(idLocal);
506                 Node responseNode = response.getParentNode();
507                 NodeList property = responseNode.getChildNodes();
508                 
509                 int idSuperGlobal = -1;
510                 try {
511                         idSuperGlobal = sendRequest("context_get", "-d " + level + " -c 1");
512                 } catch (DebugException e) {
513                         e.printStackTrace();
514                 }
515                 DebugResponse responseGlobal = getResponse(idSuperGlobal);
516                 Node responseGlobalNode = responseGlobal.getParentNode();
517                 NodeList propertyGlobal = responseGlobalNode.getChildNodes();
518                 
519                 variables = new IVariable[property.getLength() + propertyGlobal.getLength()];
520 //              variables = new IVariable[property.getLength()]; // + propertyGlobal.getLength()];
521                 
522                 int length = property.getLength();
523                 for (int i = 0; i < length; i++) {
524                         Node propertyNode = property.item(i);
525                         XDebugVariable var=getVariableFromNode(frame,propertyNode);
526                         variables[i]=var;
527                 }
528
529                 int globalLength = propertyGlobal.getLength();
530                 for (int k = 0; k < globalLength; k++) {
531                         Node propertyGlobalNode = propertyGlobal.item(k);
532                         XDebugVariable var=getVariableFromNode(frame,propertyGlobalNode);
533                         variables[k + length]=var;
534                 }
535         
536                 return variables;
537         }       
538 }