Introduce TCP & UDP server port scanning utility
Prior to this commit the Spring Framework did not provide a public means for scanning for available server ports. However, the Spring Framework internally used a FreePortScanner in integration tests within its own test suite. Furthermore, Spring Integration 2.2 provides similar support in a SocketUtils class in the spring-integration-test module. This commit introduces SocketUtils in spring-core to replace the FreePortScanner which was previously only used internally within Spring's test suite. This new implementation is inspired by both Spring Framework's FreePortScanner and Spring Integration's SocketUtils and consequently attempts to merge the best of both previous implementations. Issue: SPR-8032
This commit is contained in:
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.http.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
@@ -43,8 +40,10 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.tests.web.FreePortScanner;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public abstract class AbstractHttpRequestFactoryTestCase {
|
||||
|
||||
@@ -56,7 +55,7 @@ public abstract class AbstractHttpRequestFactoryTestCase {
|
||||
|
||||
@BeforeClass
|
||||
public static void startJettyServer() throws Exception {
|
||||
int port = FreePortScanner.getFreePort();
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
jettyServer = new Server(port);
|
||||
baseUrl = "http://localhost:" + port;
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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
|
||||
*
|
||||
* http://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.tests.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class that finds free BSD ports for use in testing scenario's.
|
||||
*
|
||||
* @author Ben Hale
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class FreePortScanner {
|
||||
|
||||
private static final int MIN_SAFE_PORT = 1024;
|
||||
|
||||
private static final int MAX_PORT = 65535;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the default range.
|
||||
*/
|
||||
public static int getFreePort() {
|
||||
return getFreePort(MIN_SAFE_PORT, MAX_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the given range.
|
||||
*/
|
||||
public static int getFreePort(int minPort, int maxPort) {
|
||||
Assert.isTrue(minPort > 0, "'minPort' must be larger than 0");
|
||||
Assert.isTrue(maxPort > minPort, "'maxPort' must be larger than minPort");
|
||||
int portRange = maxPort - minPort;
|
||||
int candidatePort;
|
||||
int searchCounter = 0;
|
||||
do {
|
||||
if (++searchCounter > portRange) {
|
||||
throw new IllegalStateException(
|
||||
String.format("There were no ports available in the range %d to %d", minPort, maxPort));
|
||||
}
|
||||
candidatePort = getRandomPort(minPort, portRange);
|
||||
}
|
||||
while (!isPortAvailable(candidatePort));
|
||||
|
||||
return candidatePort;
|
||||
}
|
||||
|
||||
private static int getRandomPort(int minPort, int portRange) {
|
||||
return minPort + random.nextInt(portRange);
|
||||
}
|
||||
|
||||
private static boolean isPortAvailable(int port) {
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
serverSocket = new ServerSocket();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to create ServerSocket.", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
InetSocketAddress sa = new InetSocketAddress(port);
|
||||
serverSocket.bind(sa);
|
||||
return true;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,14 +16,6 @@
|
||||
|
||||
package org.springframework.web.client;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
@@ -63,10 +55,12 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.tests.web.FreePortScanner;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
public class RestTemplateIntegrationTests {
|
||||
@@ -83,7 +77,7 @@ public class RestTemplateIntegrationTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void startJettyServer() throws Exception {
|
||||
int port = FreePortScanner.getFreePort();
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
jettyServer = new Server(port);
|
||||
baseUrl = "http://localhost:" + port;
|
||||
ServletContextHandler handler = new ServletContextHandler();
|
||||
@@ -243,6 +237,7 @@ public class RestTemplateIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void exchangeGet() throws Exception {
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
requestHeaders.set("MyHeader", "MyValue");
|
||||
|
||||
Reference in New Issue
Block a user