This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 3a7233cef82ff46706f78334cf227880ea160c39
Author: Rene Cordier <rcord...@linagora.com>
AuthorDate: Wed Mar 11 11:44:59 2020 +0700

    JAMES-3078 Reactor-Netty JMAPServer implementation
---
 core/src/main/java/org/apache/james/util/Port.java |  16 ++++
 .../test/java/org/apache/james/util/PortTest.java  |   9 ++
 server/protocols/jmap/pom.xml                      |  72 ++++++++++++++
 .../java/org/apache/james/jmap/HttpConstants.java  |  46 +--------
 .../org/apache/james/jmap/JMAPConfiguration.java   | 104 +++++++++++++++++++++
 .../java/org/apache/james/jmap/JMAPRoutes.java     |  60 ++++++++++++
 .../java/org/apache/james/jmap/JMAPServer.java     |  70 ++++++++++++++
 .../apache/james/jmap/JMAPConfigurationTest.java   |  87 +++++++++++++++++
 .../java/org/apache/james/jmap/JMAPServerTest.java |  87 +++++++++++++++++
 9 files changed, 510 insertions(+), 41 deletions(-)

diff --git a/core/src/main/java/org/apache/james/util/Port.java 
b/core/src/main/java/org/apache/james/util/Port.java
index 7f84202..90191d4 100644
--- a/core/src/main/java/org/apache/james/util/Port.java
+++ b/core/src/main/java/org/apache/james/util/Port.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.util;
 
+import java.util.Objects;
 import java.util.concurrent.ThreadLocalRandom;
 
 import com.google.common.base.Preconditions;
@@ -59,4 +60,19 @@ public class Port {
     public int getValue() {
         return value;
     }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof Port) {
+            Port indexName = (Port) o;
+
+            return Objects.equals(this.value, indexName.value);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(value);
+    }
 }
diff --git a/core/src/test/java/org/apache/james/util/PortTest.java 
b/core/src/test/java/org/apache/james/util/PortTest.java
index 793c162..b46acea 100644
--- a/core/src/test/java/org/apache/james/util/PortTest.java
+++ b/core/src/test/java/org/apache/james/util/PortTest.java
@@ -24,7 +24,16 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.junit.jupiter.api.Test;
 
+import nl.jqno.equalsverifier.EqualsVerifier;
+
 class PortTest {
+
+    @Test
+    void portShouldRespectBeanContract() {
+        EqualsVerifier.forClass(Port.class)
+            .verify();
+    }
+
     @Test
     void assertValidShouldThrowOnNegativePort() {
         assertThatThrownBy(() -> Port.assertValid(-1))
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
new file mode 100644
index 0000000..6116486
--- /dev/null
+++ b/server/protocols/jmap/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  * Licensed to the Apache Software Foundation (ASF) under one   *
+  * or more contributor license agreements.  See the NOTICE file *
+  * distributed with this work for additional information        *
+  * regarding copyright ownership.  The ASF licenses this file   *
+  * to you 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.                                           *
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>james-server</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>3.5.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>james-server-jmap</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-lifecycle-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>testing-base</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.projectreactor.netty</groupId>
+            <artifactId>reactor-netty</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/james/util/Port.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/HttpConstants.java
similarity index 50%
copy from core/src/main/java/org/apache/james/util/Port.java
copy to 
server/protocols/jmap/src/main/java/org/apache/james/jmap/HttpConstants.java
index 7f84202..ce50efa 100644
--- a/core/src/main/java/org/apache/james/util/Port.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/HttpConstants.java
@@ -17,46 +17,10 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.util;
+package org.apache.james.jmap;
 
-import java.util.concurrent.ThreadLocalRandom;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Range;
-
-public class Port {
-    public static final int MAX_PORT_VALUE = 65535;
-    public static final int PRIVILEGED_PORT_BOUND = 1024;
-    private static final Range<Integer> VALID_PORT_RANGE = Range.closed(1, 
MAX_PORT_VALUE);
-
-    public static Port of(int portNumber) {
-        return new Port(portNumber);
-    }
-
-    public static int generateValidUnprivilegedPort() {
-        return ThreadLocalRandom.current().nextInt(Port.MAX_PORT_VALUE - 
PRIVILEGED_PORT_BOUND) + PRIVILEGED_PORT_BOUND;
-    }
-
-    public static void assertValid(int port) {
-        Preconditions.checkArgument(isValid(port), "Port should be between 1 
and 65535");
-    }
-
-    public static boolean isValid(int port) {
-        return VALID_PORT_RANGE.contains(port);
-    }
-
-    private final int value;
-
-    public Port(int value) {
-        validate(value);
-        this.value = value;
-    }
-
-    protected void validate(int port) {
-        assertValid(port);
-    }
-
-    public int getValue() {
-        return value;
-    }
+public interface HttpConstants {
+    String JSON_CONTENT_TYPE = "application/json";
+    String JSON_CONTENT_TYPE_UTF8 = "application/json; charset=UTF-8";
+    String TEXT_PLAIN_CONTENT_TYPE = "text/plain";
 }
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
new file mode 100644
index 0000000..a54f012
--- /dev/null
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
@@ -0,0 +1,104 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.jmap;
+
+import java.util.Optional;
+
+import org.apache.james.util.Port;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class JMAPConfiguration {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private Optional<Boolean> enabled = Optional.empty();
+        private Optional<Boolean> wiretap = Optional.empty();
+        private Optional<Port> port = Optional.empty();
+
+        private Builder() {
+
+        }
+
+        public Builder enabled(boolean enabled) {
+            this.enabled = Optional.of(enabled);
+            return this;
+        }
+
+        public Builder wiretap() {
+            return wiretap(true);
+        }
+
+        public Builder wiretap(boolean enabled) {
+            this.wiretap = Optional.of(enabled);
+            return this;
+        }
+
+        public Builder enable() {
+            return enabled(true);
+        }
+
+        public Builder disable() {
+            return enabled(false);
+        }
+
+        public Builder port(Port port) {
+            this.port = Optional.of(port);
+            return this;
+        }
+
+        public Builder randomPort() {
+            this.port = Optional.empty();
+            return this;
+        }
+
+        public JMAPConfiguration build() {
+            Preconditions.checkState(enabled.isPresent(), "You should specify 
if JMAP server should be started");
+            return new JMAPConfiguration(enabled.get(), wiretap.orElse(false), 
port);
+        }
+
+    }
+
+    private final boolean enabled;
+    private final boolean wiretap;
+    private final Optional<Port> port;
+
+    @VisibleForTesting
+    JMAPConfiguration(boolean enabled, boolean wiretap, Optional<Port> port) {
+        this.enabled = enabled;
+        this.wiretap = wiretap;
+        this.port = port;
+    }
+
+    public boolean wiretapEnabled() {
+        return wiretap;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public Optional<Port> getPort() {
+        return port;
+    }
+}
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java
new file mode 100644
index 0000000..4c76901
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPRoutes.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.jmap;
+
+import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
+import static 
io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
+import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED;
+
+import java.util.function.BiFunction;
+
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+
+import reactor.core.publisher.Mono;
+import reactor.netty.http.server.HttpServerRequest;
+import reactor.netty.http.server.HttpServerResponse;
+import reactor.netty.http.server.HttpServerRoutes;
+
+public interface JMAPRoutes {
+    HttpServerRoutes define(HttpServerRoutes builder);
+
+    BiFunction<HttpServerRequest, HttpServerResponse, Publisher<Void>> 
CORS_CONTROL = (req, res) -> res.header("Access-Control-Allow-Origin", "*")
+        .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
+        .header("Access-Control-Allow-Headers", "Content-Type, Authorization, 
Accept")
+        .send();
+
+    Logger logger();
+
+    default Mono<Void> handleInternalError(HttpServerResponse response, 
Throwable e) {
+        logger().error("Internal error", e);
+        return response.status(INTERNAL_SERVER_ERROR).send();
+    }
+
+    default Mono<Void> handleBadRequest(HttpServerResponse response, Exception 
e) {
+        logger().warn("Invalid request received.", e);
+        return response.status(BAD_REQUEST).send();
+    }
+
+    default Mono<Void> handleAuthenticationFailure(HttpServerResponse 
response, Exception e) {
+        logger().warn("Unauthorized", e);
+        return response.status(UNAUTHORIZED).send();
+    }
+}
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
new file mode 100644
index 0000000..7b52ce1
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.jmap;
+
+import java.util.Optional;
+import java.util.Set;
+
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.apache.james.lifecycle.api.Startable;
+import org.apache.james.util.Port;
+
+import reactor.netty.DisposableServer;
+import reactor.netty.http.server.HttpServer;
+
+public class JMAPServer implements Startable {
+    private static final int RANDOM_PORT = 0;
+
+    private final JMAPConfiguration configuration;
+    private final Set<JMAPRoutes> jmapRoutes;
+    private Optional<DisposableServer> server;
+
+    @Inject
+    public JMAPServer(JMAPConfiguration configuration, Set<JMAPRoutes> 
jmapRoutes) {
+        this.configuration = configuration;
+        this.jmapRoutes = jmapRoutes;
+        this.server = Optional.empty();
+    }
+
+    public Port getPort() {
+        return server.map(DisposableServer::port)
+            .map(Port::of)
+            .orElseThrow(() -> new IllegalStateException("port is not 
available because server is not started or disabled"));
+    }
+
+    public void start() {
+        if (configuration.isEnabled()) {
+            server = Optional.of(HttpServer.create()
+                .port(configuration.getPort()
+                    .map(Port::getValue)
+                    .orElse(RANDOM_PORT))
+                .route(routes -> jmapRoutes.forEach(jmapRoute -> 
jmapRoute.define(routes)))
+                .wiretap(configuration.wiretapEnabled())
+                .bindNow());
+        }
+    }
+
+    @PreDestroy
+    public void stop() {
+        server.ifPresent(DisposableServer::disposeNow);
+    }
+}
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
new file mode 100644
index 0000000..a9d9c64
--- /dev/null
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
@@ -0,0 +1,87 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.jmap;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+import java.util.Optional;
+
+import org.apache.james.util.Port;
+import org.junit.jupiter.api.Test;
+
+class JMAPConfigurationTest {
+
+    public static final boolean ENABLED = true;
+    public static final boolean DISABLED = false;
+
+    @Test
+    void buildShouldThrowWhenEnableIsMissing() {
+        assertThatThrownBy(() -> JMAPConfiguration.builder().build())
+            .isInstanceOf(IllegalStateException.class)
+            .hasMessage("You should specify if JMAP server should be started");
+    }
+
+    @Test
+    void buildShouldWorkWhenRandomPort() {
+        JMAPConfiguration expectedJMAPConfiguration = new 
JMAPConfiguration(ENABLED, false, Optional.empty());
+
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .randomPort()
+            .build();
+        
assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
+    }
+
+    @Test
+    public void buildShouldWorkWhenFixedPort() {
+        JMAPConfiguration expectedJMAPConfiguration = new 
JMAPConfiguration(ENABLED, false, Optional.of(Port.of(80)));
+
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .port(Port.of(80))
+            .build();
+
+        
assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
+    }
+
+    @Test
+    public void buildShouldWorkWhenWiretap() {
+        JMAPConfiguration expectedJMAPConfiguration = new 
JMAPConfiguration(ENABLED, true, Optional.empty());
+
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .wiretap()
+            .randomPort()
+            .build();
+
+        
assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
+    }
+
+    @Test
+    public void buildShouldWorkWhenDisabled() {
+        JMAPConfiguration expectedJMAPConfiguration = new 
JMAPConfiguration(DISABLED, false, Optional.empty());
+
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .disable()
+            .build();
+        
assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
+    }
+}
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java
new file mode 100644
index 0000000..1c36384
--- /dev/null
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java
@@ -0,0 +1,87 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.jmap;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+class JMAPServerTest {
+    private static final JMAPConfiguration DISABLED_CONFIGURATION = 
JMAPConfiguration.builder().disable().build();
+    private static final JMAPConfiguration TEST_CONFIGURATION = 
JMAPConfiguration.builder()
+        .enable()
+        .randomPort()
+        .build();
+    private static final ImmutableSet<JMAPRoutes> NO_ROUTES = 
ImmutableSet.of();
+
+    @Test
+    void serverShouldAnswerWhenStarted() {
+        JMAPServer jmapServer = new JMAPServer(TEST_CONFIGURATION, NO_ROUTES);
+        jmapServer.start();
+
+        try {
+            given()
+                .port(jmapServer.getPort().getValue())
+                .basePath("http://localhost";)
+            .when()
+                .get()
+            .then()
+                .statusCode(404);
+        } finally {
+            jmapServer.stop();
+        }
+    }
+
+    @Test
+    void startShouldNotThrowWhenConfigurationDisabled() {
+        JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, 
NO_ROUTES);
+
+        assertThatCode(jmapServer::start).doesNotThrowAnyException();
+    }
+
+    @Test
+    void stopShouldNotThrowWhenConfigurationDisabled() {
+        JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, 
NO_ROUTES);
+        jmapServer.start();
+
+        assertThatCode(jmapServer::stop).doesNotThrowAnyException();
+    }
+
+    @Test
+    void getPortShouldThrowWhenServerIsNotStarted() {
+        JMAPServer jmapServer = new JMAPServer(TEST_CONFIGURATION, NO_ROUTES);
+
+        assertThatThrownBy(jmapServer::getPort)
+            .isInstanceOf(IllegalStateException.class);
+    }
+
+    @Test
+    void getPortShouldThrowWhenDisabledConfiguration() {
+        JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, 
NO_ROUTES);
+        jmapServer.start();
+
+        assertThatThrownBy(jmapServer::getPort)
+            .isInstanceOf(IllegalStateException.class);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org

Reply via email to