import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.CometEvent;
public class ChatServlet extends javax.servlet.http.HttpServlet implements org.apache.catalina.CometProcessor {
protected ConcurrentHashMap connections = new ConcurrentHashMap();
protected ConcurrentHashMap pendingClose = new ConcurrentHashMap();
protected final MessageSender messageSender = new MessageSender();
public void init() throws ServletException {
Thread messageSenderThread = new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
messageSenderThread.setDaemon(true);
messageSenderThread.start();
}
public void destroy() {
connections.clear();
messageSender.stop();
}
private String getSessionCookie(HttpServletRequest request, HttpServletResponse response) {
String sessionID = null;
if ( request.getCookies() != null) {
int numCookies = request.getCookies().length;
Cookie cookies[] = request.getCookies();
for (int i = 0; i < numCookies; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("JSESSIONID")) {
sessionID = cookie.getValue();
break;
}
}
}
if (sessionID == null ) {
Cookie sessionCookie = new Cookie("JSESSIONID", request.getSession(true).getId());
sessionID = sessionCookie.getValue();
sessionCookie.setMaxAge(1800);
sessionCookie.setPath("/chat");
response.addCookie(sessionCookie);
}
return sessionID;
}
public void event(CometEvent event)
throws IOException, ServletException {
HttpServletRequest request = event.getHttpServletRequest();
HttpServletResponse response = event.getHttpServletResponse();
String sessionID = getSessionCookie(request, response);
if (event.getEventType() == CometEvent.EventType.BEGIN) {
log("Begin for session " + sessionID);
String action = request.getParameter("action");
if (action.equals("chat")) {
String message = request.getParameter("msg");
messageSender.send(message);
PrintWriter writer = response.getWriter();
writer.println("");
writer.println("JSP Chat");
writer.println("Message Sent");
writer.flush();
response.flushBuffer();
event.close();
} else {
CometEvent e = connections.get(sessionID);
if (e != null) {
synchronized(e) {
log ("Booting old connection");
pendingClose.put(e, e);
e.close();
}
}
event.setTimeout(10*1000);
connections.put(sessionID, event);
}
} else if (event.getEventType() == CometEvent.EventType.ERROR) {
log("ERROR for session " + sessionID);
connections.remove(sessionID);
event.close();
} else if (event.getEventType() == CometEvent.EventType.END) {
log("End for session " + sessionID);
if ( pendingClose.containsKey(event) ) {
CometEvent pender = pendingClose.get(event);
synchronized(pender){
pendingClose.remove(event);
}
} else {
connections.remove(sessionID);
}
event.close();
} else if (event.getEventType() == CometEvent.EventType.READ) {
log("Read for session ");
}
}
private class MessageSender implements Runnable {
private boolean running = true;
private final ArrayList messages = new ArrayList();
public MessageSender() {
}
public void stop() {
running = false;
}
public void send(String message) {
synchronized (messages) {
messages.add(message);
messages.notifyAll();
}
}
public void run() {
while (running) {
synchronized (messages) {
if (messages.size() == 0) {
try {
messages.wait();
} catch (InterruptedException e) {/* Ignore */ }
}
}
String[] pendingMessages;
synchronized (messages) {
pendingMessages = new String[0];
messages.clear();
for (CometEvent event : connections.values()){
try {
if (event != null ) {
synchronized(event) {
HttpServletResponse response = event.getHttpServletResponse();
PrintWriter writer = response.getWriter();
for (int j = 0; j < pendingMessages.length; j++) {
writer.println(pendingMessages[j]);
}
writer.flush();
response.flushBuffer();
event.close();
}
}
} catch (IOException e) {
log("IOExeption sending message", e);
}
}
}
}
}
}
}