package net.zschech.gwt.chat.server;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpSession;
import net.zschech.gwt.chat.client.ChatException;
import net.zschech.gwt.chat.client.ChatMessage;
import net.zschech.gwt.chat.client.ChatService;
import net.zschech.gwt.chat.client.StatusUpdate;
import net.zschech.gwt.chat.client.StatusUpdate.Status;
import net.zschech.gwt.comet.server.CometServlet;
import net.zschech.gwt.comet.server.CometSession;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* A simple implementation of {@link ChatService} which maintains all its state in memory.
*
* @author Richard Zschech
*/
public class ChatServiceImpl extends RemoteServiceServlet implements ChatService {
/**
* A mapping of user names to CometSessions used for routing messages.
*/
private ConcurrentMap<String, CometSession> users = new ConcurrentHashMap<String, CometSession>();
@Override
public String getUsername() throws ChatException {
// check if there is a HTTP session setup.
HttpSession httpSession = getThreadLocalRequest().getSession(false);
if (httpSession == null) {
return null;
}
// return the user name
return (String) httpSession.getAttribute("username");
}
/**
* @see net.zschech.gwt.chat.client.ChatService#login(java.lang.String)
*/
@Override
public void login(String username) throws ChatException {
// Get or create the HTTP session for the browser
HttpSession httpSession = getThreadLocalRequest().getSession();
// Get or create the Comet session for the browser
CometSession cometSession = CometServlet.getCometSession(httpSession);
// Remember the user name for the
httpSession.setAttribute("username", username);
// setup the mapping of user names to CometSessions
if (users.putIfAbsent(username, cometSession) != null) {
// some one else has already logged in with this user name
httpSession.invalidate();
throw new ChatException("User: " + username + " already logged in");
}
}
/**
* @see net.zschech.gwt.chat.client.ChatService#logout(java.lang.String)
*/
@Override
public void logout(String username) throws ChatException {
// check if there is a HTTP session setup.
HttpSession httpSession = getThreadLocalRequest().getSession(false);
if (httpSession == null) {
throw new ChatException("User: " + username + " is not logged in: no http session");
}
// check if there is a Comet session setup. In a larger application the HTTP session may have been
// setup via other means.
CometSession cometSession = CometServlet.getCometSession(httpSession, false);
if (cometSession == null) {
throw new ChatException("User: " + username + " is not logged in: no comet session");
}
// check the user name parameter matches the HTTP sessions user name
if (!username.equals(httpSession.getAttribute("username"))) {
throw new ChatException("User: " + username + " is not logged in on this session");
}
// remove the mapping of user name to CometSession
users.remove(username, cometSession);
httpSession.invalidate();
}
/**
* @see net.zschech.gwt.chat.client.ChatService#send(java.lang.String)
*/
@Override
public void send(String message) throws ChatException {
// check if there is a HTTP session setup.
HttpSession httpSession = getThreadLocalRequest().getSession(false);
if (httpSession == null) {
throw new ChatException("not logged in: no http session");
}
// get the user name for the HTTP session.
String username = (String) httpSession.getAttribute("username");
if (username == null) {
throw new ChatException("not logged in: no http session username");
}
// create the chat message
ChatMessage chatMessage = new ChatMessage();
chatMessage.setUsername(username);
chatMessage.setMessage(message);
for (Map.Entry<String, CometSession> entry : users.entrySet()) {
entry.getValue().enqueue(chatMessage);
}
}
@Override
public void setStatus(Status status) throws ChatException {
// check if there is a HTTP session setup.
HttpSession httpSession = getThreadLocalRequest().getSession(false);
if (httpSession == null) {
throw new ChatException("not logged in: no http session");
}
// get the user name for the HTTP session.
String username = (String) httpSession.getAttribute("username");
if (username == null) {
throw new ChatException("not logged in: no http session username");
}
// create the chat message
StatusUpdate statusUpdate = new StatusUpdate();
statusUpdate.setUsername(username);
statusUpdate.setStatus(status);
for (Map.Entry<String, CometSession> entry : users.entrySet()) {
entry.getValue().enqueue(statusUpdate);
}
}
}