From bf7b475267a0b5db597735d52c27a3e5aabc3a75 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 26 Apr 2016 17:03:00 +0200 Subject: [PATCH] SocketUtils considers port range including maxPort Issue: SPR-14211 --- .../org/springframework/util/SocketUtils.java | 26 ++++----- .../util/SocketUtilsTests.java | 58 ++++++++++--------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/SocketUtils.java b/spring-core/src/main/java/org/springframework/util/SocketUtils.java index 6754a30a8b6..091a3febbc1 100644 --- a/spring-core/src/main/java/org/springframework/util/SocketUtils.java +++ b/spring-core/src/main/java/org/springframework/util/SocketUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -192,14 +192,14 @@ public class SocketUtils { } - private static enum SocketType { + private enum SocketType { TCP { @Override protected boolean isPortAvailable(int port) { try { - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, - InetAddress.getByName("localhost")); + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket( + port, 1, InetAddress.getByName("localhost")); serverSocket.close(); return true; } @@ -238,7 +238,7 @@ public class SocketUtils { */ private int findRandomPort(int minPort, int maxPort) { int portRange = maxPort - minPort; - return minPort + random.nextInt(portRange); + return minPort + random.nextInt(portRange + 1); } /** @@ -251,7 +251,7 @@ public class SocketUtils { */ int findAvailablePort(int minPort, int maxPort) { Assert.isTrue(minPort > 0, "'minPort' must be greater than 0"); - Assert.isTrue(maxPort > minPort, "'maxPort' must be greater than 'minPort'"); + Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equals 'minPort'"); Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); int portRange = maxPort - minPort; @@ -260,8 +260,8 @@ public class SocketUtils { do { if (++searchCounter > portRange) { throw new IllegalStateException(String.format( - "Could not find an available %s port in the range [%d, %d] after %d attempts", name(), minPort, - maxPort, searchCounter)); + "Could not find an available %s port in the range [%d, %d] after %d attempts", + name(), minPort, maxPort, searchCounter)); } candidatePort = findRandomPort(minPort, maxPort); } @@ -285,18 +285,18 @@ public class SocketUtils { Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); Assert.isTrue(numRequested > 0, "'numRequested' must be greater than 0"); Assert.isTrue((maxPort - minPort) >= numRequested, - "'numRequested' must not be greater than 'maxPort' - 'minPort'"); + "'numRequested' must not be greater than 'maxPort' - 'minPort'"); - final SortedSet availablePorts = new TreeSet(); + SortedSet availablePorts = new TreeSet(); int attemptCount = 0; - while ((++attemptCount <= numRequested + 100) && (availablePorts.size() < numRequested)) { + while ((++attemptCount <= numRequested + 100) && availablePorts.size() < numRequested) { availablePorts.add(findAvailablePort(minPort, maxPort)); } if (availablePorts.size() != numRequested) { throw new IllegalStateException(String.format( - "Could not find %d available %s ports in the range [%d, %d]", numRequested, name(), minPort, - maxPort)); + "Could not find %d available %s ports in the range [%d, %d]", + numRequested, name(), minPort, maxPort)); } return availablePorts; diff --git a/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java b/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java index 362ef701324..8abd6c88789 100644 --- a/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,19 +35,7 @@ import static org.springframework.util.SocketUtils.*; */ public class SocketUtilsTests { - private void assertPortInRange(int port, int minPort, int maxPort) { - assertTrue("port [" + port + "] >= " + minPort, port >= minPort); - assertTrue("port [" + port + "] <= " + maxPort, port <= maxPort); - } - - private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { - assertEquals("number of ports requested", numRequested, ports.size()); - for (int port : ports) { - assertPortInRange(port, minPort, maxPort); - } - } - - // --- TCP ----------------------------------------------------------------- + // TCP @Test(expected = IllegalArgumentException.class) public void findAvailableTcpPortWithZeroMinPort() { @@ -70,8 +58,7 @@ public class SocketUtilsTests { int port = SocketUtils.findAvailableTcpPort(); ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost")); try { - // will only look for the exact port, since random.nextInt(1) always returns 0 - SocketUtils.findAvailableTcpPort(port, port + 1); + SocketUtils.findAvailableTcpPort(port, port); } finally { socket.close(); @@ -117,17 +104,8 @@ public class SocketUtilsTests { findAvailableTcpPorts(50, 45000, 45010); } - private void findAvailableTcpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); - } - private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); - assertAvailablePorts(ports, numRequested, minPort, maxPort); - } - - // --- UDP ----------------------------------------------------------------- + // UDP @Test(expected = IllegalArgumentException.class) public void findAvailableUdpPortWithZeroMinPort() { @@ -150,8 +128,8 @@ public class SocketUtilsTests { int port = SocketUtils.findAvailableUdpPort(); DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost")); try { - // will only look for the exact port, since random.nextInt(1) always returns 0 - SocketUtils.findAvailableUdpPort(port, port + 1); + // will only look for the exact port + SocketUtils.findAvailableUdpPort(port, port); } finally { socket.close(); @@ -197,6 +175,19 @@ public class SocketUtilsTests { findAvailableUdpPorts(50, 45000, 45010); } + + // Helpers + + private void findAvailableTcpPorts(int numRequested) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); + assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + } + + private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { + SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); + assertAvailablePorts(ports, numRequested, minPort, maxPort); + } + private void findAvailableUdpPorts(int numRequested) { SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); @@ -206,5 +197,16 @@ public class SocketUtilsTests { SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); assertAvailablePorts(ports, numRequested, minPort, maxPort); } + private void assertPortInRange(int port, int minPort, int maxPort) { + assertTrue("port [" + port + "] >= " + minPort, port >= minPort); + assertTrue("port [" + port + "] <= " + maxPort, port <= maxPort); + } + + private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) { + assertEquals("number of ports requested", numRequested, ports.size()); + for (int port : ports) { + assertPortInRange(port, minPort, maxPort); + } + } }