Merge branch '2.2.x'
Closes gh-21105
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.web.embedded.jetty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -174,8 +173,9 @@ public class JettyWebServer implements WebServer {
|
||||
connector.start();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (connector instanceof NetworkConnector && findBindException(ex) != null) {
|
||||
throw new PortInUseException(((NetworkConnector) connector).getPort(), ex);
|
||||
if (connector instanceof NetworkConnector) {
|
||||
PortInUseException.throwIfPortBindingException(ex,
|
||||
() -> ((NetworkConnector) connector).getPort());
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
@@ -195,16 +195,6 @@ public class JettyWebServer implements WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
private BindException findBindException(Throwable ex) {
|
||||
if (ex == null) {
|
||||
return null;
|
||||
}
|
||||
if (ex instanceof BindException) {
|
||||
return (BindException) ex;
|
||||
}
|
||||
return findBindException(ex.getCause());
|
||||
}
|
||||
|
||||
private String getActualPortsDescription() {
|
||||
StringBuilder ports = new StringBuilder();
|
||||
for (Connector connector : this.server.getConnectors()) {
|
||||
|
||||
@@ -116,10 +116,11 @@ public class NettyWebServer implements WebServer {
|
||||
this.disposableServer = startHttpServer();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ChannelBindException bindException = findBindException(ex);
|
||||
if (bindException != null && !isPermissionDenied(bindException.getCause())) {
|
||||
throw new PortInUseException(bindException.localPort(), ex);
|
||||
}
|
||||
PortInUseException.ifCausedBy(ex, ChannelBindException.class, (bindException) -> {
|
||||
if (!isPermissionDenied(bindException.getCause())) {
|
||||
throw new PortInUseException(bindException.localPort(), ex);
|
||||
}
|
||||
});
|
||||
throw new WebServerException("Unable to start Netty", ex);
|
||||
}
|
||||
logger.info("Netty started on port(s): " + getPort());
|
||||
@@ -168,17 +169,6 @@ public class NettyWebServer implements WebServer {
|
||||
routes.route(ALWAYS, this.handler);
|
||||
}
|
||||
|
||||
private ChannelBindException findBindException(Exception ex) {
|
||||
Throwable candidate = ex;
|
||||
while (candidate != null) {
|
||||
if (candidate instanceof ChannelBindException) {
|
||||
return (ChannelBindException) candidate;
|
||||
}
|
||||
candidate = candidate.getCause();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void startDaemonAwaitThread(DisposableServer disposableServer) {
|
||||
Thread awaitThread = new Thread("server") {
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.web.embedded.tomcat;
|
||||
|
||||
import java.net.BindException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -226,9 +225,7 @@ public class TomcatWebServer implements WebServer {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (findBindException(ex) != null) {
|
||||
throw new PortInUseException(this.tomcat.getConnector().getPort());
|
||||
}
|
||||
PortInUseException.throwIfPortBindingException(ex, () -> this.tomcat.getConnector().getPort());
|
||||
throw new WebServerException("Unable to start embedded Tomcat server", ex);
|
||||
}
|
||||
finally {
|
||||
@@ -251,16 +248,6 @@ public class TomcatWebServer implements WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
private BindException findBindException(Throwable ex) {
|
||||
if (ex == null) {
|
||||
return null;
|
||||
}
|
||||
if (ex instanceof BindException) {
|
||||
return (BindException) ex;
|
||||
}
|
||||
return findBindException(ex.getCause());
|
||||
}
|
||||
|
||||
private void stopSilently() {
|
||||
try {
|
||||
stopTomcat();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.boot.web.embedded.undertow;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.BindException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.time.Duration;
|
||||
@@ -173,14 +172,13 @@ public class UndertowServletWebServer implements WebServer {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
try {
|
||||
if (findBindException(ex) != null) {
|
||||
PortInUseException.ifPortBindingException(ex, (bindException) -> {
|
||||
List<Port> failedPorts = getConfiguredPorts();
|
||||
List<Port> actualPorts = getActualPorts();
|
||||
failedPorts.removeAll(actualPorts);
|
||||
failedPorts.removeAll(getActualPorts());
|
||||
if (failedPorts.size() == 1) {
|
||||
throw new PortInUseException(failedPorts.iterator().next().getNumber(), ex);
|
||||
throw new PortInUseException(failedPorts.get(0).getNumber());
|
||||
}
|
||||
}
|
||||
});
|
||||
throw new WebServerException("Unable to start embedded Undertow", ex);
|
||||
}
|
||||
finally {
|
||||
@@ -207,17 +205,6 @@ public class UndertowServletWebServer implements WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
private BindException findBindException(Exception ex) {
|
||||
Throwable candidate = ex;
|
||||
while (candidate != null) {
|
||||
if (candidate instanceof BindException) {
|
||||
return (BindException) candidate;
|
||||
}
|
||||
candidate = candidate.getCause();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Undertow createUndertowServer() throws ServletException {
|
||||
HttpHandler httpHandler = this.manager.start();
|
||||
httpHandler = getContextHandler(httpHandler);
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.boot.web.embedded.undertow;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.BindException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
@@ -121,14 +120,13 @@ public class UndertowWebServer implements WebServer {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
try {
|
||||
if (findBindException(ex) != null) {
|
||||
List<UndertowWebServer.Port> failedPorts = getConfiguredPorts();
|
||||
List<UndertowWebServer.Port> actualPorts = getActualPorts();
|
||||
failedPorts.removeAll(actualPorts);
|
||||
PortInUseException.ifPortBindingException(ex, (bindException) -> {
|
||||
List<Port> failedPorts = getConfiguredPorts();
|
||||
failedPorts.removeAll(getActualPorts());
|
||||
if (failedPorts.size() == 1) {
|
||||
throw new PortInUseException(failedPorts.iterator().next().getNumber(), ex);
|
||||
throw new PortInUseException(failedPorts.get(0).getNumber());
|
||||
}
|
||||
}
|
||||
});
|
||||
throw new WebServerException("Unable to start embedded Undertow", ex);
|
||||
}
|
||||
finally {
|
||||
@@ -150,17 +148,6 @@ public class UndertowWebServer implements WebServer {
|
||||
}
|
||||
}
|
||||
|
||||
private BindException findBindException(Exception ex) {
|
||||
Throwable candidate = ex;
|
||||
while (candidate != null) {
|
||||
if (candidate instanceof BindException) {
|
||||
return (BindException) candidate;
|
||||
}
|
||||
candidate = candidate.getCause();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getPortsDescription() {
|
||||
List<UndertowWebServer.Port> ports = getActualPorts();
|
||||
if (!ports.isEmpty()) {
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package org.springframework.boot.web.server;
|
||||
|
||||
import java.net.BindException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
/**
|
||||
* A {@code PortInUseException} is thrown when a web server fails to start due to a port
|
||||
* already being in use.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class PortInUseException extends WebServerException {
|
||||
@@ -53,4 +58,53 @@ public class PortInUseException extends WebServerException {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a {@link PortInUseException} if the given exception was caused by a "port in
|
||||
* use" {@link BindException}.
|
||||
* @param ex the source exception
|
||||
* @param port a suppler used to provide the port
|
||||
* @since 2.2.7
|
||||
*/
|
||||
public static void throwIfPortBindingException(Exception ex, IntSupplier port) {
|
||||
ifPortBindingException(ex, (bindException) -> {
|
||||
throw new PortInUseException(port.getAsInt(), ex);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an action if the given exception was caused by a "port in use"
|
||||
* {@link BindException}.
|
||||
* @param ex the source exception
|
||||
* @param action the action to perform
|
||||
* @since 2.2.7
|
||||
*/
|
||||
public static void ifPortBindingException(Exception ex, Consumer<BindException> action) {
|
||||
ifCausedBy(ex, BindException.class, (bindException) -> {
|
||||
// bind exception can be also thrown because an address can't be assigned
|
||||
if (bindException.getMessage().toLowerCase().contains("in use")) {
|
||||
action.accept(bindException);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an action if the given exception was caused by a specific exception type.
|
||||
* @param <E> the cause exception type
|
||||
* @param ex the source exception
|
||||
* @param causedBy the required cause type
|
||||
* @param action the action to perform
|
||||
* @since 2.2.7
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E extends Exception> void ifCausedBy(Exception ex, Class<E> causedBy, Consumer<E> action) {
|
||||
Throwable candidate = ex;
|
||||
while (candidate != null) {
|
||||
if (causedBy.isInstance(candidate)) {
|
||||
action.accept((E) candidate);
|
||||
return;
|
||||
}
|
||||
candidate = candidate.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.ServerSocket;
|
||||
@@ -112,6 +113,7 @@ import org.springframework.boot.testsupport.web.servlet.ExampleServlet;
|
||||
import org.springframework.boot.web.server.Compression;
|
||||
import org.springframework.boot.web.server.ErrorPage;
|
||||
import org.springframework.boot.web.server.MimeMappings;
|
||||
import org.springframework.boot.web.server.PortInUseException;
|
||||
import org.springframework.boot.web.server.Shutdown;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
import org.springframework.boot.web.server.Ssl.ClientAuth;
|
||||
@@ -919,6 +921,16 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void malformedAddress() throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
factory.setAddress(InetAddress.getByName("123456"));
|
||||
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> {
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
}).isNotInstanceOf(PortInUseException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void localeCharsetMappingsAreConfigured() {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
|
||||
Reference in New Issue
Block a user