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