--- /dev/null
+package net.sourceforge.phpeclipse.xdebug.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugLineBreakpoint;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugThread;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IThread;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+public class DebugConnection {
+
+ private ServerSocket fDebugServerSocket;
+ private DebugResponse lastResponse;
+ private Socket fDebugSocket;
+ private OutputStreamWriter fDebugWriter;
+ private DataInputStream fDebugReader;
+ private ResponseListenerJob fResponseListener;
+
+ // Settings for Debug Process
+ private int fTransactionID=0;
+ private String fileuri = "";
+ private String appID="";
+ private String lastCommand = "";
+ private XDebugTarget fDebugTarget;
+ private HashMap ResponseList;
+
+ public class DebugResponse {
+
+ private Node parentNode;
+ private int fTransactionID=-1;
+ private String fCommand="";
+ private String fStatus;
+ private String fReason;
+ private String fName;
+ private boolean fError;
+
+ public synchronized void setParentNode (String xmlInput){
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder=null;
+ Document doc=null;
+ try {
+ builder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ ByteArrayInputStream InputXMLStream = new ByteArrayInputStream(xmlInput.getBytes());
+
+ try {
+ doc = builder.parse(InputXMLStream);
+ } catch (SAXException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ parentNode=doc.getFirstChild();
+ fName=parentNode.getNodeName();
+ String idStr = getAttributeValue("transaction_id");
+ if (idStr!="")
+ fTransactionID = Integer.parseInt(idStr);
+ fCommand = getAttributeValue("command");
+ fStatus = getAttributeValue("status");
+ fReason = getAttributeValue("reason");
+// notifyAll();
+ }
+
+ public String getAttributeValue (String AttributeName) {
+ String strValue = "";
+ if (parentNode.hasAttributes()) {
+ NamedNodeMap listAttribute = parentNode.getAttributes();
+ Node attribute = listAttribute.getNamedItem(AttributeName);
+ if (attribute !=null)
+ strValue = attribute.getNodeValue();
+ }
+ return strValue;
+ }
+
+ public synchronized Node getParentNode(){
+ return parentNode;
+ }
+
+ public synchronized String getCommand() {
+ return fCommand;
+ }
+ public synchronized String getName() {
+ return fName;
+ }
+
+
+ DebugResponse () {
+ fTransactionID = -1;
+ fCommand = "";
+ fStatus = "";
+ fReason = "";
+ fName= "";
+ }
+
+ DebugResponse (String XMLInput) {
+ setParentNode(XMLInput);
+ }
+
+ public synchronized String getReason() {
+ return fReason;
+ }
+
+ public synchronized String getStatus() {
+ return fStatus;
+ }
+
+ public synchronized int getTransactionID() {
+ return fTransactionID;
+ }
+
+ private synchronized DebugResponse waitforTransactionID(int id) {
+ while (fTransactionID!= id) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+// XDebugCorePlugin.log(IStatus.INFO,"got TransID: "+id);
+
+ return this;
+ }
+
+ public boolean isError() {
+ return fError;
+ }
+
+ public void setError(boolean error) {
+ fError = error;
+ }
+
+ protected synchronized void notifyWait() {
+ notifyAll();
+ }
+ }
+
+
+ /**
+ * Listens to events from the XDebug and fires corresponding
+ * debug events.
+ */
+ class ResponseListenerJob extends Job {
+
+ public ResponseListenerJob() {
+ super("XDebug Event Dispatch");
+ setSystem(true);
+
+ }
+
+
+
+
+ private void checkResponse(DebugResponse response) {
+ Node node=response.getParentNode();
+ if (node.hasChildNodes()) {
+ Node child=node.getFirstChild();
+ if (child.getNodeName().equals("error")) {
+ int code = Integer.parseInt(PHPDebugUtils.getAttributeValue(child, "code"));
+ String text=(child.getFirstChild()).getNodeValue();
+ XDebugCorePlugin.log(IStatus.ERROR,lastCommand+" ERROR "+code+": "+text);
+ lastResponse.setError(true);
+ return;
+ }
+ }
+ lastResponse.setError(false);
+ if (response.getStatus().equals("stopped"))
+ terminated();
+ else if (response.getStatus().equals("break") && response.getReason().equals("ok")){
+ if (response.getCommand().equals("run")) { // breakpoint hit
+ int id=-1;
+ try {
+ id=sendRequest("stack_get");
+ } catch (DebugException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ String InputXML = readData();
+ if (InputXML != null) {
+ XDebugCorePlugin.log(IStatus.INFO, InputXML);
+ lastResponse.setParentNode(InputXML);
+ fDebugTarget.breakpointHit(lastResponse.getParentNode());
+ }
+
+ } else if (response.getCommand().equals("step_into")) { // step_into
+ fDebugTarget.suspended(DebugEvent.STEP_END);
+// XDebugCorePlugin.log(IStatus.INFO,response.getCommand()+" STEP_END sent");
+ } else if (response.getCommand().equals("step_over")) { // step_over
+ fDebugTarget.suspended(DebugEvent.STEP_END);
+// XDebugCorePlugin.log(IStatus.INFO,response.getCommand()+" STEP_END sent");
+ } else if (response.getCommand().equals("step_out")) { // step_over
+ fDebugTarget.suspended(DebugEvent.STEP_END);
+// XDebugCorePlugin.log(IStatus.INFO,response.getCommand()+" STEP_END sent");
+ }
+ } else if (response.getCommand().equals("breakpoint_set")) { // step_over
+ String idStr=response.getAttributeValue("id");
+ if (idStr!="") {
+ int targetID=response.getTransactionID();
+ BreakpointResponseData ResponseData= new BreakpointResponseData(response.getTransactionID(),Integer.parseInt(idStr));
+
+ fDebugTarget.fireDebugResponseEvent(ResponseData);
+ IBreakpoint[] breakpoints=XDebugCorePlugin.getBreakpoints();
+ for(int i=0;i< breakpoints.length;i++) {
+ XDebugLineBreakpoint breakpoint=(XDebugLineBreakpoint)breakpoints[i];
+ try {
+ if (breakpoint.getID()==targetID)
+ breakpoint.setID(Integer.parseInt(idStr));
+ } catch (NumberFormatException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IStatus run(IProgressMonitor monitor) {
+ String InputXML = "";
+ while (!fDebugTarget.isTerminated() && (InputXML != null)) {
+ InputXML = readData();
+ if (InputXML != null) {
+ XDebugCorePlugin.log(IStatus.INFO, InputXML);
+ lastResponse.setParentNode(InputXML);
+ if (lastResponse.getName() == "init") {
+ Node myNode=lastResponse.getParentNode();
+ appID = PHPDebugUtils.getAttributeValue(myNode, "appid");
+ fileuri = PHPDebugUtils.getAttributeValue(myNode, "fileuri");
+// fDebugTarget.started();
+ fDebugTarget.fireCreationEvent();
+ } else if (lastResponse.getName() == "response") {
+ checkResponse(lastResponse);
+ }
+ ResponseList.put(new Integer(lastResponse.getTransactionID()),lastResponse);
+ lastResponse.notifyWait();
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ }
+
+
+ public DebugConnection (XDebugTarget debugTarget,int debugPort) {
+ fDebugTarget=debugTarget;
+ lastResponse=new DebugResponse();
+ ResponseList= new HashMap();
+
+ try {
+ fDebugServerSocket = new ServerSocket(debugPort);
+ fDebugSocket = fDebugServerSocket.accept();
+ fDebugWriter = new OutputStreamWriter(fDebugSocket.getOutputStream(), "UTF8");
+ fDebugReader = new DataInputStream(fDebugSocket.getInputStream());
+// fDebugReader = new BufferedReader(new InputStreamReader(fDebugSocket.getInputStream()));
+
+ } catch (UnknownHostException e) {
+// abort("Unable to connect to PHP Debuger", e);
+ } catch (IOException e) {
+// abort("Unable to connect to PHP Debuger", e);
+ }
+ fResponseListener = new ResponseListenerJob();
+ fResponseListener.schedule();
+
+ }
+
+ private void terminated() {
+ try {
+ fDebugReader.close();
+ fDebugWriter.close();
+ fDebugSocket.close();
+ fDebugServerSocket.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ fDebugTarget.terminated();
+
+ }
+
+ private String readData()
+ {
+ byte byteBuffer[]=null,b;
+ int count=0;
+
+ try {
+ while ( (b =fDebugReader.readByte())!=0)
+ {
+ count=count*10+b-'0';
+// count=count*10+Integer.parseInt(b);
+ }
+// System.out.println(count);
+ byteBuffer = new byte[count];
+ int readCount=0;
+ int attempts=0;
+ while ((count >0) && (attempts <5)) {
+ int rc=fDebugReader.read(byteBuffer,readCount,count);
+ count-=rc;
+ readCount+=rc;
+ attempts++;
+ }
+ if((b= fDebugReader.readByte())!=0) // reads the NULL Byte at the end;
+ System.out.println("NULL-Byte missing!!");
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ if (e instanceof EOFException==false)
+ e.printStackTrace();
+ return null;
+ }
+ return new String(byteBuffer);
+ }
+
+
+ /**
+ * Sends a request to the Debugengine and waits for an OK.
+ *
+ * @param command debug command
+ * @throws DebugException if the request fails
+ */
+
+
+ public int sendRequest(String command) throws DebugException {
+ return sendRequest(command,"");
+ }
+
+ /**
+ * Sends a request to the Debugengine and waits for an OK.
+ *
+ * @param command debug command
+ * @arguments arguments for the command
+ * @throws DebugException if the request fails
+ */
+
+ public synchronized int sendRequest(String command, String arguments) throws DebugException {
+
+// System.out.println(command+" -i "+transactionID+" "+arguments);
+ XDebugCorePlugin.log(IStatus.INFO,command+" -i "+fTransactionID+" "+arguments);
+ synchronized (fDebugSocket) {
+ try {
+ fDebugWriter.write(command);
+ fDebugWriter.write(" -i " + fTransactionID);
+ if (arguments!="")
+ fDebugWriter.write(" " + arguments);
+ fDebugWriter.write(0);
+ fDebugWriter.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return fTransactionID++;
+ }
+
+ public DebugResponse waitforTransID(int id) {
+ if (ResponseList.containsKey(new Integer(id)))
+ {
+// return (DebugResponse)ResponseList.get(new Integer(id));
+ return (DebugResponse)ResponseList.remove(new Integer(id));
+ }
+ else
+ return lastResponse.waitforTransactionID(id);
+ }
+
+ public DebugResponse getResponse(int id) {
+ if (ResponseList.containsKey(new Integer(id)))
+ return (DebugResponse)ResponseList.get(new Integer(id));
+ else
+ return waitforTransID(id);
+ }
+
+
+
+}