package won.owner.web.websocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.WebSocketSession;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* This service stores the connection between the WebSocket sessions and a given key
*
* @author Fabian Salcher
*/
public class WebSocketSessionMapping<T>
{
private final Logger logger = LoggerFactory.getLogger(getClass());
// ToDo (FS): make this persistent
private Map<T, Set<WebSocketSession>> mapping = new HashMap<T, Set<WebSocketSession>>();
private Object lock ;
public WebSocketSessionMapping() {
this.lock = new Object();
}
public void addMapping(T key, WebSocketSession session) {
logger.debug("adding mapping for key {} to websocket session {}", key, session.getId());
synchronized (lock) {
//we want to avoid losing one of two concurrent sessions added
//for the same key, so we synchronize here
if (!mapping.containsKey(key)) {
//we use the CopyOnWriteArraySet so we are safe across threads. We
//assume that reads outnumber writes by far.
mapping.put(key, new CopyOnWriteArraySet<WebSocketSession>());
}
}
mapping.get(key).add(session);
}
public void removeMapping(T key, WebSocketSession session) {
logger.debug("removing mapping from key {} to websocket session {}", key, session.getId());
synchronized (this) {
//we don't want add and remove to interfere
Set<WebSocketSession> sessions = mapping.get(key);
if (sessions != null) {
sessions.remove(session);
if (sessions.isEmpty()) mapping.remove(sessions);
}
}
}
public Set<WebSocketSession> getWebSocketSessions(T key) {
Set<WebSocketSession> sessions = mapping.get(key);
if (sessions != null) {
Set<WebSocketSession> ret = new HashSet(sessions.size());
ret.addAll(sessions);
return ret;
} else {
return new HashSet();
}
}
}