4 package net.sourceforge.phpeclipse.xdebug.core.xdebug;
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;
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;
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;
41 * @author Christian Perkonig
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;
53 public XDebugConnection(Socket debugSocket, DataInputStream reader, OutputStreamWriter writer) {
54 fResponseList = new ResponseList();
55 fDebugWriter = writer;
56 fDebugReader = reader;
57 fDebugSocket = debugSocket;
64 String initString=readData();
65 XDebugCorePlugin.log(IStatus.INFO,initString);
67 int startIdx=initString.indexOf("idekey=\"");
71 int endIdx=initString.indexOf('"',startIdx);
74 fSessionID=initString.substring(startIdx,endIdx);
78 fResponseListener=new ResponseListener(this);
81 protected String readData() {
82 byte byteBuffer[]=null,b;
86 while ((b =fDebugReader.readByte()) != 0) {
87 count = count * 10 + b - '0';
88 // count=count*10+Integer.parseInt(b);
90 // System.out.println(count);
91 byteBuffer = new byte[count];
94 while ((count >0) && (attempts < 50)) {
95 // while ((count >0) && (attempts <5)) {
96 int rc=fDebugReader.read(byteBuffer,readCount,count);
102 } catch (InterruptedException e) {
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)
115 return new String(byteBuffer);
120 * Sends a request to the Debugengine and waits for an OK.
122 * @param command debug command
123 * @throws DebugException if the request fails
127 public int sendRequest(String command) throws DebugException {
128 return sendRequest(command,"");
131 public DebugResponse sendRequestA(String command, String parameter) {
135 result = sendRequest(command, parameter);
136 } catch( DebugException e ){
140 DebugResponse response = getResponse(result);
146 * Sends a request to the Debugengine.
148 * @param command debug command
149 * @arguments arguments for the command
150 * @throws DebugException if the request fails
153 public synchronized int sendRequest(String command, String arguments) throws DebugException {
155 XDebugCorePlugin.log(IStatus.INFO,command+" -i "+fTransactionID+" "+arguments);
156 synchronized (fDebugSocket) {
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();
168 return fTransactionID++;
172 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#featureGet(java.lang.String)
174 public DebugResponse featureGet(String featureName) {
178 id= sendRequest("feature_get","-n "+featureName);
179 } catch (DebugException e) {
180 // TODO Auto-generated catch block
184 DebugResponse response = getResponse(id);
189 public boolean featureSet(String featureName, String value) {
193 id= sendRequest("feature_set","-n "+featureName + " -v " + value);
194 } catch (DebugException e) {
195 // TODO Auto-generated catch block
199 if (getResponse(id).getAttributeValue("success").equals("1") )
205 protected DebugResponse getResponse(int id) {
206 return fResponseList.get(id);
209 protected void addResponse(DebugResponse response, int id) {
210 fResponseList.add(response,id);
215 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#addBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
217 public void addBreakpoint(IBreakpoint breakpoint, IPath filePath) throws DebugException {
219 if (breakpoint.isEnabled()) {
220 IMarker marker = breakpoint.getMarker();
221 if (marker != null) {
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");
229 if (!"".equals(bpid))
230 marker.setAttribute(XDebugLineBreakpoint.BREAKPOINT_ID,Integer.parseInt(bpid));
232 } catch (CoreException e) {
233 XDebugCorePlugin.log(IStatus.INFO,"Exception set break point");
237 } catch (CoreException e) {
238 XDebugCorePlugin.log(IStatus.INFO,"Exception in breakpoint");
243 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#removeBreakpoint(int)
245 public void removeBreakpoint(IBreakpoint breakpoint) throws DebugException {
247 int id =((XDebugLineBreakpoint)breakpoint).getID();
249 sendRequest("breakpoint_remove","-d "+id);
250 } catch (CoreException e) {
255 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#getStackFrames(net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread)
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));
272 frame.setType(PHPDebugUtils.getAttributeValue(stackNode,"type"));
273 String fileName=PHPDebugUtils.unescapeString(PHPDebugUtils.getAttributeValue(stackNode,"filename"));
274 String lineNo=PHPDebugUtils.getAttributeValue(stackNode,"lineno");
276 if (!"".equals(lineNo))
277 frame.setLineNumber(Integer.parseInt(lineNo));
279 frame.setWhere(PHPDebugUtils.getAttributeValue(stackNode,"where"));
282 frame.setFullName(new URL(fileName));
283 } catch (MalformedURLException e) {
287 frame.incrementStepCounter();
289 theFrames[i] = frame;
296 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepOver()
298 public void stepOver() throws DebugException {
299 sendRequest ("step_over");
303 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepInto()
305 public void stepInto() throws DebugException {
306 sendRequest("step_into");
310 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stepOut()
312 public void stepOut() throws DebugException {
313 sendRequest ("step_out");
317 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#run()
319 public void run() throws DebugException {
324 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#stop()
326 public void stop() throws DebugException {
327 sendRequest ("stop");
331 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#setResponseListerner(org.eclipse.core.runtime.jobs.Job)
333 public void setResponseListerner(Job listener) {
334 // fResponseListener=(ResponseListener)listener;;
338 * @see net.sourceforge.phpeclipse.xdebug.core.IDebugConnection#startListener()
340 public void startListener() {
341 fResponseListener.schedule();
344 public boolean setVarValue(String name, String value) {
346 String str=Base64.encodeBytes(value.getBytes());
347 int len=str.length();
350 id =sendRequest("property_set","-n "+name+" -l "+len + " -- "+str);
351 } catch (DebugException e) {
352 // TODO Auto-generated catch block
355 DebugResponse dr=getResponse(id);
356 if ((dr.getAttributeValue("success")).equals("1"))
363 public void close() {
364 fResponseListener.cancel();
366 fDebugReader.close();
367 fDebugWriter.close();
368 fDebugSocket.close();
369 } catch (IOException e) {
376 public XDebugVariable getVariableFromNodeA(XDebugStackFrame frame, Node property) {
377 String address = PHPDebugUtils.getAttributeValue(property, "address");
379 String Name = PHPDebugUtils.getAttributeValue(property,"name");
380 if ("".equals(Name)) {
386 String varEncoding=PHPDebugUtils.getAttributeValue(property,"encoding");
387 int varNumChildren = 0;
388 if (PHPDebugUtils.getAttributeValue(property,"numchildren").equals(""))
391 varNumChildren=Integer.parseInt(PHPDebugUtils.getAttributeValue(property,"numchildren"));
393 String typeName=PHPDebugUtils.getAttributeValue(property,"type");
395 XDebugVariable variable = new XDebugVariable(typeName, varName);
396 variable.setEncoding(varEncoding);
397 variable.setNumChildren(varNumChildren);
398 XDebugAbstractValue val=null;
400 val = (XDebugAbstractValue) variable.getValue();
401 } catch (DebugException e1) {
402 e1.printStackTrace();
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);
413 val.setChildVariables(variables);
417 str=property.getFirstChild().getNodeValue();
418 } catch (NullPointerException e) {
421 if (variable.getEncoding().equals("base64")) {
423 str=new String(Base64.decode(str));
427 val.renderValueString(str);
430 String className=PHPDebugUtils.getAttributeValue(property,"classname");
431 if(!"".equals(className))
432 val.renderValueString(className);
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");
443 int varNumChildren = 0;
444 if (PHPDebugUtils.getAttributeValue(property, "numchildren").equals("")) {
447 varNumChildren = Integer.parseInt(PHPDebugUtils.getAttributeValue(property, "numchildren"));
450 String typeName = PHPDebugUtils.getAttributeValue(property,"type");
452 XDebugVariable variable = new XDebugVariable(frame,varFullName,varName,typeName);
453 variable.setEncoding(varEncoding);
454 variable.setNumChildren(varNumChildren);
455 XDebugAbstractValue val=null;
457 val = (XDebugAbstractValue) variable.getValue();
458 } catch (DebugException e1) {
459 // TODO Auto-generated catch block
460 e1.printStackTrace();
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);
471 val.setChildVariables(variables);
475 str=property.getFirstChild().getNodeValue();
476 } catch (NullPointerException e) {
479 if (variable.getEncoding().equals("base64")) {
481 str=new String(Base64.decode(str));
485 val.renderValueString(str);
488 String className=PHPDebugUtils.getAttributeValue(property,"classname");
489 if(!"".equals(className))
490 val.renderValueString(className);
496 public IVariable[] getVariables(XDebugStackFrame frame,int level) {
497 IVariable[] variables = null;
501 idLocal = sendRequest("context_get", "-d " + level);
502 } catch (DebugException e) {
505 DebugResponse response = getResponse(idLocal);
506 Node responseNode = response.getParentNode();
507 NodeList property = responseNode.getChildNodes();
509 int idSuperGlobal = -1;
511 idSuperGlobal = sendRequest("context_get", "-d " + level + " -c 1");
512 } catch (DebugException e) {
515 DebugResponse responseGlobal = getResponse(idSuperGlobal);
516 Node responseGlobalNode = responseGlobal.getParentNode();
517 NodeList propertyGlobal = responseGlobalNode.getChildNodes();
519 variables = new IVariable[property.getLength() + propertyGlobal.getLength()];
520 // variables = new IVariable[property.getLength()]; // + propertyGlobal.getLength()];
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);
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;