From 7c57c85d007406670537796b014b17c383946552 Mon Sep 17 00:00:00 2001 From: Manuel Ryan Date: Tue, 13 Oct 2015 01:18:01 +0200 Subject: [PATCH] Attempt to fix Mac OSX compatibility by listing all network interfaces and binding on each one separately --- .../extension/impl/AvailablePortFinder.java | 71 ++++++++++++++----- .../impl/AvailablePortFinderTest.java | 12 +++- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/github/mryan43/arquillian/available/port/extension/impl/AvailablePortFinder.java b/src/main/java/com/github/mryan43/arquillian/available/port/extension/impl/AvailablePortFinder.java index 272b74f..dfc3291 100644 --- a/src/main/java/com/github/mryan43/arquillian/available/port/extension/impl/AvailablePortFinder.java +++ b/src/main/java/com/github/mryan43/arquillian/available/port/extension/impl/AvailablePortFinder.java @@ -1,9 +1,11 @@ package com.github.mryan43.arquillian.available.port.extension.impl; import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; import java.net.ServerSocket; -import java.util.HashMap; -import java.util.Map; +import java.net.SocketException; +import java.util.*; import org.jboss.arquillian.core.api.annotation.Observes; import org.jboss.arquillian.core.api.event.ManagerStarted; @@ -12,7 +14,7 @@ public class AvailablePortFinder { private static final String SYSTEM_PROPERTY_NAME = "available.port"; - private static final Integer MAX_PORT_NUMBER = 65535; + private static final Integer MAX_PORT_NUMBER = 0xFFFF; //65535 private static final Integer MIN_PORT_NUMBER = 8080; private final Map previousValues = new HashMap(); @@ -20,29 +22,54 @@ public class AvailablePortFinder { // it's important that this method is invoked before the arquillian.xml file is read, which is typically triggered by the // ConfigurationRegistar observer, which is a ManagerStarted event observer. // Since the ManagerStarted event is the very first one fired by Arquillian, we need to use the same, but with a higher precedence. - public void beforeConfigurationIsRead(@Observes(precedence = 50) ManagerStarted event) { - - for (int port = MIN_PORT_NUMBER; port <= MAX_PORT_NUMBER; port++) { - try { - ServerSocket serverSocket = new ServerSocket(port); - serverSocket.close(); - previousValues.put(event, System.getProperty(SYSTEM_PROPERTY_NAME)); - System.setProperty(SYSTEM_PROPERTY_NAME, Integer.toString(port)); - return; + public void findAvailableNetworkPort(@Observes(precedence = 50) ManagerStarted event) { + + try{ + Set addresses = getAllNetworkAddresses(); + + for (int port = MIN_PORT_NUMBER; port <= MAX_PORT_NUMBER; port++) { + boolean failed = false; + for (InetAddress address : addresses){ + try{ + ServerSocket serverSocket = new ServerSocket(port,5,address); + serverSocket.close(); + } + catch (IOException ioe) { + // Port binding failed on one of the interfaces, let's try next port + failed = true; + break; + } + } + // managed to bind on all interfaces ? + if (!failed){ + previousValues.put(event, System.getProperty(SYSTEM_PROPERTY_NAME)); + System.setProperty(SYSTEM_PROPERTY_NAME, Integer.toString(port)); + return; + } } - catch (IOException ioe) { - // Tried binding port without success. Trying next port + } catch (SocketException e){ + // Failed to list all network addresses, we fallback and try to bind on the default port + for (int port = MIN_PORT_NUMBER; port <= MAX_PORT_NUMBER; port++) { + try { + ServerSocket serverSocket = new ServerSocket(port); + serverSocket.close(); + previousValues.put(event, System.getProperty(SYSTEM_PROPERTY_NAME)); + System.setProperty(SYSTEM_PROPERTY_NAME, Integer.toString(port)); + return; + } + catch (IOException ioe) { + // Port binding failed let's try next port + } } } - System.clearProperty("available.port"); throw new IllegalStateException("Unable to find an available port between " + MIN_PORT_NUMBER + " and " + MAX_PORT_NUMBER); } // Restore any previous value of the system property after the configuration has been read - public void afterConfigurationIsRead(@Observes(precedence = -50) ManagerStarted event) { + public void cleanup(@Observes(precedence = -50) ManagerStarted event) { String previousValue = previousValues.get(event); if (previousValue == null){ @@ -52,4 +79,16 @@ public void afterConfigurationIsRead(@Observes(precedence = -50) ManagerStarted } } + private static Set getAllNetworkAddresses() throws SocketException { + Set result = new HashSet(); + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) { + Enumeration inetAddresses = networkInterface.getInetAddresses(); + for (InetAddress inetAddress : Collections.list(inetAddresses)) { + result.add(inetAddress); + } + } + return result; + } + } diff --git a/src/test/java/com/githum/mryan43/arquillian/available/port/extension/impl/AvailablePortFinderTest.java b/src/test/java/com/githum/mryan43/arquillian/available/port/extension/impl/AvailablePortFinderTest.java index 0f23c7d..86f08b9 100644 --- a/src/test/java/com/githum/mryan43/arquillian/available/port/extension/impl/AvailablePortFinderTest.java +++ b/src/test/java/com/githum/mryan43/arquillian/available/port/extension/impl/AvailablePortFinderTest.java @@ -9,10 +9,15 @@ import com.github.mryan43.arquillian.available.port.extension.impl.AvailablePortFinder; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; + public class AvailablePortFinderTest { @Test - public void test_find_port(){ + public void test_find_port() throws IOException{ // Given AvailablePortFinder portFinder = new AvailablePortFinder(); @@ -20,7 +25,7 @@ public void test_find_port(){ System.setProperty("available.port", "previous value foo"); // When - portFinder.beforeConfigurationIsRead(event); + portFinder.findAvailableNetworkPort(event); // Then String[] possibleValues = new String[65537]; @@ -28,9 +33,10 @@ public void test_find_port(){ possibleValues[i] = Integer.toString(i); } assertThat(System.getProperty("available.port"), is(oneOf(possibleValues))); + System.out.println("Found available port : "+System.getProperty("available.port")); // When - portFinder.afterConfigurationIsRead(event); + portFinder.cleanup(event); // Then assertThat(System.getProperty("available.port"), is("previous value foo"));