001package systems.dmx.core.impl; 002 003import systems.dmx.core.service.CoreService; 004 005import org.eclipse.jetty.websocket.WebSocket; 006import org.eclipse.jetty.websocket.WebSocket.Connection; 007 008import java.util.logging.Level; 009import java.util.logging.Logger; 010 011 012 013/** 014 * A WebSocket connection that is bound to a DMX plugin. 015 * When a message arrives on the connection the plugin is notified via a WEBSOCKET_TEXT_MESSAGE event. 016 * <p> 017 * Once the actual WebSocket connection is opened or closed the WebSocketConnection is added/removed to a pool. 018 */ 019class WebSocketConnection implements WebSocket, WebSocket.OnTextMessage, WebSocket.OnBinaryMessage { 020 021 // ---------------------------------------------------------------------------------------------- Instance Variables 022 023 String pluginUri; 024 String sessionId; 025 026 /** 027 * The underlying Jetty WebSocket connection. 028 */ 029 private Connection connection; 030 031 private WebSocketConnectionPool pool; 032 private CoreService dmx; 033 034 private Logger logger = Logger.getLogger(getClass().getName()); 035 036 // ----------------------------------------------------------------------------------------------------- Constructor 037 038 WebSocketConnection(String pluginUri, String sessionId, WebSocketConnectionPool pool, CoreService dmx) { 039 this.pluginUri = pluginUri; 040 this.sessionId = sessionId; 041 this.pool = pool; 042 this.dmx = dmx; 043 } 044 045 // -------------------------------------------------------------------------------------------------- Public Methods 046 047 // *** WebSocket *** 048 049 @Override 050 public void onOpen(Connection connection) { 051 logger.info("Opening a WebSocket connection for plugin \"" + pluginUri + "\" (session " + sessionId + ")"); 052 this.connection = connection; 053 pool.add(this); 054 } 055 056 @Override 057 public void onClose(int code, String message) { 058 logger.info("Closing a WebSocket connection of plugin \"" + pluginUri + "\" (session " + sessionId + ")"); 059 pool.remove(this); 060 } 061 062 // *** WebSocket.OnTextMessage *** 063 064 @Override 065 public void onMessage(String message) { 066 try { 067 dmx.dispatchEvent(pluginUri, CoreEvent.WEBSOCKET_TEXT_MESSAGE, message); 068 } catch (Exception e) { 069 // Note: we don't rethrow to Jetty here. It would not log the exception's cause. DM's exception 070 // mapper would not kick in either as the plugin is called from Jetty directly, not Jersey. 071 logger.log(Level.SEVERE, "An error occurred while dispatching a WebSocket message to plugin \"" + 072 pluginUri + "\":", e); 073 } 074 } 075 076 // *** WebSocket.OnBinaryMessage *** 077 078 @Override 079 public void onMessage(byte[] data, int offset, int length) { 080 // ### TODO 081 } 082 083 // ----------------------------------------------------------------------------------------- Package Private Methods 084 085 void sendMessage(String message) { 086 try { 087 connection.sendMessage(message); 088 } catch (Exception e) { 089 pool.remove(this); 090 logger.log(Level.SEVERE, "Sending message via " + this + " failed -- connection removed", e); 091 } 092 } 093}