1) Improvements for the XDebug plugin.
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / core / xdebug / XDebugConnection.java
1 package net.sourceforge.phpeclipse.xdebug.core.xdebug;
2
3 import java.io.DataInputStream;
4 import java.io.EOFException;
5 import java.io.IOException;
6 import java.io.OutputStreamWriter;
7 import java.io.UnsupportedEncodingException;
8 import java.net.Socket;
9
10 import net.sourceforge.phpeclipse.xdebug.core.Base64;
11 import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
12 import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
13
14 import org.eclipse.core.runtime.IStatus;
15
16 /**
17  * @author Christian Perkonig
18  *
19  */
20 public class XDebugConnection {
21         private int fTransactionID;
22         private Socket fDebugSocket;
23         private OutputStreamWriter fDebugWriter;
24         private DataInputStream fDebugReader;
25         private boolean fInitialized;
26         private boolean fIsClosed;
27         private String fSessionID;
28         
29         public String getSessionID() {
30                 return fSessionID;
31         }
32         
33         public boolean isInitialized() {
34                 return fInitialized;
35         }
36         
37         public boolean isClosed() {
38                 return fIsClosed;
39         }
40
41         public XDebugConnection(Socket debugSocket) {
42                 fDebugSocket = debugSocket;
43                 fTransactionID = 0;
44                 fInitialized = false;
45                 try {
46                         fDebugWriter = new OutputStreamWriter(debugSocket.getOutputStream(), "UTF8");
47                         fDebugReader = new DataInputStream(debugSocket.getInputStream()); 
48                 } catch (UnsupportedEncodingException e) {
49                         e.printStackTrace();
50                 } catch (IOException e) {
51                         e.printStackTrace();
52                 }
53
54                 fIsClosed = false;
55
56                 String initString = readData();
57                 XDebugCorePlugin.log(IStatus.INFO,initString);
58
59                 int startIdx = initString.indexOf("idekey=\"");
60                 if (startIdx == -1)
61                         return;
62                 startIdx += 8;
63                 int endIdx=initString.indexOf('"',startIdx);
64                 if (endIdx==-1)
65                         return;
66                 fSessionID = initString.substring(startIdx,endIdx);
67                 fInitialized = true;
68         }
69         
70         protected String readData()     {
71                 if (fIsClosed)
72                         return null;
73                 
74         byte byteBuffer[]=null,b;
75                 int count=0;
76                 
77                 try {
78                         while ((b =fDebugReader.readByte()) != 0) {
79                                 count = count * 10 + b - '0';
80                         }
81                         byteBuffer = new byte[count];
82                         int readCount=0;
83                         int attempts=0;
84                         while ((count >0) && (attempts <5)) {
85                                 int rc=fDebugReader.read(byteBuffer,readCount,count);
86                                 count-=rc;
87                                 readCount+=rc;
88                                 if (count>65530)
89                                         try {
90                                                 Thread.sleep(200);
91                                         } catch (InterruptedException e) {
92                                         }
93                                 else
94                                         attempts++;
95                         }
96                         
97                         fDebugReader.readFully(byteBuffer,readCount,count);
98                         
99                         if((b= fDebugReader.readByte())!=0) // reads the NULL Byte at the end;
100                                 System.out.println("NULL-Byte missing!!"); 
101                 } catch (IOException e) {
102                         if (e instanceof EOFException == false) {
103                                 if (!fIsClosed) {
104 //                                      e.printStackTrace();
105                                 }
106                         }
107                         return null;
108                 }
109                 return new String(byteBuffer);
110         }
111         
112         private /*XDebugResponse*/ int sendRequest(String command, String arguments) {
113                 return _sendRequest(command, arguments);
114         }
115
116         private synchronized int _sendRequest(String command, String arguments) {
117                 if (fDebugSocket == null) {
118                         return 0;
119                 }
120                 
121                 XDebugCorePlugin.log(IStatus.INFO,command+" -i "+fTransactionID+" "+arguments);
122                 synchronized (fDebugSocket) {
123                         try {
124                                 fDebugWriter.write(command);
125                                 fDebugWriter.write(" -i " + fTransactionID);
126                                 if (!"".equals(arguments))
127                                         fDebugWriter.write(" " + arguments);
128                                 fDebugWriter.write(0);
129                                 fDebugWriter.flush();
130                         } catch (IOException e) {
131                                 e.printStackTrace();
132                 }
133                 }
134
135                 return fTransactionID++;
136         }
137
138         public /*XDebugResponse*/ int eval(String Expression) {
139                 String encoded = Base64.encodeBytes(Expression.getBytes());
140                 
141                 return sendRequest("eval", "-- "+encoded);
142         }
143
144         public /*XDebugResponse*/ int featureGet(String featureName) {
145                 return sendRequest("feature_get","-n "+featureName);
146         }
147
148         public int  featureSet(String featureName, String value) {
149                 return sendRequest("feature_set","-n "+featureName + " -v " + value);
150         }
151
152         public /*XDebugResponse*/ int  breakpointSetOld(String file, int lineNumber) {
153                 String arg = "-t line -f file://"+PHPDebugUtils.escapeString(file)+" -n " + lineNumber;
154                 return sendRequest("breakpoint_set", arg);              
155         }
156         
157         public /*XDebugResponse*/ int  breakpointSet(String file, int lineNumber, int hitCount) {
158                 String arg = "-t line -f file://"+PHPDebugUtils.escapeString(file)+" -n " + lineNumber;
159                 if (hitCount > 0) {
160                         arg += " -h " + hitCount;       
161                 }
162                 return sendRequest("breakpoint_set", arg);              
163         }
164         
165         public int  breakpointGet(int id) {
166                 String arg = "-d " + id;
167                 
168                 return sendRequest("breakpoint_get", arg);              
169         }
170         
171         public /*XDebugResponse*/ int  breakpointRemove(int id) {
172                 return sendRequest("breakpoint_set", "-d " + id);
173         }
174
175         public /*XDebugResponse*/ int  stackGet(/*int Level*/) {
176                 return sendRequest("stack_get", "");                    
177         }
178         
179         public void stepOver() {
180                 sendRequest("step_over", "");
181         }
182
183         public void stepInto() {
184                 sendRequest("step_into", "");
185         }
186
187         public void stepOut() {
188                 sendRequest("step_out", "");
189         }
190
191         public void run() {
192                 sendRequest("run", "");
193         }
194
195         public void stop() {
196                 sendRequest("stop", "");
197         }
198
199         public /*XDebugResponse*/ int  propertySet(String Name, String Value) {
200                 String str = Base64.encodeBytes(Value.getBytes());
201                 int len = str.length();
202
203                 return sendRequest("property_set", "-n " + Name + " -d 0 -l " + len + " -- " + str);
204         }
205
206         public /*XDebugResponse*/ int  contextGet(int Level, int Type) {
207                 return sendRequest("context_get", "-d " + Level + " -c " + Type);
208         }
209
210         public int setVarValue(String Name, String Value) {
211                 return propertySet(Name, Value);
212         }
213         
214         public void close() {
215                 if (!fIsClosed) {
216                         fIsClosed = true;
217                         try {
218                                 fDebugSocket.close();
219                                 fDebugReader.close();
220                                 //fDebugReader = null;
221                                 fDebugWriter.close();
222                         } catch (IOException e) {
223                                 e.printStackTrace();
224                         }
225                 }
226         }       
227 }