PageRenderTime 20ms CodeModel.GetById 11ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 1ms

/tags/1.3b1/src/main/java/flowersinthesand/example/HttpChatServlet.java

http://jquery-stream.googlecode.com/
Java | 152 lines | 114 code | 27 blank | 11 comment | 7 complexity | 4beca9b03ba5e7e5a9548adc53daa047 MD5 | raw file
  1package flowersinthesand.example;
  2
  3import java.io.IOException;
  4import java.io.PrintWriter;
  5import java.util.LinkedHashMap;
  6import java.util.Map;
  7import java.util.UUID;
  8import java.util.concurrent.BlockingQueue;
  9import java.util.concurrent.ConcurrentHashMap;
 10import java.util.concurrent.LinkedBlockingQueue;
 11
 12import javax.servlet.AsyncContext;
 13import javax.servlet.AsyncEvent;
 14import javax.servlet.AsyncListener;
 15import javax.servlet.ServletConfig;
 16import javax.servlet.ServletException;
 17import javax.servlet.http.HttpServlet;
 18import javax.servlet.http.HttpServletRequest;
 19import javax.servlet.http.HttpServletResponse;
 20
 21import com.google.gson.Gson;
 22
 23public class HttpChatServlet extends HttpServlet {
 24
 25	private static final long serialVersionUID = -8823775068689773674L;
 26
 27	/* Common */
 28	private BlockingQueue<String> messages = new LinkedBlockingQueue<String>();
 29	private Thread notifier = new Thread(new Runnable() {
 30		public void run() {
 31			boolean done = false;
 32			while (!done) {
 33				try {
 34					String message = messages.take();
 35					for (AsyncContext asyncContext : asyncContexts.values()) {
 36						try {
 37							// Message
 38							PrintWriter writer = asyncContext.getResponse().getWriter();
 39							writer.print(message.length());
 40							writer.print(";");
 41							writer.print(message);
 42							writer.print(";");
 43							writer.flush();
 44						} catch (Exception e) {
 45							asyncContexts.values().remove(asyncContext);
 46						}
 47					}
 48				} catch (InterruptedException e) {
 49					done = true;
 50				}
 51			}
 52		}
 53	});
 54
 55	@Override
 56	public void init(ServletConfig config) throws ServletException {
 57		super.init(config);
 58		notifier.start();
 59	}
 60
 61	@Override
 62	public void destroy() {
 63		messages.clear();
 64		asyncContexts.clear();
 65		notifier.interrupt();
 66	}
 67
 68	/* HTTP Streaming powered by Servlet 3.0 */
 69	private Map<String, AsyncContext> asyncContexts = new ConcurrentHashMap<String, AsyncContext>();
 70
 71	// GET method is used to open stream
 72	@Override
 73	protected void doGet(HttpServletRequest request, HttpServletResponse response)
 74			throws ServletException, IOException {
 75		// Wrong access
 76		if ("websocket".equalsIgnoreCase(request.getHeader("Upgrade"))) {
 77			response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
 78			return;
 79		}
 80
 81		response.setCharacterEncoding("utf-8");
 82
 83		// Content-Type header
 84		response.setContentType("text/plain");
 85
 86		// Access-Control-Allow-Origin header
 87		response.setHeader("Access-Control-Allow-Origin", "*");
 88
 89		PrintWriter writer = response.getWriter();
 90
 91		// Id
 92		final String id = UUID.randomUUID().toString();
 93		writer.print(id);
 94		writer.print(';');
 95
 96		// Padding
 97		for (int i = 0; i < 1024; i++) {
 98			writer.print(' ');
 99		}
100		writer.print(';');
101		writer.flush();
102
103		final AsyncContext ac = request.startAsync();
104		ac.setTimeout(5 * 60 * 1000);
105		ac.addListener(new AsyncListener() {
106			public void onComplete(AsyncEvent event) throws IOException {
107				asyncContexts.remove(id);
108			}
109
110			public void onTimeout(AsyncEvent event) throws IOException {
111				asyncContexts.remove(id);
112			}
113
114			public void onError(AsyncEvent event) throws IOException {
115				asyncContexts.remove(id);
116			}
117
118			public void onStartAsync(AsyncEvent event) throws IOException {
119
120			}
121		});
122		asyncContexts.put(id, ac);
123	}
124
125	// POST method is used to handle data sent by user through the stream
126	@Override
127	protected void doPost(HttpServletRequest request, HttpServletResponse response)
128			throws ServletException, IOException {
129		request.setCharacterEncoding("utf-8");
130
131		if ("close".equals(request.getHeader("x-jquery-stream-type"))) {
132			AsyncContext ac = asyncContexts.get(request.getHeader("x-jquery-stream-id"));
133			if (ac != null) {
134				ac.complete();
135			}
136
137			return;
138		}
139
140		// Handles data sent from a client
141		Map<String, String> data = new LinkedHashMap<String, String>();
142		data.put("username", request.getParameter("username"));
143		data.put("message", request.getParameter("message"));
144
145		try {
146			messages.put(new Gson().toJson(data));
147		} catch (InterruptedException e) {
148			throw new IOException(e);
149		}
150	}
151
152}