package io.mangoo.managers; import java.util.HashSet; import java.util.Objects; import java.util.Set; import org.apache.commons.io.IOUtils; import com.google.inject.Inject; import com.google.inject.Singleton; import io.mangoo.cache.Cache; import io.mangoo.enums.CacheName; import io.mangoo.enums.Default; import io.mangoo.enums.Required; import io.mangoo.helpers.RequestHelper; import io.mangoo.providers.CacheProvider; import io.undertow.server.handlers.sse.ServerSentEventConnection; import io.undertow.server.handlers.sse.ServerSentEventConnection.EventCallback; /** * * @author svenkubiak * */ @Singleton public class ServerEventManager { private final Cache cache; private final RequestHelper requestHelper; @Inject private ServerEventManager(CacheProvider cacheProvider, RequestHelper requestHelper) { Objects.requireNonNull(cacheProvider, Required.CACHE_PROVIDER.toString()); Objects.requireNonNull(cacheProvider, Required.REQUEST_HELPER.toString()); this.cache = cacheProvider.getCache(CacheName.SSE); this.requestHelper = requestHelper; } /** * Adds a new connection to the manager * * @param connection The connection to put */ @SuppressWarnings("all") public void addConnection(ServerSentEventConnection connection) { Objects.requireNonNull(connection, Required.CONNECTION.toString()); final String url = this.requestHelper.getServerSentEventURL(connection); Set<ServerSentEventConnection> uriConnections = getConnections(url); if (uriConnections == null) { uriConnections = new HashSet<>(); uriConnections.add(connection); } else { uriConnections.add(connection); } setConnections(url, uriConnections); } /** * Sends data to all connections for a given URI resource * * @param uri The URI resource for the connection * @param data The event data */ public void send(String uri, String data) { Objects.requireNonNull(uri, Required.URI.toString()); final Set<ServerSentEventConnection> uriConnections = getConnections(uri); if (uriConnections != null) { uriConnections.forEach(connection -> { if (connection.isOpen()) { connection.send(data); } }); } } /** * Sends data to all connections for a given URI and invokes the callback * on Success or failure * * @param uri The URI resource for the connection * @param data The event data * @param eventCallback A callback that is notified on Success or failure */ public void send(String uri, String data, EventCallback eventCallback) { Objects.requireNonNull(uri, Required.URI.toString()); Objects.requireNonNull(eventCallback, Required.EVENT_CALLBACK.toString()); final Set<ServerSentEventConnection> uriConnections = getConnections(uri); if (uriConnections != null) { uriConnections.forEach(connection -> { if (connection.isOpen()) { connection.send(data, eventCallback); } }); } } /** * Closes all connections for a given URI resource * * @param uri The URI resource for the connection */ public void close(String uri) { Objects.requireNonNull(uri, Required.URI.toString()); final Set<ServerSentEventConnection> uriConnections = getConnections(uri); if (uriConnections != null) { uriConnections.forEach(connection -> { if (connection.isOpen()){ IOUtils.closeQuietly(connection); } }); removeConnections(uri); } } /** * Retrieves all connection resources under a given URL * * @param uri The URI resource for the connections * * @return A Set of connections for the URI resource */ public Set<ServerSentEventConnection> getConnections(String uri) { Objects.requireNonNull(uri, Required.URI.toString()); final Set<ServerSentEventConnection> uriConnections = this.cache.get(Default.SSE_CACHE_PREFIX.toString() + uri); return (uriConnections == null) ? new HashSet<>() : uriConnections; } /** * Sets the URI resources for a given URL * * @param uri The URI resource for the connection * @param uriConnections The connections for the URI resource */ public void setConnections(String uri, Set<ServerSentEventConnection> uriConnections) { Objects.requireNonNull(uri, Required.URI.toString()); Objects.requireNonNull(uriConnections, Required.URI_CONNECTIONS.toString()); this.cache.put(Default.SSE_CACHE_PREFIX.toString() + uri, uriConnections); } /** * Removes all URI resources for a given URL * * @param uri The URI resource for the connection */ public void removeConnections(String uri) { Objects.requireNonNull(uri, Required.URI.toString()); this.cache.remove(Default.SSE_CACHE_PREFIX.toString() + uri); } }