1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.osgi.equinoxtools.console;
20
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.util.HashMap;
24 import java.util.LinkedList;
25 import java.util.Map;
26 import java.util.Queue;
27
28 import javax.servlet.ServletException;
29 import javax.servlet.http.HttpServlet;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.eclipse.jetty.continuation.Continuation;
34 import org.eclipse.jetty.continuation.ContinuationSupport;
35 import org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator;
36 import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
37 import org.eclipse.osgi.framework.console.ConsoleSession;
38
39
40
41
42
43 public class EquinoxConsoleContinuationServlet extends HttpServlet implements OnFlushListener
44 {
45
46 private static final long serialVersionUID = 1L;
47 private Map<String,ConsoleUser> _consoleUsers = new HashMap<String, ConsoleUser>();
48 private WebConsoleSession _consoleSession;
49 private EquinoxChattingSupport _support;
50
51
52
53
54 public EquinoxConsoleContinuationServlet()
55 {
56
57 }
58
59
60
61 public EquinoxConsoleContinuationServlet(WebConsoleSession consoleSession, EquinoxChattingSupport support)
62 {
63 _consoleSession = consoleSession;
64 _support = support;
65 }
66 @Override
67 public void init() throws ServletException
68 {
69 if (_consoleSession == null)
70 {
71 _consoleSession = new WebConsoleSession();
72 WebEquinoxToolsActivator.getContext().registerService(ConsoleSession.class.getName(), _consoleSession, null);
73 }
74 if (_support == null)
75 {
76 _support = new EquinoxChattingSupport(_consoleSession);
77 }
78 _consoleSession.addOnFlushListener(this);
79 }
80 @Override
81 public void destroy()
82 {
83 _consoleSession.removeOnFlushListener(this);
84 }
85
86
87
88 @Override
89 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
90 {
91 if (request.getParameter("action")!=null)
92 doPost(request,response);
93 else
94 response.sendRedirect(request.getContextPath() + request.getServletPath()
95 + (request.getPathInfo() != null ? request.getPathInfo() : "") + "/index.html");
96 }
97
98
99 @Override
100 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
101 {
102
103 String action = request.getParameter("action");
104 String message = request.getParameter("message");
105 String username = request.getParameter("user");
106
107 if (action.equals("join"))
108 join(request,response,username);
109 else if (action.equals("poll"))
110 poll(request,response,username);
111 else if (action.equals("chat"))
112 chat(request,response,username,message);
113 }
114
115 private synchronized void join(HttpServletRequest request,HttpServletResponse response,String username)
116 throws IOException
117 {
118 ConsoleUser member = new ConsoleUser(username);
119 _consoleUsers.put(username,member);
120 response.setContentType("text/json;charset=utf-8");
121 PrintWriter out=response.getWriter();
122 out.print("{action:\"join\"}");
123 }
124
125 private synchronized void poll(HttpServletRequest request,HttpServletResponse response,String username)
126 throws IOException
127 {
128 ConsoleUser member = _consoleUsers.get(username);
129 if (member==null)
130 {
131 response.sendError(503);
132 return;
133 }
134
135 synchronized(member)
136 {
137 if (member.getMessageQueue().size()>0)
138 {
139
140 response.setContentType("text/json;charset=utf-8");
141 StringBuilder buf=new StringBuilder();
142
143 buf.append("{\"action\":\"poll\",");
144 buf.append("\"from\":\"");
145 buf.append(member.getMessageQueue().poll());
146 buf.append("\",");
147
148 String message = member.getMessageQueue().poll();
149 int quote=message.indexOf('"');
150 while (quote>=0)
151 {
152 message=message.substring(0,quote)+'\\'+message.substring(quote);
153 quote=message.indexOf('"',quote+2);
154 }
155 buf.append("\"chat\":\"");
156 buf.append(message);
157 buf.append("\"}");
158 byte[] bytes = buf.toString().getBytes("utf-8");
159 response.setContentLength(bytes.length);
160 response.getOutputStream().write(bytes);
161 }
162 else
163 {
164 Continuation continuation = ContinuationSupport.getContinuation(request);
165 if (continuation.isInitial())
166 {
167
168 continuation.setTimeout(20000);
169 continuation.suspend();
170 member.setContinuation(continuation);
171 }
172 else
173 {
174
175 response.setContentType("text/json;charset=utf-8");
176 PrintWriter out=response.getWriter();
177 out.print("{action:\"poll\"}");
178 }
179 }
180 }
181 }
182
183 private synchronized void chat(HttpServletRequest request,HttpServletResponse response,String username,String message)
184 throws IOException
185 {
186 if (!message.endsWith("has joined!"))
187 {
188 _consoleSession.processCommand(message, false);
189 }
190
191 onFlush();
192
193 response.setContentType("text/json;charset=utf-8");
194 PrintWriter out=response.getWriter();
195 out.print("{action:\"chat\"}");
196 }
197
198
199
200
201 public void onFlush()
202 {
203 Queue<String> pendingConsoleOutputMessages = _support.processConsoleOutput(true, this);
204 for (ConsoleUser m:_consoleUsers.values())
205 {
206 synchronized (m)
207 {
208
209
210 m.getMessageQueue().addAll(pendingConsoleOutputMessages);
211
212
213 if (m.getContinuation()!=null)
214 {
215 m.getContinuation().resume();
216 m.setContinuation(null);
217 }
218 }
219 }
220 }
221
222 class ConsoleUser
223 {
224 private String _name;
225 private Continuation _continuation;
226 private Queue<String> _queue = new LinkedList<String>();
227
228 public ConsoleUser(String name)
229 {
230 _name = name;
231 }
232
233 public String getName()
234 {
235 return _name;
236 }
237
238 public void setContinuation(Continuation continuation)
239 {
240 _continuation = continuation;
241 }
242
243 public Continuation getContinuation()
244 {
245 return _continuation;
246 }
247 public Queue<String> getMessageQueue()
248 {
249 return _queue;
250 }
251
252 }
253 }