package de.is24.infrastructure.gridfs.http.utils; 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 de.is24.infrastructure.gridfs.http.utils.retry.RetryUtils.execute; /** * 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); execute().maxTries(3).wait(2).command(() -> { port = Network.getFreeServerPort(); LOG.info("StatsdMockServer starting : port={}", port); server.socket().bind(new InetSocketAddress(port)); return null; }); 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(); } } }