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

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

commit 18bb63c4b1bc53e03652246050e249193dcfecb6
Author: Tran Tien Duc <[email protected]>
AuthorDate: Wed Jun 26 16:43:38 2019 +0700

    JAMES-2806 Make namespace(defaultBucketName) configuration become optional
---
 .../ObjectStorageBlobConfiguration.java            | 30 ++++++++++------------
 .../ObjectStorageBlobConfigurationTest.java        | 29 +++++++++++++++++++--
 .../objectstorage/aws/s3/DockerAwsS3TestRule.java  |  3 ++-
 .../objectstorage/swift/DockerSwiftTestRule.java   |  2 +-
 .../swift/ObjectStorageBlobConfigurationTest.java  |  6 ++---
 .../swift/ObjectStorageBlobStoreModuleTest.java    |  6 ++---
 .../swift/SwiftObjectStorageTest.java              | 12 ++++-----
 7 files changed, 56 insertions(+), 32 deletions(-)

diff --git 
a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
 
b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
index f1fb395..05d0193 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
@@ -46,8 +46,8 @@ public class ObjectStorageBlobConfiguration {
 
     public static ObjectStorageBlobConfiguration from(Configuration 
configuration) throws ConfigurationException {
         String provider = configuration.getString(OBJECTSTORAGE_PROVIDER, 
null);
-        String namespace = configuration.getString(OBJECTSTORAGE_NAMESPACE, 
null);
         String codecName = 
configuration.getString(OBJECTSTORAGE_PAYLOAD_CODEC, null);
+        Optional<String> namespace = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_NAMESPACE, null));
         Optional<String> aesSalt = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_AES256_HEXSALT, 
null));
         Optional<char[]> aesPassword = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_AES256_PASSWORD, 
null))
             .map(String::toCharArray);
@@ -55,9 +55,6 @@ public class ObjectStorageBlobConfiguration {
         if (Strings.isNullOrEmpty(provider)) {
             throw new ConfigurationException("Mandatory configuration value " 
+ OBJECTSTORAGE_PROVIDER + " is missing from " + 
OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
         }
-        if (Strings.isNullOrEmpty(namespace)) {
-            throw new ConfigurationException("Mandatory configuration value " 
+ OBJECTSTORAGE_NAMESPACE + " is missing from " + 
OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
-        }
         if (Strings.isNullOrEmpty(codecName)) {
             throw new ConfigurationException("Mandatory configuration value " 
+ OBJECTSTORAGE_PAYLOAD_CODEC  + " is missing from " + 
OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
         }
@@ -70,10 +67,10 @@ public class ObjectStorageBlobConfiguration {
         return builder()
             .codec(payloadCodecFactory)
             .provider(ObjectStorageProvider.from(provider))
-            .bucketName(BucketName.of(namespace))
             .authConfiguration(authConfiguration(provider, configuration))
             .aesSalt(aesSalt)
             .aesPassword(aesPassword)
+            .defaultBucketName(namespace.map(BucketName::of))
             .build();
     }
 
@@ -88,7 +85,7 @@ public class ObjectStorageBlobConfiguration {
     }
 
     public static Builder.RequirePayloadCodec builder() {
-        return payloadCodec -> provider -> container -> authConfiguration -> 
new Builder.ReadyToBuild(payloadCodec, provider, container, authConfiguration);
+        return payloadCodec -> provider -> authConfiguration -> new 
Builder.ReadyToBuild(payloadCodec, provider, authConfiguration);
     }
 
     public interface Builder {
@@ -99,12 +96,7 @@ public class ObjectStorageBlobConfiguration {
 
         @FunctionalInterface
         interface RequireProvider {
-            RequireContainerName provider(ObjectStorageProvider provider);
-        }
-
-        @FunctionalInterface
-        interface RequireContainerName {
-            RequireAuthConfiguration bucketName(BucketName bucketName);
+            RequireAuthConfiguration provider(ObjectStorageProvider provider);
         }
 
         @FunctionalInterface
@@ -116,22 +108,21 @@ public class ObjectStorageBlobConfiguration {
 
             private final PayloadCodecFactory payloadCodecFactory;
             private final ObjectStorageProvider provider;
-            private final BucketName bucketName;
             private final SpecificAuthConfiguration specificAuthConfiguration;
 
             private Optional<String> aesSalt;
             private Optional<char[]> aesPassword;
+            private Optional<BucketName> defaultBucketName;
 
             public ReadyToBuild(PayloadCodecFactory payloadCodecFactory,
                                 ObjectStorageProvider provider,
-                                BucketName bucketName,
                                 SpecificAuthConfiguration 
specificAuthConfiguration) {
                 this.aesSalt = Optional.empty();
                 this.aesPassword = Optional.empty();
                 this.payloadCodecFactory = payloadCodecFactory;
                 this.provider = provider;
-                this.bucketName = bucketName;
                 this.specificAuthConfiguration = specificAuthConfiguration;
+                this.defaultBucketName = Optional.empty();
             }
 
             public ReadyToBuild aesSalt(String aesSalt) {
@@ -152,6 +143,11 @@ public class ObjectStorageBlobConfiguration {
                 return this;
             }
 
+            public ReadyToBuild defaultBucketName(Optional<BucketName> 
defaultBucketName) {
+                this.defaultBucketName = defaultBucketName;
+                return this;
+            }
+
             public ObjectStorageBlobConfiguration build() {
                 if (payloadCodecFactory == PayloadCodecFactory.AES256) {
                     aesSalt.filter(s -> !s.isEmpty())
@@ -160,7 +156,9 @@ public class ObjectStorageBlobConfiguration {
                         .orElseThrow(() -> new IllegalStateException("AES code 
requires an non-empty password parameter"));
                 }
 
-                return new ObjectStorageBlobConfiguration(payloadCodecFactory, 
provider, bucketName, specificAuthConfiguration, aesSalt, aesPassword);
+                BucketName defaultBucketName = 
this.defaultBucketName.orElse(BucketName.DEFAULT);
+
+                return new ObjectStorageBlobConfiguration(payloadCodecFactory, 
provider, defaultBucketName, specificAuthConfiguration, aesSalt, aesPassword);
             }
 
         }
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
index 4d2798f..30578bc 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
@@ -8,6 +8,7 @@ import java.util.stream.Stream;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.MapConfiguration;
+import org.apache.james.blob.api.BucketName;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -22,7 +23,6 @@ class ObjectStorageBlobConfigurationTest {
 
     static final ImmutableMap<String, Object> CONFIGURATION_WITHOUT_CODEC = 
ImmutableMap.<String, Object>builder()
         .put("objectstorage.provider", "swift")
-        .put("objectstorage.namespace", "foo")
         .put("objectstorage.swift.authapi", "tmpauth")
         .put("objectstorage.swift.endpoint", "http://swift/endpoint";)
         .put("objectstorage.swift.credentials", "testing")
@@ -40,7 +40,7 @@ class ObjectStorageBlobConfigurationTest {
     static class RequiredParameters implements ArgumentsProvider {
         @Override
         public Stream<? extends Arguments> provideArguments(ExtensionContext 
context) {
-            return Stream.of("objectstorage.provider", 
"objectstorage.namespace", "objectstorage.swift.authapi", 
"objectstorage.payload.codec")
+            return Stream.of("objectstorage.provider", 
"objectstorage.swift.authapi", "objectstorage.payload.codec")
                     .map(Arguments::of);
         }
     }
@@ -156,4 +156,29 @@ class ObjectStorageBlobConfigurationTest {
             .isInstanceOf(ConfigurationException.class)
             .hasMessage("Unknown object storage provider: unknown");
     }
+
+    @Test
+    void fromShouldParseNameSpaceWhenSpecified() throws Exception {
+        String bucketNameAsString = "my-bucket";
+        MapConfiguration configuration = new MapConfiguration(
+            ImmutableMap.<String, Object>builder()
+                .putAll(VALID_CONFIGURATION)
+                .put("objectstorage.namespace", bucketNameAsString)
+                .build());
+
+         
assertThat(ObjectStorageBlobConfiguration.from(configuration).getNamespace())
+            .isEqualTo(BucketName.of(bucketNameAsString));
+    }
+
+     @Test
+    void fromShouldUseTheDefaultValueWhenDontSpecifyNameSpace() throws 
Exception {
+        MapConfiguration configuration = new MapConfiguration(
+            ImmutableMap.<String, Object>builder()
+                .putAll(VALID_CONFIGURATION)
+                .build());
+
+         
assertThat(ObjectStorageBlobConfiguration.from(configuration).getNamespace())
+            .isEqualTo(BucketName.DEFAULT);
+    }
+
 }
\ No newline at end of file
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/aws/s3/DockerAwsS3TestRule.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/aws/s3/DockerAwsS3TestRule.java
index b8bf038..68b8a03 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/aws/s3/DockerAwsS3TestRule.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/aws/s3/DockerAwsS3TestRule.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.modules.objectstorage.aws.s3;
 
+import java.util.Optional;
 import java.util.UUID;
 
 import javax.inject.Inject;
@@ -115,10 +116,10 @@ public class DockerAwsS3TestRule implements 
GuiceModuleTestRule {
         ObjectStorageBlobConfiguration configuration = 
ObjectStorageBlobConfiguration.builder()
             .codec(payloadCodecFactory)
             .provider(ObjectStorageProvider.AWSS3)
-            .bucketName(bucketName)
             .authConfiguration(authConfiguration)
             .aesSalt("c603a7327ee3dcbc031d8d34b1096c605feca5e1")
             .aesPassword("dockerAwsS3Encryption".toCharArray())
+            .defaultBucketName(Optional.of(bucketName))
             .build();
 
         return binder -> {
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
index 7f08fe1..9289465 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
@@ -110,13 +110,13 @@ public class DockerSwiftTestRule implements 
GuiceModuleTestRule {
         ObjectStorageBlobConfiguration configuration = 
ObjectStorageBlobConfiguration.builder()
             .codec(payloadCodecFactory)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(bucketName)
             .authConfiguration(new 
SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
                 Optional.empty(),
                 Optional.of(authConfiguration),
                 Optional.empty()))
             .aesSalt("c603a7327ee3dcbc031d8d34b1096c605feca5e1")
             .aesPassword("dockerSwiftEncryption".toCharArray())
+            .defaultBucketName(Optional.of(bucketName))
             .build();
 
         return binder -> {
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
index 6e159b9..5b777c7 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
@@ -97,7 +97,6 @@ class ObjectStorageBlobConfigurationTest {
                 ObjectStorageBlobConfiguration.builder()
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
-                    .bucketName(BucketName.of("foo"))
                     .authConfiguration(new 
SwiftAuthConfiguration(SwiftTempAuthObjectStorage.AUTH_API_NAME,
                         Optional.of(SwiftTempAuthObjectStorage.configBuilder()
                             .endpoint(URI.create("http://swift/endpoint";))
@@ -109,6 +108,7 @@ class ObjectStorageBlobConfigurationTest {
                             .build()),
                         Optional.empty(),
                         Optional.empty()))
+                    .defaultBucketName(Optional.of(BucketName.of("foo")))
                     .build());
     }
 
@@ -130,7 +130,6 @@ class ObjectStorageBlobConfigurationTest {
                 ObjectStorageBlobConfiguration.builder()
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
-                    .bucketName(BucketName.of("foo"))
                     .authConfiguration(new 
SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
                         Optional.empty(),
                         Optional.of(SwiftKeystone2ObjectStorage.configBuilder()
@@ -140,6 +139,7 @@ class ObjectStorageBlobConfigurationTest {
                             .tenantName(TenantName.of("test"))
                             .build()),
                         Optional.empty()))
+                    .defaultBucketName(Optional.of(BucketName.of("foo")))
                     .build());
     }
 
@@ -162,7 +162,6 @@ class ObjectStorageBlobConfigurationTest {
                 ObjectStorageBlobConfiguration.builder()
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
-                    .bucketName(BucketName.of("foo"))
                     .authConfiguration(new 
SwiftAuthConfiguration(SwiftKeystone3ObjectStorage.AUTH_API_NAME,
                         Optional.empty(),
                         Optional.empty(),
@@ -172,6 +171,7 @@ class ObjectStorageBlobConfigurationTest {
                             .project(Project.of(ProjectName.of("test")))
                             .identity(IdentityV3.of(DomainName.of("Default"), 
UserName.of("demo")))
                             .build())))
+                    .defaultBucketName(Optional.of(BucketName.of("foo")))
                     .build());
     }
 
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
index e27f990..22b9f8d 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
@@ -79,7 +79,6 @@ class ObjectStorageBlobStoreModuleTest {
             ObjectStorageBlobConfiguration tmpAuth = 
ObjectStorageBlobConfiguration.builder()
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
-                .bucketName(generateBucketName())
                 .authConfiguration(new 
SwiftAuthConfiguration(SwiftTempAuthObjectStorage.AUTH_API_NAME,
                     Optional.of(SwiftTempAuthObjectStorage.configBuilder()
                         .endpoint(dockerSwift.swiftEndpoint())
@@ -91,11 +90,11 @@ class ObjectStorageBlobStoreModuleTest {
                         .build()),
                     Optional.empty(),
                     Optional.empty()))
+                .defaultBucketName(Optional.of(generateBucketName()))
                 .build();
             ObjectStorageBlobConfiguration keystone2 = 
ObjectStorageBlobConfiguration.builder()
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
-                .bucketName(generateBucketName())
                 .authConfiguration(new 
SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
                     Optional.empty(),
                     Optional.of(SwiftKeystone2ObjectStorage.configBuilder()
@@ -105,11 +104,11 @@ class ObjectStorageBlobStoreModuleTest {
                         .tenantName(TenantName.of("test"))
                         .build()),
                     Optional.empty()))
+                .defaultBucketName(Optional.of(generateBucketName()))
                 .build();
             ObjectStorageBlobConfiguration keystone3 = 
ObjectStorageBlobConfiguration.builder()
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
-                .bucketName(generateBucketName())
                 .authConfiguration(new 
SwiftAuthConfiguration(SwiftKeystone3ObjectStorage.AUTH_API_NAME,
                     Optional.empty(),
                     Optional.empty(),
@@ -119,6 +118,7 @@ class ObjectStorageBlobStoreModuleTest {
                         .project(Project.of(ProjectName.of("test")))
                         .identity(IdentityV3.of(DomainName.of("Default"), 
UserName.of("demo")))
                         .build())))
+                .defaultBucketName(Optional.of(generateBucketName()))
                 .build();
             return Stream.of(tmpAuth, keystone2, keystone3).map(Arguments::of);
         }
diff --git 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
index 12411c3..8e872f9 100644
--- 
a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
+++ 
b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
@@ -37,8 +37,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(new SwiftAuthConfiguration("tmpauth", 
Optional.empty(), Optional.empty(), Optional.empty()))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         assertThatThrownBy(() -> 
SwiftObjectStorage.builder(objectStorageBlobConfiguration))
             .isInstanceOf(IllegalArgumentException.class)
@@ -57,8 +57,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         SwiftObjectStorage.builder(objectStorageBlobConfiguration);
     }
@@ -68,8 +68,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(new SwiftAuthConfiguration("keystone2", 
Optional.empty(), Optional.empty(), Optional.empty()))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         assertThatThrownBy(() -> 
SwiftObjectStorage.builder(objectStorageBlobConfiguration))
             .isInstanceOf(IllegalArgumentException.class)
@@ -88,8 +88,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         SwiftObjectStorage.builder(objectStorageBlobConfiguration);
     }
@@ -99,8 +99,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(new SwiftAuthConfiguration("keystone3", 
Optional.empty(), Optional.empty(), Optional.empty()))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         assertThatThrownBy(() -> 
SwiftObjectStorage.builder(objectStorageBlobConfiguration))
             .isInstanceOf(IllegalArgumentException.class)
@@ -119,8 +119,8 @@ class SwiftObjectStorageTest {
         ObjectStorageBlobConfiguration objectStorageBlobConfiguration = 
ObjectStorageBlobConfiguration.builder()
             .codec(PayloadCodecFactory.DEFAULT)
             .provider(ObjectStorageProvider.SWIFT)
-            .bucketName(BucketName.of("myContainer"))
             .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .defaultBucketName(Optional.of(BucketName.of("myBucket")))
             .build();
         SwiftObjectStorage.builder(objectStorageBlobConfiguration);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to