You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2017/04/21 03:57:05 UTC
[06/17] james-project git commit: JAMES-2004 Starting JMAP should be
made optional, as well as providing it's configuration file
JAMES-2004 Starting JMAP should be made optional, as well as providing it's configuration file
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/67e769c1
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/67e769c1
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/67e769c1
Branch: refs/heads/master
Commit: 67e769c1db3bc99301fce3a44a59a2857a475c7c
Parents: 445680d
Author: benwa <bt...@linagora.com>
Authored: Tue Apr 18 08:35:59 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Fri Apr 21 08:27:36 2017 +0700
----------------------------------------------------------------------
.../destination/conf/jmap.properties | 2 +
.../cassandra/destination/conf/jmap.properties | 2 +
.../sample-configuration/jmap.properties | 2 +
.../java/org/apache/james/jmap/JMAPModule.java | 16 ++++-
.../modules/protocols/JMAPServerModule.java | 16 +++--
.../james/modules/TestJMAPServerModule.java | 1 +
.../apache/james/jmap/JMAPConfiguration.java | 35 +++++++---
.../java/org/apache/james/jmap/JMAPServer.java | 73 ++++++++++----------
.../james/jmap/JMAPConfigurationTest.java | 28 +++++++-
.../crypto/JamesSignatureHandlerProvider.java | 1 +
10 files changed, 122 insertions(+), 54 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/dockerfiles/run/guice/cassandra-ldap/destination/conf/jmap.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/jmap.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/jmap.properties
index 34ab451..63e6702 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/jmap.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/jmap.properties
@@ -1,5 +1,7 @@
# Configuration file for JMAP
+enabled=true
+
tls.keystoreURL=file://conf/keystore
tls.secret=james72laBalle
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/dockerfiles/run/guice/cassandra/destination/conf/jmap.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/jmap.properties b/dockerfiles/run/guice/cassandra/destination/conf/jmap.properties
index 34ab451..63e6702 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/jmap.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/jmap.properties
@@ -1,5 +1,7 @@
# Configuration file for JMAP
+enabled=true
+
tls.keystoreURL=file://conf/keystore
tls.secret=james72laBalle
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/container/guice/memory-guice/sample-configuration/jmap.properties
----------------------------------------------------------------------
diff --git a/server/container/guice/memory-guice/sample-configuration/jmap.properties b/server/container/guice/memory-guice/sample-configuration/jmap.properties
index 071bafb..709ed8e 100644
--- a/server/container/guice/memory-guice/sample-configuration/jmap.properties
+++ b/server/container/guice/memory-guice/sample-configuration/jmap.properties
@@ -1,5 +1,7 @@
# Configuration file for JMAP
+enabled=true
+
tls.keystoreURL=file://conf/keystore
tls.secret=james72laBalle
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
index de72639..86f3f5e 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.james.jmap;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
@@ -44,6 +45,8 @@ import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
import org.apache.james.transport.matchers.RecipientIsLocal;
import org.apache.james.utils.ConfigurationPerformer;
import org.apache.james.utils.PropertiesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.github.fge.lambdas.Throwing;
import com.google.common.base.Charsets;
@@ -58,6 +61,7 @@ import com.google.inject.multibindings.Multibinder;
public class JMAPModule extends AbstractModule {
private static final int DEFAULT_JMAP_PORT = 80;
+ private static final Logger LOGGER = LoggerFactory.getLogger(JMAPModule.class);
@Override
protected void configure() {
@@ -82,13 +86,21 @@ public class JMAPModule extends AbstractModule {
@Provides
@Singleton
JMAPConfiguration provideConfiguration(PropertiesProvider propertiesProvider, FileSystem fileSystem) throws ConfigurationException, IOException{
- PropertiesConfiguration configuration = propertiesProvider.getConfiguration("jmap");
- return JMAPConfiguration.builder()
+ try {
+ PropertiesConfiguration configuration = propertiesProvider.getConfiguration("jmap");
+ return JMAPConfiguration.builder()
+ .enabled(configuration.getBoolean("enabled", true))
.keystore(configuration.getString("tls.keystoreURL"))
.secret(configuration.getString("tls.secret"))
.jwtPublicKeyPem(loadPublicKey(fileSystem, Optional.ofNullable(configuration.getString("jwt.publickeypem.url"))))
.port(configuration.getInt("jmap.port", DEFAULT_JMAP_PORT))
.build();
+ } catch (FileNotFoundException e) {
+ LOGGER.warn("Could not find JMAP configuration file. JMAP server will not be enabled.");
+ return JMAPConfiguration.builder()
+ .disable()
+ .build();
+ }
}
@Provides
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/container/guice/protocols/jmap/src/main/java/org/apache/james/modules/protocols/JMAPServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/modules/protocols/JMAPServerModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/modules/protocols/JMAPServerModule.java
index a04e1db..aa1cc00 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/modules/protocols/JMAPServerModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/modules/protocols/JMAPServerModule.java
@@ -22,6 +22,8 @@ package org.apache.james.modules.protocols;
import java.security.Security;
import java.util.List;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.james.jmap.JMAPConfiguration;
import org.apache.james.jmap.JMAPModule;
import org.apache.james.jmap.JMAPServer;
import org.apache.james.jmap.crypto.JamesSignatureHandler;
@@ -40,6 +42,8 @@ import com.google.inject.multibindings.Multibinder;
public class JMAPServerModule extends AbstractModule {
+ private static final HierarchicalConfiguration NULL_CONFIGURATION = null;
+
@Override
protected void configure() {
install(new JMAPModule());
@@ -52,19 +56,23 @@ public class JMAPServerModule extends AbstractModule {
private final JMAPServer server;
private final JamesSignatureHandler signatureHandler;
+ private final JMAPConfiguration jmapConfiguration;
@Inject
- public JMAPModuleConfigurationPerformer(JMAPServer server, JamesSignatureHandler signatureHandler) {
+ public JMAPModuleConfigurationPerformer(JMAPServer server, JamesSignatureHandler signatureHandler, JMAPConfiguration jmapConfiguration) {
this.server = server;
this.signatureHandler = signatureHandler;
+ this.jmapConfiguration = jmapConfiguration;
}
@Override
public void initModule() {
try {
- signatureHandler.init();
- server.configure(null);
- registerPEMWithSecurityProvider();
+ if (jmapConfiguration.isEnabled()) {
+ signatureHandler.init();
+ server.configure(NULL_CONFIGURATION);
+ registerPEMWithSecurityProvider();
+ }
} catch (Exception e) {
Throwables.propagate(e);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
index 6512fac..f23d3b6 100644
--- a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
+++ b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
@@ -59,6 +59,7 @@ public class TestJMAPServerModule extends AbstractModule{
@Singleton
JMAPConfiguration provideConfiguration() throws FileNotFoundException, ConfigurationException{
return JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("james72laBalle")
.jwtPublicKeyPem(Optional.of(PUBLIC_PEM_KEY))
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
----------------------------------------------------------------------
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
index 35d0496..e194e0f 100644
--- 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
@@ -33,18 +33,30 @@ public class JMAPConfiguration {
public static class Builder {
private String keystore;
private String secret;
- private Optional<String> jwtPublicKeyPem;
+ private Optional<Boolean> enabled = Optional.empty();
+ private Optional<String> jwtPublicKeyPem = Optional.empty();
private Optional<Integer> port = Optional.empty();
- private Builder() {
- jwtPublicKeyPem = Optional.empty();
- }
+ private Builder() {}
public Builder keystore(String keystore) {
this.keystore = keystore;
return this;
}
+ public Builder enabled(boolean enabled) {
+ this.enabled = Optional.of(enabled);
+ return this;
+ }
+
+ public Builder enable() {
+ return enabled(true);
+ }
+
+ public Builder disable() {
+ return enabled(false);
+ }
+
public Builder secret(String secret) {
this.secret = secret;
return this;
@@ -67,24 +79,31 @@ public class JMAPConfiguration {
}
public JMAPConfiguration build() {
- Preconditions.checkState(!Strings.isNullOrEmpty(keystore), "'keystore' is mandatory");
- Preconditions.checkState(!Strings.isNullOrEmpty(secret), "'secret' is mandatory");
- return new JMAPConfiguration(keystore, secret, jwtPublicKeyPem, port);
+ Preconditions.checkState(enabled.isPresent(), "You should specify if JMAP server should be started");
+ Preconditions.checkState(!enabled.get() || !Strings.isNullOrEmpty(keystore), "'keystore' is mandatory");
+ Preconditions.checkState(!enabled.get() || !Strings.isNullOrEmpty(secret), "'secret' is mandatory");
+ return new JMAPConfiguration(enabled.get(), keystore, secret, jwtPublicKeyPem, port);
}
}
+ private final boolean enabled;
private final String keystore;
private final String secret;
private final Optional<String> jwtPublicKeyPem;
private final Optional<Integer> port;
- @VisibleForTesting JMAPConfiguration(String keystore, String secret, Optional<String> jwtPublicKeyPem, Optional<Integer> port) {
+ @VisibleForTesting JMAPConfiguration(boolean enabled, String keystore, String secret, Optional<String> jwtPublicKeyPem, Optional<Integer> port) {
+ this.enabled = enabled;
this.keystore = keystore;
this.secret = secret;
this.jwtPublicKeyPem = jwtPublicKeyPem;
this.port = port;
}
+ public boolean isEnabled() {
+ return enabled;
+ }
+
public String getKeystore() {
return keystore;
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPServer.java
----------------------------------------------------------------------
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
index de3ac75..a6ac629 100644
--- 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
@@ -21,6 +21,8 @@ package org.apache.james.jmap;
import static org.apache.james.jmap.BypassAuthOnRequestMethod.bypass;
+import java.util.Optional;
+
import javax.annotation.PreDestroy;
import javax.inject.Inject;
@@ -31,42 +33,45 @@ import org.apache.james.http.jetty.Configuration.Builder;
import org.apache.james.http.jetty.JettyHttpServer;
import org.apache.james.lifecycle.api.Configurable;
-import com.google.common.base.Throwables;
+import com.github.fge.lambdas.Throwing;
public class JMAPServer implements Configurable {
- private final JettyHttpServer server;
+ private final Optional<JettyHttpServer> server;
@Inject
private JMAPServer(JMAPConfiguration jmapConfiguration,
AuthenticationServlet authenticationServlet, JMAPServlet jmapServlet, DownloadServlet downloadServlet, UploadServlet uploadServlet,
AuthenticationFilter authenticationFilter, UserProvisioningFilter userProvisioningFilter, DefaultMailboxesProvisioningFilter defaultMailboxesProvisioningFilter) {
-
- server = JettyHttpServer.create(
+ if (jmapConfiguration.isEnabled()) {
+ server = Optional.of(JettyHttpServer.create(
configurationBuilderFor(jmapConfiguration)
- .serve(JMAPUrls.AUTHENTICATION)
- .with(authenticationServlet)
- .filter(JMAPUrls.AUTHENTICATION)
- .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("POST").and("OPTIONS").only()))
- .only()
- .serve(JMAPUrls.JMAP)
- .with(jmapServlet)
- .filter(JMAPUrls.JMAP)
- .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
- .and(userProvisioningFilter)
- .and(defaultMailboxesProvisioningFilter)
- .only()
- .serveAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
- .with(downloadServlet)
- .filterAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
- .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
- .only()
- .serve(JMAPUrls.UPLOAD)
- .with(uploadServlet)
- .filterAsOneLevelTemplate(JMAPUrls.UPLOAD)
- .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
- .only()
- .build());
+ .serve(JMAPUrls.AUTHENTICATION)
+ .with(authenticationServlet)
+ .filter(JMAPUrls.AUTHENTICATION)
+ .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("POST").and("OPTIONS").only()))
+ .only()
+ .serve(JMAPUrls.JMAP)
+ .with(jmapServlet)
+ .filter(JMAPUrls.JMAP)
+ .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
+ .and(userProvisioningFilter)
+ .and(defaultMailboxesProvisioningFilter)
+ .only()
+ .serveAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
+ .with(downloadServlet)
+ .filterAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
+ .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
+ .only()
+ .serve(JMAPUrls.UPLOAD)
+ .with(uploadServlet)
+ .filterAsOneLevelTemplate(JMAPUrls.UPLOAD)
+ .with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
+ .only()
+ .build()));
+ } else {
+ server = Optional.empty();
+ }
}
private Builder configurationBuilderFor(JMAPConfiguration jmapConfiguration) {
@@ -81,23 +86,15 @@ public class JMAPServer implements Configurable {
@Override
public void configure(HierarchicalConfiguration config) throws ConfigurationException {
- try {
- server.start();
- } catch (Exception e) {
- Throwables.propagate(e);
- }
+ server.ifPresent(Throwing.consumer(JettyHttpServer::start).sneakyThrow());
}
@PreDestroy
public void stop() {
- try {
- server.stop();
- } catch (Exception e) {
- Throwables.propagate(e);
- }
+ server.ifPresent(Throwing.consumer(JettyHttpServer::stop).sneakyThrow());
}
public int getPort() {
- return server.getPort();
+ return server.map(JettyHttpServer::getPort).orElseThrow(() -> new RuntimeException("JMAP server was disabled. No port bound"));
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
----------------------------------------------------------------------
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
index e7a427e..4ffce68 100644
--- 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
@@ -28,9 +28,13 @@ import org.junit.Test;
public class JMAPConfigurationTest {
+ public static final boolean ENABLED = true;
+ public static final boolean DISABLED = false;
+
@Test
public void buildShouldThrowWhenKeystoreIsNull() {
assertThatThrownBy(() -> JMAPConfiguration.builder()
+ .enable()
.keystore(null)
.build())
.isInstanceOf(IllegalStateException.class)
@@ -40,6 +44,7 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldThrowWhenKeystoreIsEmpty() {
assertThatThrownBy(() -> JMAPConfiguration.builder()
+ .enable()
.keystore("")
.build())
.isInstanceOf(IllegalStateException.class)
@@ -49,6 +54,7 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldThrowWhenSecretIsNull() {
assertThatThrownBy(() -> JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret(null)
.build())
@@ -59,6 +65,7 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldThrowWhenSecretIsEmpty() {
assertThatThrownBy(() -> JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("")
.build())
@@ -69,6 +76,7 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldThrowWhenJwtPublicKeyPemIsNull() {
assertThatThrownBy(() -> JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("secret")
.jwtPublicKeyPem(null)
@@ -78,9 +86,10 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldWorkWhenRandomPort() {
- JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration("keystore", "secret", Optional.of("file://conf/jwt_publickey"), Optional.empty());
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, "keystore", "secret", Optional.of("file://conf/jwt_publickey"), Optional.empty());
JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("secret")
.jwtPublicKeyPem(Optional.of("file://conf/jwt_publickey"))
@@ -91,9 +100,10 @@ public class JMAPConfigurationTest {
@Test
public void buildShouldWorkWhenFixedPort() {
- JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration("keystore", "secret", Optional.of("file://conf/jwt_publickey"), Optional.of(80));
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, "keystore", "secret", Optional.of("file://conf/jwt_publickey"), Optional.of(80));
JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("secret")
.jwtPublicKeyPem(Optional.of("file://conf/jwt_publickey"))
@@ -101,4 +111,18 @@ public class JMAPConfigurationTest {
.build();
assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
}
+
+ @Test
+ public void buildShouldWorkWhenDisabled() {
+ String keystore = null;
+ String secret = null;
+ Optional<String> jwtPublicKeyPem = Optional.empty();
+ Optional<Integer> port = Optional.empty();
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(DISABLED, keystore, secret, jwtPublicKeyPem, port);
+
+ JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+ .disable()
+ .build();
+ assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration);
+ }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/67e769c1/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
index 06e3bd3..f3d0656 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
@@ -48,6 +48,7 @@ public class JamesSignatureHandlerProvider {
};
JamesSignatureHandler signatureHandler = new JamesSignatureHandler(fileSystem,
JMAPConfiguration.builder()
+ .enable()
.keystore("keystore")
.secret("james72laBalle")
.build());
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org