3d6396a69d65261d441d39d55ddaa20a748bf4f0
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / core / XDebugProxy.java
1 package net.sourceforge.phpeclipse.xdebug.core;
2
3 import java.io.DataInputStream;
4 import java.io.IOException;
5 import java.io.OutputStreamWriter;
6 import java.io.UnsupportedEncodingException;
7 import java.net.ServerSocket;
8 import java.net.Socket;
9 import java.net.UnknownHostException;
10
11 import net.sourceforge.phpeclipse.xdebug.core.xdebug.XDebugConnection;
12
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.core.runtime.ISafeRunnable;
15 import org.eclipse.core.runtime.IStatus;
16 import org.eclipse.core.runtime.Platform;
17 import org.eclipse.core.runtime.Status;
18 import org.eclipse.core.runtime.jobs.Job;
19 import org.eclipse.debug.core.DebugException;
20 import org.eclipse.debug.core.IDebugEventFilter;
21 import org.eclipse.debug.core.IDebugEventSetListener;
22
23 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
24
25 public class XDebugProxy {
26         private XDebugTarget fTarget;
27
28         protected String fInitString;
29         protected String fIdeKey;
30
31         protected AbstractDebugConnection fConnection;
32
33         class ProxyListenerJob extends Job {
34                 public ProxyListenerJob() {
35                         super("XDebug Proxy Connection Dispatch");
36                         setSystem(true);
37                         
38                 }
39                 
40                 /* (non-Javadoc)
41                  * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
42                  */
43                 protected IStatus run(IProgressMonitor monitor) {
44                         boolean timeout;
45                         boolean error;
46                         Socket socket=null;
47                         DataInputStream reader=null;
48                         OutputStreamWriter writer=null;
49                         
50                         while (!fTerminate) {
51                                 timeout = false;
52                                 error = false;
53                                 socket=null;
54                                 reader=null;
55                                 writer=null;
56                                 if (monitor.isCanceled()) return Status.CANCEL_STATUS;
57                                 try {
58                                         socket = fProxyServerSocket.accept();
59                                 } catch (java.net.SocketTimeoutException e) {
60                                         timeout=true;
61                                 } catch (IOException e) {
62                                         error=true;
63 //                                      e.printStackTrace();
64                                 }
65                                 if (!(timeout || error)) {
66                                         XDebugCorePlugin.log(IStatus.INFO,"Proxy: someone tries to connect");
67                                         
68                                         try {
69                                                 writer = new OutputStreamWriter(socket.getOutputStream(), "UTF8");
70                                                 reader = new DataInputStream(socket.getInputStream()); 
71                                         } catch (UnsupportedEncodingException e) {
72                                                 // TODO Auto-generated catch block
73                                                 e.printStackTrace();
74                                         } catch (IOException e) {
75                                                 // TODO Auto-generated catch block
76                                                 e.printStackTrace();
77                                         }
78                                         fConnection=(AbstractDebugConnection) new XDebugConnection(socket,reader,writer);       
79                                         if (fConnection.isInitialized()) {
80                                                 fIdeKey=fConnection.getSessionID();
81                                                 XDebugCorePlugin.log(IStatus.INFO,"<init idekey \""+fIdeKey+"\">");
82                                         
83                                                 fireProxyEvent();
84                                         }
85                                 }
86                                 
87                         }
88                         return Status.OK_STATUS;
89                 }
90         }
91         
92         /**
93          * Filters and dispatches events in a safe runnable to handle any
94          * exceptions.
95          */
96         class EventNotifier implements ISafeRunnable {
97                 
98                 private IProxyEventListener fListener;
99                 
100                 /**
101                  * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
102                  */
103                 public void handleException(Throwable exception) {
104                         IStatus status = new Status(IStatus.ERROR, XDebugCorePlugin.getUniqueIdentifier(), IStatus.ERROR, "An exception occurred while dispatching proxy", exception); //$NON-NLS-1$
105                         XDebugCorePlugin.log(status);
106                 }
107
108                 /**
109                  * @see org.eclipse.core.runtime.ISafeRunnable#run()
110                  */
111                 public void run() throws Exception {
112                         
113                         fListener.handleProxyEvent(fIdeKey, fInitString, fConnection);
114                 }
115                 
116                 /**
117                  * Filter and dispatch the given events. If an exception occurs in one
118                  * listener, events are still fired to subsequent listeners.
119                  * 
120                  * @param events debug events
121                  */
122                 public void dispatch() {
123                         fListener = (IProxyEventListener) getEventListener(fIdeKey);
124                         if (fListener==null) {     // no listener is found so start the script
125                                 try {
126                                         fConnection.run();
127                                 } catch (DebugException e) {
128                                         // TODO Auto-generated catch block
129                                         e.printStackTrace();
130                                 }
131                         } else
132                                 Platform.run(this);
133                         fListener = null;
134                 }
135
136         }
137
138
139         private ServerSocket fProxyServerSocket;
140         private ProxyListenerJob fProxyListener;
141         private boolean fTerminate;
142         private int fProxyPort;
143         private ListenerMap fEventListeners;
144         private boolean fIsRunning;
145         
146         
147         public XDebugProxy (int port) {
148                 fProxyPort=port;
149         }
150         
151         public void setTarget( XDebugTarget Target ) {
152                 fTarget = Target;
153         }
154         
155         public XDebugTarget getTarget() {
156                 return fTarget;
157         }
158         
159         public void start() {
160                 if (fIsRunning)
161                         return;
162                 try {
163                         fProxyServerSocket = new ServerSocket(fProxyPort);
164                         // set 5sek as timeout 
165                         fProxyServerSocket.setSoTimeout(5000);
166                         XDebugCorePlugin.log(IStatus.INFO,"Proxy listens on port "+fProxyPort);
167
168 //                      fDebugReader = new BufferedReader(new InputStreamReader(fDebugSocket.getInputStream()));
169                         
170                 } catch (UnknownHostException e) {
171                         e.printStackTrace();
172 //                      abort("Unable to connect to PHP Debuger", e);
173                 } catch (IOException e) {
174                         e.printStackTrace();
175 //                      abort("Unable to connect to PHP Debuger", e);
176                 }
177                 fTerminate=false;
178                 fProxyListener = new ProxyListenerJob();
179                 fProxyListener.schedule();
180                 fIsRunning=true;
181                 
182         }
183         
184 /*      public void stop() {
185                 if (!fIsRunning)
186                         return;
187                 fTerminate=true;
188                 fProxyListener.cancel();
189                 try {
190                         fProxyServerSocket.close();
191                 } catch (IOException e) {
192                         // TODO Auto-generated catch block
193                         e.printStackTrace();
194                 }
195                 fIsRunning = false;
196                 XDebugCorePlugin.log(IStatus.INFO,"Proxy stopped");
197
198         }*/
199         
200         public void stop() {
201                 if (fIsRunning) {
202                         fProxyListener.cancel();
203                         fTerminate = true;
204                         try {
205                                 fProxyServerSocket.close();
206                         } catch (IOException e) {
207                                 e.printStackTrace();
208                         }
209                         fIsRunning = false;
210                         XDebugCorePlugin.log(IStatus.INFO,"Proxy stopped");
211                 }
212         }
213
214         /**
215          * Adds the given listener to the collection of registered proxy
216          * event listeners. Has no effect if an identical listener is already
217          * registered.
218          *
219          * @param listener the listener to add
220
221          */
222         public void addProxyEventListener(IProxyEventListener listener, String key) {
223                 if (fEventListeners == null) {
224                         fEventListeners = new ListenerMap(5);
225                 }
226                 fEventListeners.add(listener, key);
227         }
228         
229         /**
230          * Removes the given listener from the collection of registered proxy
231          * event listeners. Has no effect if an identical listener is not already
232          * registered.
233          *
234          * @param listener the listener to remove
235          */
236         public void removeProxyEventListener(IProxyEventListener listener,String key) {
237                 if (fEventListeners != null) {
238                         fEventListeners.remove(listener,key);
239                 }
240         }       
241         
242         /**
243          * Notifies all registered proxy event set listeners of the given
244          * proxy events. Events which are filtered by a registered debug event
245          * filter are not fired.
246          * 
247          * @param events array of debug events to fire
248          * @see IDebugEventFilter
249          * @see IDebugEventSetListener
250          * @since 2.0
251          */
252         public void fireProxyEvent() {
253                 EventNotifier fNotifier = new EventNotifier();
254                 fNotifier.dispatch();
255         }
256         
257         /**
258          * Returns the collection of registered proxy event listeners
259          * 
260          * @return list of registered proxy event listeners, instances
261          *  of <code>IProxyEventListeners</code>
262          */
263         /*private Map getEventListeners() {
264                 return fEventListeners.getListeners();
265         }*/
266         
267         private Object getEventListener(String ideKey) {
268                 return fEventListeners.getListener(ideKey);
269         }
270                 
271         /**
272          * @return Returns the fProxyPort.
273          */
274         public int getProxyPort() {
275                 return fProxyPort;
276         }
277
278         public boolean isRunning() {
279                 return fIsRunning;
280         }
281 }