diff --git a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
index f9863819b4..65b3d032be 100644
--- a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
@@ -34,6 +34,7 @@ import javax.management.remote.JMXServiceURL;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.core.testfixture.net.TestSocketUtils;
import org.springframework.jmx.AbstractMBeanServerTests;
import org.springframework.jmx.IJmxTestBean;
import org.springframework.jmx.JmxTestBean;
@@ -177,7 +178,7 @@ class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
assumeTrue(runTests);
@SuppressWarnings("deprecation")
- final int port = org.springframework.util.SocketUtils.findAvailableTcpPort();
+ final int port = TestSocketUtils.findAvailableTcpPort();
JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:" + port);
JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer());
diff --git a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java
index a617803188..f315bd46e1 100644
--- a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java
@@ -28,6 +28,8 @@ import javax.management.remote.JMXServiceURL;
import org.junit.jupiter.api.AfterEach;
+import org.springframework.core.testfixture.net.TestSocketUtils;
+
/**
* @author Rob Harrop
* @author Chris Beams
@@ -36,7 +38,7 @@ import org.junit.jupiter.api.AfterEach;
class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests {
@SuppressWarnings("deprecation")
- private final int servicePort = org.springframework.util.SocketUtils.findAvailableTcpPort();
+ private final int servicePort = TestSocketUtils.findAvailableTcpPort();
private final String serviceUrl = "service:jmx:jmxmp://localhost:" + servicePort;
diff --git a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java
index fad3ed40ec..5f34977445 100644
--- a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java
@@ -30,6 +30,7 @@ import javax.management.remote.JMXServiceURL;
import org.junit.jupiter.api.Test;
+import org.springframework.core.testfixture.net.TestSocketUtils;
import org.springframework.jmx.AbstractMBeanServerTests;
import static org.assertj.core.api.Assertions.assertThat;
@@ -47,7 +48,7 @@ class ConnectorServerFactoryBeanTests extends AbstractMBeanServerTests {
private static final String OBJECT_NAME = "spring:type=connector,name=test";
@SuppressWarnings("deprecation")
- private final String serviceUrl = "service:jmx:jmxmp://localhost:" + org.springframework.util.SocketUtils.findAvailableTcpPort();
+ private final String serviceUrl = "service:jmx:jmxmp://localhost:" + TestSocketUtils.findAvailableTcpPort();
@Test
diff --git a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java
index 64159c6e51..6391f607f9 100644
--- a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java
+++ b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java
@@ -24,6 +24,7 @@ import javax.management.remote.JMXServiceURL;
import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;
+import org.springframework.core.testfixture.net.TestSocketUtils;
import org.springframework.jmx.AbstractMBeanServerTests;
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTests {
@SuppressWarnings("deprecation")
- private final String serviceUrl = "service:jmx:jmxmp://localhost:" + org.springframework.util.SocketUtils.findAvailableTcpPort();
+ private final String serviceUrl = "service:jmx:jmxmp://localhost:" + TestSocketUtils.findAvailableTcpPort();
@Test
diff --git a/spring-core/src/main/java/org/springframework/util/SocketUtils.java b/spring-core/src/main/java/org/springframework/util/SocketUtils.java
deleted file mode 100644
index a100bc6d86..0000000000
--- a/spring-core/src/main/java/org/springframework/util/SocketUtils.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright 2002-2022 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.
- * You may obtain a copy of the License at
- *
- * https://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.springframework.util;
-
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.util.Random;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.net.ServerSocketFactory;
-
-/**
- * Simple utility methods for working with network sockets — for example,
- * for finding available ports on {@code localhost}.
- *
- *
Within this class, a TCP port refers to a port for a {@link ServerSocket};
- * whereas, a UDP port refers to a port for a {@link DatagramSocket}.
- *
- *
{@code SocketUtils} was introduced in Spring Framework 4.0, primarily to
- * assist in writing integration tests which start an external server on an
- * available random port. However, these utilities make no guarantee about the
- * subsequent availability of a given port and are therefore unreliable. Instead
- * of using {@code SocketUtils} to find an available local port for a server, it
- * is recommended that you rely on a server's ability to start on a random port
- * that it selects or is assigned by the operating system. To interact with that
- * server, you should query the server for the port it is currently using.
- *
- * @author Sam Brannen
- * @author Ben Hale
- * @author Arjen Poutsma
- * @author Gunnar Hillert
- * @author Gary Russell
- * @since 4.0
- * @deprecated as of Spring Framework 5.3.16, to be removed in 6.0; see
- * {@link SocketUtils class-level Javadoc} for details.
- */
-@Deprecated
-public class SocketUtils {
-
- /**
- * The default minimum value for port ranges used when finding an available
- * socket port.
- */
- public static final int PORT_RANGE_MIN = 1024;
-
- /**
- * The default maximum value for port ranges used when finding an available
- * socket port.
- */
- public static final int PORT_RANGE_MAX = 65535;
-
-
- private static final Random random = new Random(System.nanoTime());
-
-
- /**
- * Although {@code SocketUtils} consists solely of static utility methods,
- * this constructor is intentionally {@code public}.
- *
Rationale
- * Static methods from this class may be invoked from within XML
- * configuration files using the Spring Expression Language (SpEL) and the
- * following syntax.
- *
<bean id="bean1" ... p:port="#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />
- * If this constructor were {@code private}, you would be required to supply
- * the fully qualified class name to SpEL's {@code T()} function for each usage.
- * Thus, the fact that this constructor is {@code public} allows you to reduce
- * boilerplate configuration with SpEL as can be seen in the following example.
- * <bean id="socketUtils" class="org.springframework.util.SocketUtils" />
- * <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" />
- * <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
- */
- public SocketUtils() {
- }
-
-
- /**
- * Find an available TCP port randomly selected from the range
- * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}].
- * @return an available TCP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableTcpPort() {
- return findAvailableTcpPort(PORT_RANGE_MIN);
- }
-
- /**
- * Find an available TCP port randomly selected from the range
- * [{@code minPort}, {@value #PORT_RANGE_MAX}].
- * @param minPort the minimum port number
- * @return an available TCP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableTcpPort(int minPort) {
- return findAvailableTcpPort(minPort, PORT_RANGE_MAX);
- }
-
- /**
- * Find an available TCP port randomly selected from the range
- * [{@code minPort}, {@code maxPort}].
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return an available TCP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableTcpPort(int minPort, int maxPort) {
- return SocketType.TCP.findAvailablePort(minPort, maxPort);
- }
-
- /**
- * Find the requested number of available TCP ports, each randomly selected
- * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}].
- * @param numRequested the number of available ports to find
- * @return a sorted set of available TCP port numbers
- * @throws IllegalStateException if the requested number of available ports could not be found
- */
- public static SortedSet findAvailableTcpPorts(int numRequested) {
- return findAvailableTcpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX);
- }
-
- /**
- * Find the requested number of available TCP ports, each randomly selected
- * from the range [{@code minPort}, {@code maxPort}].
- * @param numRequested the number of available ports to find
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return a sorted set of available TCP port numbers
- * @throws IllegalStateException if the requested number of available ports could not be found
- */
- public static SortedSet findAvailableTcpPorts(int numRequested, int minPort, int maxPort) {
- return SocketType.TCP.findAvailablePorts(numRequested, minPort, maxPort);
- }
-
- /**
- * Find an available UDP port randomly selected from the range
- * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}].
- * @return an available UDP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableUdpPort() {
- return findAvailableUdpPort(PORT_RANGE_MIN);
- }
-
- /**
- * Find an available UDP port randomly selected from the range
- * [{@code minPort}, {@value #PORT_RANGE_MAX}].
- * @param minPort the minimum port number
- * @return an available UDP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableUdpPort(int minPort) {
- return findAvailableUdpPort(minPort, PORT_RANGE_MAX);
- }
-
- /**
- * Find an available UDP port randomly selected from the range
- * [{@code minPort}, {@code maxPort}].
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return an available UDP port number
- * @throws IllegalStateException if no available port could be found
- */
- public static int findAvailableUdpPort(int minPort, int maxPort) {
- return SocketType.UDP.findAvailablePort(minPort, maxPort);
- }
-
- /**
- * Find the requested number of available UDP ports, each randomly selected
- * from the range [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}].
- * @param numRequested the number of available ports to find
- * @return a sorted set of available UDP port numbers
- * @throws IllegalStateException if the requested number of available ports could not be found
- */
- public static SortedSet findAvailableUdpPorts(int numRequested) {
- return findAvailableUdpPorts(numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX);
- }
-
- /**
- * Find the requested number of available UDP ports, each randomly selected
- * from the range [{@code minPort}, {@code maxPort}].
- * @param numRequested the number of available ports to find
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return a sorted set of available UDP port numbers
- * @throws IllegalStateException if the requested number of available ports could not be found
- */
- public static SortedSet findAvailableUdpPorts(int numRequested, int minPort, int maxPort) {
- return SocketType.UDP.findAvailablePorts(numRequested, minPort, maxPort);
- }
-
-
- private enum SocketType {
-
- TCP {
- @Override
- protected boolean isPortAvailable(int port) {
- try {
- ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(
- port, 1, InetAddress.getByName("localhost"));
- serverSocket.close();
- return true;
- }
- catch (Exception ex) {
- return false;
- }
- }
- },
-
- UDP {
- @Override
- protected boolean isPortAvailable(int port) {
- try {
- DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"));
- socket.close();
- return true;
- }
- catch (Exception ex) {
- return false;
- }
- }
- };
-
- /**
- * Determine if the specified port for this {@code SocketType} is
- * currently available on {@code localhost}.
- */
- protected abstract boolean isPortAvailable(int port);
-
- /**
- * Find a pseudo-random port number within the range
- * [{@code minPort}, {@code maxPort}].
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return a random port number within the specified range
- */
- private int findRandomPort(int minPort, int maxPort) {
- int portRange = maxPort - minPort;
- return minPort + random.nextInt(portRange + 1);
- }
-
- /**
- * Find an available port for this {@code SocketType}, randomly selected
- * from the range [{@code minPort}, {@code maxPort}].
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return an available port number for this socket type
- * @throws IllegalStateException if no available port could be found
- */
- 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 or equal to 'minPort'");
- Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX);
-
- int portRange = maxPort - minPort;
- int candidatePort;
- int searchCounter = 0;
- 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));
- }
- candidatePort = findRandomPort(minPort, maxPort);
- searchCounter++;
- }
- while (!isPortAvailable(candidatePort));
-
- return candidatePort;
- }
-
- /**
- * Find the requested number of available ports for this {@code SocketType},
- * each randomly selected from the range [{@code minPort}, {@code maxPort}].
- * @param numRequested the number of available ports to find
- * @param minPort the minimum port number
- * @param maxPort the maximum port number
- * @return a sorted set of available port numbers for this socket type
- * @throws IllegalStateException if the requested number of available ports could not be found
- */
- SortedSet findAvailablePorts(int numRequested, 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 <= 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'");
-
- SortedSet availablePorts = new TreeSet<>();
- int attemptCount = 0;
- 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));
- }
-
- 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
deleted file mode 100644
index c0f8748195..0000000000
--- a/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2002-2022 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.
- * You may obtain a copy of the License at
- *
- * https://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.springframework.util;
-
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.util.SortedSet;
-
-import javax.net.ServerSocketFactory;
-
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-
-/**
- * Unit tests for {@link SocketUtils}.
- *
- * @author Sam Brannen
- * @author Gary Russell
- */
-@SuppressWarnings("deprecation")
-class SocketUtilsTests {
-
- @Test
- void canBeInstantiated() {
- // Just making sure somebody doesn't try to make SocketUtils abstract,
- // since that would be a breaking change due to the intentional public
- // constructor.
- new org.springframework.util.SocketUtils();
- }
-
- // TCP
-
- @Test
- void findAvailableTcpPortWithZeroMinPort() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableTcpPort(0));
- }
-
- @Test
- void findAvailableTcpPortWithNegativeMinPort() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableTcpPort(-500));
- }
-
- @Test
- void findAvailableTcpPort() {
- int port = org.springframework.util.SocketUtils.findAvailableTcpPort();
- assertPortInRange(port, org.springframework.util.SocketUtils.PORT_RANGE_MIN,
- org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- @Test
- void findAvailableTcpPortWithMinPortEqualToMaxPort() {
- int minMaxPort = org.springframework.util.SocketUtils.findAvailableTcpPort();
- int port = org.springframework.util.SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort);
- assertThat(port).isEqualTo(minMaxPort);
- }
-
- @Test
- void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception {
- int port = org.springframework.util.SocketUtils.findAvailableTcpPort();
- try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) {
- assertThat(socket).isNotNull();
- // will only look for the exact port
- assertThatIllegalStateException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableTcpPort(port, port))
- .withMessageStartingWith("Could not find an available TCP port")
- .withMessageEndingWith("after 1 attempts");
- }
- }
-
- @Test
- void findAvailableTcpPortWithMin() {
- int port = org.springframework.util.SocketUtils.findAvailableTcpPort(50000);
- assertPortInRange(port, 50000, org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- @Test
- void findAvailableTcpPortInRange() {
- int minPort = 20000;
- int maxPort = minPort + 1000;
- int port = org.springframework.util.SocketUtils.findAvailableTcpPort(minPort, maxPort);
- assertPortInRange(port, minPort, maxPort);
- }
-
- @Test
- void find4AvailableTcpPorts() {
- findAvailableTcpPorts(4);
- }
-
- @Test
- void find50AvailableTcpPorts() {
- findAvailableTcpPorts(50);
- }
-
- @Test
- void find4AvailableTcpPortsInRange() {
- findAvailableTcpPorts(4, 30000, 35000);
- }
-
- @Test
- void find50AvailableTcpPortsInRange() {
- findAvailableTcpPorts(50, 40000, 45000);
- }
-
- @Test
- void findAvailableTcpPortsWithRequestedNumberGreaterThanSizeOfRange() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- findAvailableTcpPorts(50, 45000, 45010));
- }
-
-
- // UDP
-
- @Test
- void findAvailableUdpPortWithZeroMinPort() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableUdpPort(0));
- }
-
- @Test
- void findAvailableUdpPortWithNegativeMinPort() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableUdpPort(-500));
- }
-
- @Test
- void findAvailableUdpPort() {
- int port = org.springframework.util.SocketUtils.findAvailableUdpPort();
- assertPortInRange(port, org.springframework.util.SocketUtils.PORT_RANGE_MIN,
- org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- @Test
- void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception {
- int port = org.springframework.util.SocketUtils.findAvailableUdpPort();
- try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) {
- assertThat(socket).isNotNull();
- // will only look for the exact port
- assertThatIllegalStateException().isThrownBy(() ->
- org.springframework.util.SocketUtils.findAvailableUdpPort(port, port))
- .withMessageStartingWith("Could not find an available UDP port")
- .withMessageEndingWith("after 1 attempts");
- }
- }
-
- @Test
- void findAvailableUdpPortWithMin() {
- int port = org.springframework.util.SocketUtils.findAvailableUdpPort(50000);
- assertPortInRange(port, 50000, org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- @Test
- void findAvailableUdpPortInRange() {
- int minPort = 20000;
- int maxPort = minPort + 1000;
- int port = org.springframework.util.SocketUtils.findAvailableUdpPort(minPort, maxPort);
- assertPortInRange(port, minPort, maxPort);
- }
-
- @Test
- void find4AvailableUdpPorts() {
- findAvailableUdpPorts(4);
- }
-
- @Test
- void find50AvailableUdpPorts() {
- findAvailableUdpPorts(50);
- }
-
- @Test
- void find4AvailableUdpPortsInRange() {
- findAvailableUdpPorts(4, 30000, 35000);
- }
-
- @Test
- void find50AvailableUdpPortsInRange() {
- findAvailableUdpPorts(50, 40000, 45000);
- }
-
- @Test
- void findAvailableUdpPortsWithRequestedNumberGreaterThanSizeOfRange() {
- assertThatIllegalArgumentException().isThrownBy(() ->
- findAvailableUdpPorts(50, 45000, 45010));
- }
-
-
- // Helpers
-
- private void findAvailableTcpPorts(int numRequested) {
- SortedSet ports = org.springframework.util.SocketUtils.findAvailableTcpPorts(numRequested);
- assertAvailablePorts(ports, numRequested, org.springframework.util.SocketUtils.PORT_RANGE_MIN,
- org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) {
- SortedSet ports = org.springframework.util.SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort);
- assertAvailablePorts(ports, numRequested, minPort, maxPort);
- }
-
- private void findAvailableUdpPorts(int numRequested) {
- SortedSet ports = org.springframework.util.SocketUtils.findAvailableUdpPorts(numRequested);
- assertAvailablePorts(ports, numRequested, org.springframework.util.SocketUtils.PORT_RANGE_MIN,
- org.springframework.util.SocketUtils.PORT_RANGE_MAX);
- }
-
- private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) {
- SortedSet ports = org.springframework.util.SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort);
- assertAvailablePorts(ports, numRequested, minPort, maxPort);
- }
- private void assertPortInRange(int port, int minPort, int maxPort) {
- assertThat(port >= minPort).as("port [" + port + "] >= " + minPort).isTrue();
- assertThat(port <= maxPort).as("port [" + port + "] <= " + maxPort).isTrue();
- }
-
- private void assertAvailablePorts(SortedSet ports, int numRequested, int minPort, int maxPort) {
- assertThat(ports.size()).as("number of ports requested").isEqualTo(numRequested);
- for (int port : ports) {
- assertPortInRange(port, minPort, maxPort);
- }
- }
-
-}
diff --git a/spring-core/src/testFixtures/java/org/springframework/core/testfixture/net/TestSocketUtils.java b/spring-core/src/testFixtures/java/org/springframework/core/testfixture/net/TestSocketUtils.java
new file mode 100644
index 0000000000..ca94026b0d
--- /dev/null
+++ b/spring-core/src/testFixtures/java/org/springframework/core/testfixture/net/TestSocketUtils.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2002-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://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.springframework.core.testfixture.net;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.util.Random;
+
+import javax.net.ServerSocketFactory;
+
+import org.springframework.util.Assert;
+
+/**
+ * Removed from spring-core and introduced as an internal test utility in
+ * spring-context in Spring Framework 6.0.
+ *
+ * Simple utility methods for working with network sockets — for example,
+ * for finding available ports on {@code localhost}.
+ *
+ *
Within this class, a TCP port refers to a port for a {@link ServerSocket};
+ * whereas, a UDP port refers to a port for a {@link DatagramSocket}.
+ *
+ *
{@code SocketUtils} was introduced in Spring Framework 4.0, primarily to
+ * assist in writing integration tests which start an external server on an
+ * available random port. However, these utilities make no guarantee about the
+ * subsequent availability of a given port and are therefore unreliable. Instead
+ * of using {@code SocketUtils} to find an available local port for a server, it
+ * is recommended that you rely on a server's ability to start on a random port
+ * that it selects or is assigned by the operating system. To interact with that
+ * server, you should query the server for the port it is currently using.
+ *
+ * @author Sam Brannen
+ * @author Ben Hale
+ * @author Arjen Poutsma
+ * @author Gunnar Hillert
+ * @author Gary Russell
+ * @since 4.0
+ */
+public class TestSocketUtils {
+
+ /**
+ * The default minimum value for port ranges used when finding an available
+ * socket port.
+ */
+ private static final int PORT_RANGE_MIN = 1024;
+
+ /**
+ * The default maximum value for port ranges used when finding an available
+ * socket port.
+ */
+ private static final int PORT_RANGE_MAX = 65535;
+
+
+ private static final Random random = new Random(System.nanoTime());
+
+
+ /**
+ * Find an available TCP port randomly selected from the range
+ * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}].
+ * @return an available TCP port number
+ * @throws IllegalStateException if no available port could be found
+ */
+ public static int findAvailableTcpPort() {
+ return findAvailablePort(PORT_RANGE_MIN, PORT_RANGE_MAX);
+ }
+
+ /**
+ * Find an available port for this {@code SocketType}, randomly selected
+ * from the range [{@code minPort}, {@code maxPort}].
+ * @param minPort the minimum port number
+ * @param maxPort the maximum port number
+ * @return an available port number for this socket type
+ * @throws IllegalStateException if no available port could be found
+ */
+ private static 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 or equal to 'minPort'");
+ Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX);
+
+ int portRange = maxPort - minPort;
+ int candidatePort;
+ int searchCounter = 0;
+ do {
+ if (searchCounter > portRange) {
+ throw new IllegalStateException(String.format(
+ "Could not find an available TCP port in the range [%d, %d] after %d attempts",
+ minPort, maxPort, searchCounter));
+ }
+ candidatePort = findRandomPort(minPort, maxPort);
+ searchCounter++;
+ }
+ while (!isPortAvailable(candidatePort));
+
+ return candidatePort;
+ }
+
+ /**
+ * Find a pseudo-random port number within the range
+ * [{@code minPort}, {@code maxPort}].
+ * @param minPort the minimum port number
+ * @param maxPort the maximum port number
+ * @return a random port number within the specified range
+ */
+ private static int findRandomPort(int minPort, int maxPort) {
+ int portRange = maxPort - minPort;
+ return minPort + random.nextInt(portRange + 1);
+ }
+
+ /**
+ * Determine if the specified port for this {@code SocketType} is
+ * currently available on {@code localhost}.
+ */
+ private static boolean isPortAvailable(int port) {
+ try {
+ ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(
+ port, 1, InetAddress.getByName("localhost"));
+ serverSocket.close();
+ return true;
+ }
+ catch (Exception ex) {
+ return false;
+ }
+ }
+
+}