Java tutorial
/* * Copyright 2015-present Open Networking Laboratory * * 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.onlab.stc; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.io.ByteStreams; import com.google.common.net.MediaType; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Timer; import java.util.TimerTask; /** * Web socket servlet capable of creating web sockets for the STC monitor. */ public class MonitorWebSocketServlet extends WebSocketServlet implements MonitorDelegate { private static final long PING_DELAY_MS = 5000; private static final String DOT = "."; private static Monitor monitor; private static MonitorWebSocketServlet instance; private final Set<MonitorWebSocket> sockets = new HashSet<>(); private final Timer timer = new Timer(); private final TimerTask pruner = new Pruner(); /** * Binds the shared process flow monitor. * * @param m process monitor reference */ public static void setMonitor(Monitor m) { monitor = m; } /** * Closes all currently open monitor web-sockets. */ public static void closeAll() { if (instance != null) { instance.sockets.forEach(MonitorWebSocket::close); instance.sockets.clear(); } } @Override public void init() throws ServletException { super.init(); instance = this; monitor.setDelegate(this); timer.schedule(pruner, PING_DELAY_MS, PING_DELAY_MS); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String uri = req.getRequestURI(); uri = uri.length() <= 1 ? "/index.html" : uri; InputStream resource = getClass().getResourceAsStream(uri); if (resource == null) { resp.setStatus(HttpServletResponse.SC_NOT_FOUND); } else { byte[] entity = ByteStreams.toByteArray(resource); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType(contentType(uri).toString()); resp.setContentLength(entity.length); resp.getOutputStream().write(entity); } } private MediaType contentType(String uri) { int sep = uri.lastIndexOf(DOT); String ext = sep > 0 ? uri.substring(sep + 1) : null; return ext == null ? MediaType.APPLICATION_BINARY : ext.equals("html") ? MediaType.HTML_UTF_8 : ext.equals("js") ? MediaType.JAVASCRIPT_UTF_8 : ext.equals("css") ? MediaType.CSS_UTF_8 : MediaType.APPLICATION_BINARY; } @Override public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { MonitorWebSocket socket = new MonitorWebSocket(monitor); synchronized (sockets) { sockets.add(socket); } return socket; } @Override public void notify(ObjectNode event) { if (instance != null) { instance.sockets.forEach(ws -> ws.sendMessage(event)); } } // Task for pruning web-sockets that are idle. private class Pruner extends TimerTask { @Override public void run() { synchronized (sockets) { Iterator<MonitorWebSocket> it = sockets.iterator(); while (it.hasNext()) { MonitorWebSocket socket = it.next(); if (socket.isIdle()) { it.remove(); socket.close(); } } } } } }