package de.is24.util.monitoring.tools; import de.flapdoodle.embed.process.runtime.Network; import org.junit.rules.ExternalResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import static java.lang.String.format; import static java.lang.Thread.sleep; /** * Mock for a statsd server using non-blocking IO according to http://www.onjava.com/pub/a/onjava/2002/09/04/nio.html?page=2 */ public class StatsdMockServer extends ExternalResource implements Runnable { private static final Logger LOG = LoggerFactory.getLogger(StatsdMockServer.class); private ServerSocketChannel server; private int port; private Selector selector; private Thread thread; @Override public void before() throws Throwable { server = ServerSocketChannel.open(); server.configureBlocking(false); int maxTries = 3; int sleepInSec = 2; for (int i = 0; i < maxTries; i++) { try { port = Network.getFreeServerPort(); server.socket().bind(new InetSocketAddress(port)); LOG.info("StatsdMockServer started : port={}", port); } catch (Throwable e) { int lastTry = maxTries - 1; if (i < lastTry) { LOG.warn(format("Starting StatsdMockServer: try %s of %s failed. Retry after %s seconds.", i + 1, maxTries, sleepInSec), e); sleep(sleepInSec * 1000); } else { LOG.error(format("Starting StatsdMockServer: %s of %s failed. No retries left.", i + 1, maxTries)); throw e; } } } selector = Selector.open(); server.register(selector, SelectionKey.OP_ACCEPT); thread = new Thread(this); thread.start(); } @Override public void after() { try { thread.interrupt(); } catch (Exception e) { } try { selector.close(); } catch (IOException e) { } try { server.close(); } catch (Exception e) { } } public int getPort() { return port; } @Override public void run() { try { while (!thread.isInterrupted()) { if (selector.select() > 0) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); if (!key.isValid()) { continue; } if (key.isAcceptable()) { SocketChannel client = server.accept(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); continue; } if (key.isReadable()) { SocketChannel client = (SocketChannel) key.channel(); int BUFFER_SIZE = 32; ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); try { client.read(buffer); } catch (Exception e) { e.printStackTrace(); } continue; } } } } } catch (IOException e) { e.printStackTrace(); } } }