/* * Copyright 2012 Future Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.httpd; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class WebSocketManager { private final Logger logger = LoggerFactory.getLogger(WebSocketManager.class.getName()); private static final String WEBSOCKET_PATH = "/websocket"; /** * part of websocket location (ws://domain/path/to/websocket) */ private String path = WEBSOCKET_PATH; private WebSocketServlet servlet; private ConcurrentMap<InetSocketAddress, WebSocket> sockets; private CopyOnWriteArraySet<WebSocketListener> listeners; public WebSocketManager() { servlet = new WebSocketServlet(this); sockets = new ConcurrentHashMap<InetSocketAddress, WebSocket>(); listeners = new CopyOnWriteArraySet<WebSocketListener>(); } public WebSocketServlet getServlet() { return servlet; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Collection<WebSocket> getSockets() { return new ArrayList<WebSocket>(sockets.values()); } public void register(WebSocket socket) { logger.trace("kraken httpd: adding websocket session [{}]", socket); sockets.put(socket.getRemoteAddress(), socket); // invoke callbacks for (WebSocketListener listener : listeners) { try { listener.onConnected(socket); } catch (Exception e) { logger.warn("kraken httpd: callback should not throw any exception", e); } } } public void unregister(InetSocketAddress remote) { WebSocket socket = sockets.remove(remote); if (socket == null) return; logger.trace("kraken httpd: removing websocket session [{}]", remote); for (WebSocketListener listener : listeners) { try { listener.onDisconnected(socket); } catch (Exception e) { logger.warn("kraken httpd: callback should not throw any exception", e); } } } public void dispatch(WebSocketFrame frame) { WebSocket socket = sockets.get(frame.getRemote()); if (socket == null) { logger.warn("kraken httpd: websocket not found for frame [{}]", frame); return; } logger.trace("kraken httpd: received frame [{}]", frame); for (WebSocketListener listener : listeners) { try { listener.onMessage(socket, frame); } catch (Exception e) { logger.warn("kraken httpd: callback should not throw any exception", e); } } } public void addListener(WebSocketListener listener) { logger.trace("kraken httpd: listener [{}] added", listener); listeners.add(listener); } public void removeListener(WebSocketListener listener) { logger.trace("kraken httpd: listener [{}] removed", listener); listeners.remove(listener); } @Override public String toString() { return "WebSocket path [" + path + "], sessions [" + sockets.size() + "]"; } }