diff --git a/pom.xml b/pom.xml index aed0ac3..3ec91a4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + 4.0.0 @@ -58,7 +57,7 @@ 0.2.1 4.0.0-M8 - 2.3.18.Final + 2.3.13.Final @@ -96,11 +95,6 @@ org.junit.jupiter junit-jupiter-api - - org.assertj - assertj-core - test - @@ -110,8 +104,7 @@ maven-shade-plugin - + ch.fritteli.maze.server.Main diff --git a/src/main/java/ch/fritteli/maze/server/MazeServer.java b/src/main/java/ch/fritteli/maze/server/MazeServer.java index 84a1fcb..b41da69 100644 --- a/src/main/java/ch/fritteli/maze/server/MazeServer.java +++ b/src/main/java/ch/fritteli/maze/server/MazeServer.java @@ -18,11 +18,11 @@ public class MazeServer { private final Undertow undertow; private MazeServer(@NotNull final ServerConfig config) { - final String hostAddress = config.address().getHostAddress(); - final int port = config.port(); + final String hostAddress = config.getAddress().getHostAddress(); + final int port = config.getPort(); log.info("Starting Server at http://{}:{}/", hostAddress, port); final RoutingHandler routingHandler = new RoutingHandler() - .get(CreateHandler.PATH_TEMPLATE, new CreateHandler(config.maxMazeHeight(), config.maxMazeWidth())) + .get(CreateHandler.PATH_TEMPLATE, new CreateHandler()) .post(RenderV1Handler.PATH_TEMPLATE, new RenderV1Handler()) .post(RenderV2Handler.PATH_TEMPLATE, new RenderV2Handler()); @@ -47,7 +47,7 @@ public class MazeServer { private void start() { Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); this.undertow.start(); - final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().getFirst().getAddress(); + final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress(); final String hostAddress = address.getAddress().getHostAddress(); final int port = address.getPort(); diff --git a/src/main/java/ch/fritteli/maze/server/ServerConfig.java b/src/main/java/ch/fritteli/maze/server/ServerConfig.java index 401fd6d..ce25a6b 100644 --- a/src/main/java/ch/fritteli/maze/server/ServerConfig.java +++ b/src/main/java/ch/fritteli/maze/server/ServerConfig.java @@ -1,56 +1,42 @@ package ch.fritteli.maze.server; -import io.vavr.control.Option; import io.vavr.control.Try; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Value; import lombok.extern.slf4j.Slf4j; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.wildfly.common.annotation.NotNull; import java.net.InetAddress; +@AllArgsConstructor(access = AccessLevel.PRIVATE) @Slf4j -public record ServerConfig(@NotNull InetAddress address, - int port, - @NotNull Option maxMazeHeight, - @NotNull Option maxMazeWidth) { +@Value +public class ServerConfig { public static final String SYSPROP_HOST = "fritteli.maze.server.host"; public static final String SYSPROP_PORT = "fritteli.maze.server.port"; - public static final String SYSPROP_MAX_MAZE_HEIGHT = "fritteli.maze.maxheight"; - public static final String SYSPROP_MAX_MAZE_WIDTH = "fritteli.maze.maxwidth"; - public ServerConfig(@NotNull final InetAddress address, - final int port, - @NotNull final Option maxMazeHeight, - @NotNull final Option maxMazeWidth) { - this.address = address; + @NotNull + InetAddress address; + int port; + + public ServerConfig(@Nullable final String address, final int port) throws ConfigurationException { + this.address = validateAddress(address); this.port = validatePort(port); - this.maxMazeHeight = validateDimension(maxMazeHeight, "height"); - this.maxMazeWidth = validateDimension(maxMazeWidth, "width"); - log.debug("host={}, port={}, maxHeight={}, maxWidth={}", this.address, this.port, this.maxMazeHeight, this.maxMazeWidth); - } - - public ServerConfig(@Nullable final String address, - final int port, - @NotNull final Option maxMazeHeight, - @NotNull final Option maxMazeWidth) - throws ConfigurationException { - this(validateAddress(address), port, maxMazeHeight, maxMazeWidth); + log.debug("host={}, port={}", this.address, this.port); } @NotNull public static ServerConfig init() throws ConfigurationException { final String host = System.getProperty(SYSPROP_HOST); final String portString = System.getProperty(SYSPROP_PORT); - final String maxMazeHeightString = System.getProperty(SYSPROP_MAX_MAZE_HEIGHT); - final String maxMazeWidthString = System.getProperty(SYSPROP_MAX_MAZE_WIDTH); final int port = validatePort(portString); - final Option maxMazeHeight = validateDimension(maxMazeHeightString, "height", SYSPROP_MAX_MAZE_HEIGHT); - final Option maxMazeWidth = validateDimension(maxMazeWidthString, "width", SYSPROP_MAX_MAZE_WIDTH); - return new ServerConfig(host, port, maxMazeHeight, maxMazeWidth); + return new ServerConfig(host, port); } @NotNull - private static InetAddress validateAddress(@Nullable final String address) throws ConfigurationException { + private static InetAddress validateAddress(@Nullable final String address) { return Try.of(() -> InetAddress.getByName(address)) .getOrElseThrow(cause -> new ConfigurationException( "Invalid hostname/address: %s".formatted(address), @@ -58,48 +44,22 @@ public record ServerConfig(@NotNull InetAddress address, )); } - private static int validatePort(final int port) throws ConfigurationException { + private static int validatePort(final int port) { if (port < 0 || port > 0xFFFF) { throw new ConfigurationException("Port out of range (0..65535): %s".formatted(port)); } return port; } - private static int validatePort(@Nullable final String portString) throws ConfigurationException { + private static int validatePort(@Nullable final String portString) { if (portString == null) { log.info("No port configured; using default."); return 0; } - return Try.of(() -> Integer.parseInt(portString)) + return Try.of(() -> Integer.valueOf(portString)) .getOrElseThrow(cause -> new ConfigurationException( "Failed to parse port specified in system property '%s': %s".formatted(SYSPROP_PORT, portString), cause )); } - - @NotNull - private static Option validateDimension(@NotNull final Option dimension, - @NotNull final String identifier) { - if (dimension.exists(d -> d <= 1)) { - throw new ConfigurationException("Maximum %s must be greater than 1: %s" - .formatted(identifier, dimension.get())); - } - return dimension; - } - - private static Option validateDimension(@Nullable final String dimensionString, - @NotNull final String identifier, - @NotNull final String syspropName) { - if (dimensionString == null) { - log.info("No maximum {} configured; using default (unlimited).", identifier); - return Option.none(); - } - final int desiredDimension = Try.of(() -> Integer.parseInt(dimensionString)) - .getOrElseThrow(cause -> new ConfigurationException( - "Failed to parse maximum %s specified in system property '%s': %s" - .formatted(identifier, syspropName, dimensionString), - cause - )); - return Option.some(desiredDimension); - } } diff --git a/src/main/java/ch/fritteli/maze/server/handler/CreateHandler.java b/src/main/java/ch/fritteli/maze/server/handler/CreateHandler.java index 4d44ab2..a14954b 100644 --- a/src/main/java/ch/fritteli/maze/server/handler/CreateHandler.java +++ b/src/main/java/ch/fritteli/maze/server/handler/CreateHandler.java @@ -7,7 +7,6 @@ import io.undertow.server.HttpServerExchange; import io.undertow.util.Headers; import io.undertow.util.HttpString; import io.undertow.util.StatusCodes; -import io.vavr.control.Option; import io.vavr.control.Try; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -23,15 +22,6 @@ import java.util.Map; public class CreateHandler extends AbstractHttpHandler { public static final String PATH_TEMPLATE = "/create/{output}"; - @NotNull - private final Option maxHeight; - @NotNull - private final Option maxWidth; - - public CreateHandler(@NotNull final Option maxHeight, @NotNull final Option maxWidth) { - this.maxHeight = maxHeight; - this.maxWidth = maxWidth; - } @Override protected void handle(@NotNull final HttpServerExchange exchange) { @@ -39,11 +29,10 @@ public class CreateHandler extends AbstractHttpHandler { log.debug("Handling create request"); this.createMazeFromRequestParameters(exchange.getQueryParameters()) .onFailure(e -> { + log.error("Error creating maze from request", e); if (e instanceof InvalidRequestParameterException) { - log.debug("Error creating maze from request", e); exchange.setStatusCode(StatusCodes.BAD_REQUEST); } else { - log.error("Error creating maze from request", e); exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR); } exchange.getResponseSender() @@ -86,6 +75,6 @@ public class CreateHandler extends AbstractHttpHandler { @NotNull private Try createMazeFromRequestParameters(final Map> queryParameters) { - return new ParametersToMazeExtractor(queryParameters, this.maxHeight, this.maxWidth).createMaze(); + return new ParametersToMazeExtractor(queryParameters).createMaze(); } } diff --git a/src/main/java/ch/fritteli/maze/server/handler/ParametersToMazeExtractor.java b/src/main/java/ch/fritteli/maze/server/handler/ParametersToMazeExtractor.java index 6c747e5..bca9efa 100644 --- a/src/main/java/ch/fritteli/maze/server/handler/ParametersToMazeExtractor.java +++ b/src/main/java/ch/fritteli/maze/server/handler/ParametersToMazeExtractor.java @@ -20,10 +20,6 @@ class ParametersToMazeExtractor { @NotNull private final Map> queryParameters; - @NotNull - private final Option maxHeight; - @NotNull - private final Option maxWidth; @NotNull Try createMaze() { @@ -53,29 +49,12 @@ class ParametersToMazeExtractor { ))); } - final int desiredHeight = height.get(); - final int desiredWidth = width.get(); - - if (desiredHeight <= 1) { - return Try.failure(new InvalidRequestParameterException("Specified height (%s) must be > 1".formatted(desiredHeight))); - } - if (desiredWidth <= 1) { - return Try.failure(new InvalidRequestParameterException("Specified width (%s) must be > 1".formatted(desiredHeight))); - } - if (this.maxHeight.exists(max -> desiredHeight > max)) { - return Try.failure(new InvalidRequestParameterException("Specified height (%s) is greater than allowed maximum of %s".formatted(desiredHeight, this.maxHeight.get()))); - } - - if (this.maxWidth.exists(max -> desiredWidth > max)) { - return Try.failure(new InvalidRequestParameterException("Specified width (%s) is greater than allowed maximum of %s".formatted(desiredWidth, this.maxWidth.get()))); - } - return Try.of(() -> { final Maze maze; if (start.isDefined() && end.isDefined()) { - maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); + maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); } else { - maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong())); + maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong())); } new RandomDepthFirst(maze).run(); return new GeneratedMaze(maze, output.get(), RandomDepthFirst.class.getSimpleName()); diff --git a/src/test/java/ch/fritteli/maze/server/ServerConfigTest.java b/src/test/java/ch/fritteli/maze/server/ServerConfigTest.java index 68aae74..7760147 100644 --- a/src/test/java/ch/fritteli/maze/server/ServerConfigTest.java +++ b/src/test/java/ch/fritteli/maze/server/ServerConfigTest.java @@ -3,16 +3,16 @@ package ch.fritteli.maze.server; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import java.net.UnknownHostException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class ServerConfigTest { @BeforeEach void clearSysProperties() { System.clearProperty(ServerConfig.SYSPROP_HOST); System.clearProperty(ServerConfig.SYSPROP_PORT); - System.clearProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT); - System.clearProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH); } @Test @@ -22,27 +22,9 @@ class ServerConfigTest { final ServerConfig sut = ServerConfig.init(); // assert - assertThat(sut.address()) - .satisfies( - address -> assertThat(address.getHostAddress()).isEqualTo("127.0.0.1"), - address -> assertThat(address.getHostName()).isEqualTo("localhost") - ); - assertThat(sut.port()).isZero(); - assertThat(sut.maxMazeHeight()).isEmpty(); - assertThat(sut.maxMazeWidth()).isEmpty(); - } - - - @Test - void testInit_invalidAddress() { - // arrange - System.setProperty(ServerConfig.SYSPROP_HOST, "256.2515.19.0"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Invalid hostname/address") - .withMessageContaining("256.2515.19.0"); + assertEquals("127.0.0.1", sut.getAddress().getHostAddress()); + assertEquals("localhost", sut.getAddress().getHostName()); + assertEquals(0, sut.getPort()); } @Test @@ -51,101 +33,29 @@ class ServerConfigTest { System.setProperty(ServerConfig.SYSPROP_PORT, "Hello World!"); // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Failed to parse port") - .withMessageContaining("Hello World!"); + assertThrows(ConfigurationException.class, ServerConfig::init); } @Test - void testInit_invalidPortTooSmall() { - // arrange - System.setProperty(ServerConfig.SYSPROP_PORT, "-5"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Port out of range") - .withMessageContaining("-5"); - } - - @Test - void testInit_invalidPortTooLarge() { + void testInit_invalidPort() { // arrange System.setProperty(ServerConfig.SYSPROP_PORT, "99999"); // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Port out of range") - .withMessageContaining("99999"); + assertThrows(ConfigurationException.class, ServerConfig::init); } @Test - void testInit_unparseableMaxMazeHeight() { + void testInit() throws ConfigurationException, UnknownHostException { // arrange - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "Hello World!"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Failed to parse maximum height") - .withMessageContaining("Hello World!"); - - } - - @Test - void testInit_invalidMaxMazeHeight() { - // arrange - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "1"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Maximum height must be greater than 1:") - .withMessageEndingWith("1"); - } - - @Test - void testInit_unparseableMaxMazeWidth() { - // arrange - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "Hello World!"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Failed to parse maximum width") - .withMessageContaining("Hello World!"); - - } - - @Test - void testInit_invalidMaxMazeWidth() { - // arrange - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "-24"); - - // act / assert - assertThatExceptionOfType(ConfigurationException.class) - .isThrownBy(ServerConfig::init) - .withMessageContaining("Maximum width must be greater than 1:") - .withMessageContaining("-24"); - } - - @Test - void testInit() throws ConfigurationException { - // arrange - System.setProperty(ServerConfig.SYSPROP_HOST, "10.0.9.12"); + System.setProperty(ServerConfig.SYSPROP_HOST, "127.0.0.1"); System.setProperty(ServerConfig.SYSPROP_PORT, "12345"); - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "100"); - System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "42"); // act final ServerConfig sut = ServerConfig.init(); // assert - assertThat(sut.address().getHostAddress()).isEqualTo("10.0.9.12"); - assertThat(sut.port()).isEqualTo(12345); - assertThat(sut.maxMazeHeight()).singleElement().isEqualTo(100); - assertThat(sut.maxMazeWidth()).singleElement().isEqualTo(42); + assertEquals("127.0.0.1", sut.getAddress().getHostAddress()); + assertEquals(12345, sut.getPort()); } }