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