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 ro...@apache.org on 2018/02/27 13:27:41 UTC

[1/5] james-project git commit: JAMES-2344 introduce QuotaCount and QuotaSize to share parsing and error handling

Repository: james-project
Updated Branches:
  refs/heads/master dbe65ce08 -> fc5c1eaaf


JAMES-2344 introduce QuotaCount and QuotaSize to share parsing and error handling


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/c80590c5
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/c80590c5
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/c80590c5

Branch: refs/heads/master
Commit: c80590c5dd5263c2d742760f817e6e09c34d4511
Parents: 5ebcf3a
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Feb 21 16:05:00 2018 +0100
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Feb 27 09:59:23 2018 +0100

----------------------------------------------------------------------
 .../apache/james/webadmin/dto/QuotaRequest.java | 39 ----------
 .../webadmin/routes/GlobalQuotaRoutes.java      | 24 ++----
 .../james/webadmin/routes/UserQuotaRoutes.java  | 29 ++-----
 .../webadmin/service/GlobalQuotaService.java    | 11 +--
 .../webadmin/service/UserQuotaService.java      | 11 +--
 .../james/webadmin/validation/QuotaValue.java   | 78 +++++++++++++++++++
 .../james/webadmin/dto/QuotaRequestTest.java    | 59 ---------------
 .../webadmin/validation/QuotaValueTest.java     | 79 ++++++++++++++++++++
 8 files changed, 182 insertions(+), 148 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
deleted file mode 100644
index 7ae9e85..0000000
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************
- * 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.webadmin.dto;
-
-import com.google.common.base.Preconditions;
-
-public class QuotaRequest {
-    public static QuotaRequest parse(String serialized) {
-        return new QuotaRequest(Long.valueOf(serialized));
-    }
-
-    private final long value;
-
-    public QuotaRequest(long value) {
-        Preconditions.checkArgument(value >= 0);
-        this.value = value;
-    }
-
-    public long getValue() {
-        return value;
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
index 0121d60..4c59504 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
@@ -28,13 +28,15 @@ import javax.ws.rs.Produces;
 
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.dto.QuotaRequest;
 import org.apache.james.webadmin.service.GlobalQuotaService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
 import org.apache.james.webadmin.utils.JsonExtractException;
 import org.apache.james.webadmin.utils.JsonExtractor;
 import org.apache.james.webadmin.utils.JsonTransformer;
+import org.apache.james.webadmin.validation.QuotaValue;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
 import org.eclipse.jetty.http.HttpStatus;
 
 import io.swagger.annotations.Api;
@@ -43,7 +45,6 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
-import spark.Request;
 import spark.Service;
 
 @Api(tags = "GlobalQuota")
@@ -164,8 +165,8 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaSize() {
         service.put(SIZE_ENDPOINT, (request, response) -> {
-            QuotaRequest quotaRequest = parseQuotaRequest(request);
-            globalQuotaService.defineMaxSizeQuota(quotaRequest);
+            QuotaSize quotaSize = QuotaValue.quotaSize(request.body());
+            globalQuotaService.defineMaxSizeQuota(quotaSize);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
         });
@@ -210,7 +211,7 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaCount() {
         service.put(COUNT_ENDPOINT, (request, response) -> {
-            QuotaRequest quotaRequest = parseQuotaRequest(request);
+            QuotaCount quotaRequest = QuotaValue.quotaCount(request.body());
             globalQuotaService.defineMaxCountQuota(quotaRequest);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
@@ -228,17 +229,4 @@ public class GlobalQuotaRoutes implements Routes {
         service.get(COUNT_ENDPOINT, (request, response) -> globalQuotaService.getMaxCountQuota(), jsonTransformer);
     }
 
-    private QuotaRequest parseQuotaRequest(Request request) {
-        try {
-            return QuotaRequest.parse(request.body());
-        } catch (IllegalArgumentException e) {
-            throw ErrorResponder.builder()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .type(ErrorType.INVALID_ARGUMENT)
-                .message("Invalid quota. Need to be an integer value greater than 0")
-                .cause(e)
-                .haltError();
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
index b72d65f..1a4deaf 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
@@ -30,16 +30,16 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.dto.QuotaRequest;
 import org.apache.james.webadmin.service.UserQuotaService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
 import org.apache.james.webadmin.utils.JsonExtractException;
 import org.apache.james.webadmin.utils.JsonExtractor;
 import org.apache.james.webadmin.utils.JsonTransformer;
+import org.apache.james.webadmin.validation.QuotaValue;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
 import org.eclipse.jetty.http.HttpStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -55,8 +55,6 @@ import spark.Service;
 @Produces("application/json")
 public class UserQuotaRoutes implements Routes {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(Routes.class);
-
     private static final String USER = "user";
     static final String QUOTA_ENDPOINT = "/quota/users/:" + USER;
     private static final String COUNT_ENDPOINT = QUOTA_ENDPOINT + "/count";
@@ -160,8 +158,8 @@ public class UserQuotaRoutes implements Routes {
     public void defineUpdateQuotaSize() {
         service.put(SIZE_ENDPOINT, (request, response) -> {
             String user = checkUserExist(request);
-            QuotaRequest quotaRequest = parseQuotaRequest(request);
-            userQuotaService.defineMaxSizeQuota(user, quotaRequest);
+            QuotaSize quotaSize = QuotaValue.quotaSize(request.body());
+            userQuotaService.defineMaxSizeQuota(user, quotaSize);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
         });
@@ -212,8 +210,8 @@ public class UserQuotaRoutes implements Routes {
     public void defineUpdateQuotaCount() {
         service.put(COUNT_ENDPOINT, (request, response) -> {
             String user = checkUserExist(request);
-            QuotaRequest quotaRequest = parseQuotaRequest(request);
-            userQuotaService.defineMaxCountQuota(user, quotaRequest);
+            QuotaCount quotaCount = QuotaValue.quotaCount(request.body());
+            userQuotaService.defineMaxCountQuota(user, quotaCount);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
         });
@@ -265,17 +263,4 @@ public class UserQuotaRoutes implements Routes {
         }
     }
 
-    private QuotaRequest parseQuotaRequest(Request request) {
-        try {
-            return QuotaRequest.parse(request.body());
-        } catch (IllegalArgumentException e) {
-            LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
-            throw ErrorResponder.builder()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .type(ErrorType.INVALID_ARGUMENT)
-                .message("Invalid quota. Need to be an integer value greater than 0")
-                .cause(e)
-                .haltError();
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
index 33d76de..a5902ce 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
@@ -24,7 +24,8 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.dto.QuotaRequest;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
 
 public class GlobalQuotaService {
 
@@ -52,8 +53,8 @@ public class GlobalQuotaService {
         return maxQuotaManager.getDefaultMaxStorage();
     }
 
-    public void defineMaxSizeQuota(QuotaRequest quotaRequest) throws MailboxException {
-        maxQuotaManager.setDefaultMaxStorage(quotaRequest.getValue());
+    public void defineMaxSizeQuota(QuotaSize quotaRequest) throws MailboxException {
+        maxQuotaManager.setDefaultMaxStorage(quotaRequest.asLong());
     }
 
     public void deleteMaxSizeQuota() throws MailboxException {
@@ -64,8 +65,8 @@ public class GlobalQuotaService {
         return maxQuotaManager.getDefaultMaxMessage();
     }
 
-    public void defineMaxCountQuota(QuotaRequest quotaRequest) throws MailboxException {
-        maxQuotaManager.setDefaultMaxMessage(quotaRequest.getValue());
+    public void defineMaxCountQuota(QuotaCount value) throws MailboxException {
+        maxQuotaManager.setDefaultMaxMessage(value.asLong());
     }
 
     public void deleteMaxCountQuota() throws MailboxException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
index ddaf630..31440b3 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
@@ -25,7 +25,8 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.dto.QuotaRequest;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
+import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
 
 public class UserQuotaService {
 
@@ -55,8 +56,8 @@ public class UserQuotaService {
         return maxQuotaManager.getMaxStorage(QuotaRoot.forUser(user));
     }
 
-    public void defineMaxSizeQuota(String user, QuotaRequest quotaRequest) throws MailboxException {
-        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), quotaRequest.getValue());
+    public void defineMaxSizeQuota(String user, QuotaSize quotaSize) throws MailboxException {
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), quotaSize.asLong());
     }
 
     public void deleteMaxSizeQuota(String user) throws MailboxException {
@@ -67,8 +68,8 @@ public class UserQuotaService {
         return maxQuotaManager.getMaxMessage(QuotaRoot.forUser(user));
     }
 
-    public void defineMaxCountQuota(String user, QuotaRequest quotaRequest) throws MailboxException {
-        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), quotaRequest.getValue());
+    public void defineMaxCountQuota(String user, QuotaCount quotaCount) throws MailboxException {
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), quotaCount.asLong());
     }
 
     public void deleteMaxCountQuota(String user) throws MailboxException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/QuotaValue.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/QuotaValue.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/QuotaValue.java
new file mode 100644
index 0000000..a0ea65f
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/QuotaValue.java
@@ -0,0 +1,78 @@
+/****************************************************************
+ * 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.webadmin.validation;
+
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.eclipse.jetty.http.HttpStatus;
+
+public abstract class QuotaValue {
+
+    public static class QuotaSize extends QuotaValue {
+        QuotaSize(long value) {
+            super(value);
+        }
+    }
+
+    public static class QuotaCount extends QuotaValue {
+        QuotaCount(long value) {
+            super(value);
+        }
+    }
+
+    public static QuotaCount quotaCount(String serialized) {
+        return new QuotaCount(parse(serialized));
+    }
+
+    public static QuotaSize quotaSize(String serialized) {
+        return new QuotaSize(parse(serialized));
+    }
+
+    private static long parse(String serialized) {
+        try {
+            return Long.valueOf(serialized);
+        } catch (IllegalArgumentException e) {
+            throw generateInvalidInputError()
+                .cause(e)
+                .haltError();
+        }
+    }
+
+    private static ErrorResponder generateInvalidInputError() {
+        return ErrorResponder.builder()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+            .message("Invalid quota. Need to be an integer value greater than 0");
+    }
+
+    private final long value;
+
+    private QuotaValue(long value) {
+        if (value < 0) {
+            throw generateInvalidInputError()
+                .haltError();
+        }
+        this.value = value;
+    }
+
+    public long asLong() {
+        return value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java
deleted file mode 100644
index 34df209..0000000
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/QuotaRequestTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************
- * 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.webadmin.dto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class QuotaRequestTest {
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @Test
-    public void parseShouldThrowWhenNotANumber() {
-        expectedException.expect(NumberFormatException.class);
-
-        QuotaRequest.parse("invalid");
-    }
-
-    @Test
-    public void parseShouldThrowOnNegativeNumber() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        QuotaRequest.parse("-1");
-    }
-
-    @Test
-    public void parseShouldParseZero() {
-        assertThat(QuotaRequest.parse("0").getValue())
-            .isEqualTo(0);
-    }
-
-    @Test
-    public void parseShouldParsePositiveValue() {
-        assertThat(QuotaRequest.parse("42").getValue())
-            .isEqualTo(42);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/c80590c5/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/validation/QuotaValueTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/validation/QuotaValueTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/validation/QuotaValueTest.java
new file mode 100644
index 0000000..1cc2330
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/validation/QuotaValueTest.java
@@ -0,0 +1,79 @@
+/****************************************************************
+ * 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.webadmin.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+import spark.HaltException;
+
+public class QuotaValueTest {
+
+    @Test
+    public void quotaCountShouldThrowWhenNotANumber() {
+        assertThatThrownBy(() -> QuotaValue.quotaCount("invalid"))
+            .isInstanceOf(HaltException.class);
+    }
+
+    @Test
+    public void quotaCountShouldParseZero() {
+        assertThat(QuotaValue.quotaCount("0").asLong())
+            .isEqualTo(0);
+    }
+
+    @Test
+    public void quotaCountShouldParsePositiveValue() {
+        assertThat(QuotaValue.quotaCount("42").asLong())
+            .isEqualTo(42);
+    }
+
+    @Test
+    public void quotaCountShouldThrowOnNegativeNumber() {
+        assertThatThrownBy(() -> QuotaValue.quotaCount("-1"))
+            .isInstanceOf(HaltException.class);
+    }
+
+    @Test
+    public void quotaSizeShouldThrowWhenNotANumber() {
+        assertThatThrownBy(() -> QuotaValue.quotaSize("invalid"))
+            .isInstanceOf(HaltException.class);
+    }
+
+    @Test
+    public void quotaSizeShouldParseZero() {
+        assertThat(QuotaValue.quotaSize("0").asLong())
+            .isEqualTo(0);
+    }
+
+    @Test
+    public void quotaSizeShouldParsePositiveValue() {
+        assertThat(QuotaValue.quotaSize("42").asLong())
+            .isEqualTo(42);
+    }
+
+    @Test
+    public void quotaSizeShouldThrowOnNegativeNumber() {
+        assertThatThrownBy(() -> QuotaValue.quotaSize("-1"))
+            .isInstanceOf(HaltException.class);
+    }
+
+}


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


[2/5] james-project git commit: JAMES-2344 extract GlobalQuota logic into a service class

Posted by ro...@apache.org.
JAMES-2344 extract GlobalQuota logic into a service class


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/5ebcf3ab
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/5ebcf3ab
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/5ebcf3ab

Branch: refs/heads/master
Commit: 5ebcf3ab8486900ec6c92b6b6625ff044b731f6b
Parents: e87c055
Author: Matthieu Baechler <ma...@apache.org>
Authored: Wed Feb 21 15:34:19 2018 +0100
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Feb 27 09:59:23 2018 +0100

----------------------------------------------------------------------
 .../webadmin/routes/GlobalQuotaRoutes.java      | 99 +++++++-------------
 .../webadmin/service/GlobalQuotaService.java    | 74 +++++++++++++++
 .../webadmin/routes/GlobalQuotaRoutesTest.java  |  3 +-
 3 files changed, 112 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/5ebcf3ab/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
index 397381a..0121d60 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
@@ -26,20 +26,16 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
-import org.apache.james.mailbox.model.Quota;
-import org.apache.james.mailbox.quota.MaxQuotaManager;
-import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.QuotaDTO;
 import org.apache.james.webadmin.dto.QuotaRequest;
+import org.apache.james.webadmin.service.GlobalQuotaService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
 import org.apache.james.webadmin.utils.JsonExtractException;
 import org.apache.james.webadmin.utils.JsonExtractor;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -47,6 +43,7 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
+import spark.Request;
 import spark.Service;
 
 @Api(tags = "GlobalQuota")
@@ -57,16 +54,15 @@ public class GlobalQuotaRoutes implements Routes {
     public static final String QUOTA_ENDPOINT = "/quota";
     public static final String COUNT_ENDPOINT = QUOTA_ENDPOINT + "/count";
     public static final String SIZE_ENDPOINT = QUOTA_ENDPOINT + "/size";
-    private static final Logger LOGGER = LoggerFactory.getLogger(Routes.class);
 
-    private final MaxQuotaManager maxQuotaManager;
     private final JsonTransformer jsonTransformer;
     private final JsonExtractor<QuotaDTO> jsonExtractor;
+    private final GlobalQuotaService globalQuotaService;
     private Service service;
 
     @Inject
-    public GlobalQuotaRoutes(MaxQuotaManager maxQuotaManager, JsonTransformer jsonTransformer) {
-        this.maxQuotaManager = maxQuotaManager;
+    public GlobalQuotaRoutes(GlobalQuotaService globalQuotaService, JsonTransformer jsonTransformer) {
+        this.globalQuotaService = globalQuotaService;
         this.jsonTransformer = jsonTransformer;
         this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class);
     }
@@ -106,11 +102,10 @@ public class GlobalQuotaRoutes implements Routes {
         service.put(QUOTA_ENDPOINT, ((request, response) -> {
             try {
                 QuotaDTO quotaDTO = jsonExtractor.parse(request.body());
-                maxQuotaManager.setDefaultMaxMessage(quotaDTO.getCount());
-                maxQuotaManager.setDefaultMaxStorage(quotaDTO.getSize());
+                globalQuotaService.defineQuota(quotaDTO);
                 response.status(HttpStatus.NO_CONTENT_204);
+                return response;
             } catch (JsonExtractException e) {
-                LOGGER.info("Malformed JSON", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.BAD_REQUEST_400)
                     .type(ErrorType.INVALID_ARGUMENT)
@@ -118,7 +113,6 @@ public class GlobalQuotaRoutes implements Routes {
                     .cause(e)
                     .haltError();
             } catch (IllegalArgumentException e) {
-                LOGGER.info("Quota should be positive or unlimited (-1)", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.BAD_REQUEST_400)
                     .type(ErrorType.INVALID_ARGUMENT)
@@ -126,7 +120,6 @@ public class GlobalQuotaRoutes implements Routes {
                     .cause(e)
                     .haltError();
             }
-            return Constants.EMPTY_BODY;
         }));
     }
 
@@ -140,13 +133,7 @@ public class GlobalQuotaRoutes implements Routes {
             @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
     })
     public void defineGetQuota() {
-        service.get(QUOTA_ENDPOINT, (request, response) -> {
-            QuotaDTO quotaDTO = QuotaDTO.builder()
-                .count(maxQuotaManager.getDefaultMaxMessage())
-                .size(maxQuotaManager.getDefaultMaxStorage()).build();
-            response.status(HttpStatus.OK_200);
-            return quotaDTO;
-        }, jsonTransformer);
+        service.get(QUOTA_ENDPOINT, (request, response) -> globalQuotaService.getQuota(), jsonTransformer);
     }
 
     @DELETE
@@ -158,9 +145,9 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineDeleteQuotaSize() {
         service.delete(SIZE_ENDPOINT, (request, response) -> {
-            maxQuotaManager.setDefaultMaxStorage(Quota.UNLIMITED);
+            globalQuotaService.deleteMaxSizeQuota();
             response.status(HttpStatus.NO_CONTENT_204);
-            return Constants.EMPTY_BODY;
+            return response;
         });
     }
 
@@ -177,20 +164,10 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaSize() {
         service.put(SIZE_ENDPOINT, (request, response) -> {
-            try {
-                QuotaRequest quotaRequest = QuotaRequest.parse(request.body());
-                maxQuotaManager.setDefaultMaxStorage(quotaRequest.getValue());
-                response.status(HttpStatus.NO_CONTENT_204);
-            } catch (IllegalArgumentException e) {
-                LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
-                throw ErrorResponder.builder()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .type(ErrorType.INVALID_ARGUMENT)
-                    .message("Invalid quota. Need to be an integer value greater than 0")
-                    .cause(e)
-                    .haltError();
-            }
-            return Constants.EMPTY_BODY;
+            QuotaRequest quotaRequest = parseQuotaRequest(request);
+            globalQuotaService.defineMaxSizeQuota(quotaRequest);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
         });
     }
 
@@ -202,11 +179,7 @@ public class GlobalQuotaRoutes implements Routes {
             @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
     })
     public void defineGetQuotaSize() {
-        service.get(SIZE_ENDPOINT, (request, response) -> {
-            long value = maxQuotaManager.getDefaultMaxStorage();
-            response.status(HttpStatus.OK_200);
-            return value;
-        }, jsonTransformer);
+        service.get(SIZE_ENDPOINT, (request, response) -> globalQuotaService.getMaxSizeQuota(), jsonTransformer);
     }
 
     @DELETE
@@ -218,9 +191,9 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineDeleteQuotaCount() {
         service.delete(COUNT_ENDPOINT, (request, response) -> {
-            maxQuotaManager.setDefaultMaxMessage(Quota.UNLIMITED);
+            globalQuotaService.deleteMaxCountQuota();
             response.status(HttpStatus.NO_CONTENT_204);
-            return Constants.EMPTY_BODY;
+            return response;
         });
     }
 
@@ -237,20 +210,10 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaCount() {
         service.put(COUNT_ENDPOINT, (request, response) -> {
-            try {
-                QuotaRequest quotaRequest = QuotaRequest.parse(request.body());
-                maxQuotaManager.setDefaultMaxMessage(quotaRequest.getValue());
-                response.status(HttpStatus.NO_CONTENT_204);
-            } catch (IllegalArgumentException e) {
-                LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
-                throw ErrorResponder.builder()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
-                    .type(ErrorType.INVALID_ARGUMENT)
-                    .message("Invalid quota. Need to be an integer value greater than 0")
-                    .cause(e)
-                    .haltError();
-            }
-            return Constants.EMPTY_BODY;
+            QuotaRequest quotaRequest = parseQuotaRequest(request);
+            globalQuotaService.defineMaxCountQuota(quotaRequest);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
         });
     }
 
@@ -262,10 +225,20 @@ public class GlobalQuotaRoutes implements Routes {
             @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
     })
     public void defineGetQuotaCount() {
-        service.get(COUNT_ENDPOINT, (request, response) -> {
-            long value = maxQuotaManager.getDefaultMaxMessage();
-            response.status(HttpStatus.OK_200);
-            return value;
-        }, jsonTransformer);
+        service.get(COUNT_ENDPOINT, (request, response) -> globalQuotaService.getMaxCountQuota(), jsonTransformer);
     }
+
+    private QuotaRequest parseQuotaRequest(Request request) {
+        try {
+            return QuotaRequest.parse(request.body());
+        } catch (IllegalArgumentException e) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorType.INVALID_ARGUMENT)
+                .message("Invalid quota. Need to be an integer value greater than 0")
+                .cause(e)
+                .haltError();
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/5ebcf3ab/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
new file mode 100644
index 0000000..33d76de
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/GlobalQuotaService.java
@@ -0,0 +1,74 @@
+/****************************************************************
+ * 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.webadmin.service;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.webadmin.dto.QuotaDTO;
+import org.apache.james.webadmin.dto.QuotaRequest;
+
+public class GlobalQuotaService {
+
+    private final MaxQuotaManager maxQuotaManager;
+
+    @Inject
+    public GlobalQuotaService(MaxQuotaManager maxQuotaManager) {
+        this.maxQuotaManager = maxQuotaManager;
+    }
+
+    public void defineQuota(QuotaDTO quota) throws MailboxException {
+        maxQuotaManager.setDefaultMaxMessage(quota.getCount());
+        maxQuotaManager.setDefaultMaxStorage(quota.getSize());
+    }
+
+    public QuotaDTO getQuota() throws MailboxException {
+        return QuotaDTO
+            .builder()
+            .count(maxQuotaManager.getDefaultMaxMessage())
+            .size(maxQuotaManager.getDefaultMaxStorage())
+            .build();
+    }
+
+    public Long getMaxSizeQuota() throws MailboxException {
+        return maxQuotaManager.getDefaultMaxStorage();
+    }
+
+    public void defineMaxSizeQuota(QuotaRequest quotaRequest) throws MailboxException {
+        maxQuotaManager.setDefaultMaxStorage(quotaRequest.getValue());
+    }
+
+    public void deleteMaxSizeQuota() throws MailboxException {
+        maxQuotaManager.setDefaultMaxStorage(Quota.UNLIMITED);
+    }
+
+    public Long getMaxCountQuota() throws MailboxException {
+        return maxQuotaManager.getDefaultMaxMessage();
+    }
+
+    public void defineMaxCountQuota(QuotaRequest quotaRequest) throws MailboxException {
+        maxQuotaManager.setDefaultMaxMessage(quotaRequest.getValue());
+    }
+
+    public void deleteMaxCountQuota() throws MailboxException {
+        maxQuotaManager.setDefaultMaxMessage(Quota.UNLIMITED);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/5ebcf3ab/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java
index 60029c1..e626fd6 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/GlobalQuotaRoutesTest.java
@@ -30,6 +30,7 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.service.GlobalQuotaService;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.After;
@@ -50,7 +51,7 @@ public class GlobalQuotaRoutesTest {
         maxQuotaManager = new InMemoryPerUserMaxQuotaManager();
         webAdminServer = WebAdminUtils.createWebAdminServer(
             new DefaultMetricFactory(),
-            new GlobalQuotaRoutes(maxQuotaManager, new JsonTransformer()));
+            new GlobalQuotaRoutes(new GlobalQuotaService(maxQuotaManager), new JsonTransformer()));
         webAdminServer.configure(NO_CONFIGURATION);
         webAdminServer.await();
 


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


[5/5] james-project git commit: JAMES-2344 merge QuotaImpl and Quota, it's part of the API

Posted by ro...@apache.org.
JAMES-2344 merge QuotaImpl and Quota, it's part of the API


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/fc5c1eaa
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/fc5c1eaa
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/fc5c1eaa

Branch: refs/heads/master
Commit: fc5c1eaaf365ae0aaea560224dbdeb3d6b4e0f7c
Parents: c80590c
Author: Matthieu Baechler <ma...@apache.org>
Authored: Mon Feb 26 17:44:29 2018 +0100
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Feb 27 09:59:59 2018 +0100

----------------------------------------------------------------------
 .../org/apache/james/mailbox/model/Quota.java   | 91 ++++++++++++-------
 .../apache/james/mailbox/model/QuotaTest.java   | 81 +++++++++++++++++
 .../mailbox/store/quota/NoQuotaManager.java     |  4 +-
 .../james/mailbox/store/quota/QuotaImpl.java    | 92 --------------------
 .../mailbox/store/quota/StoreQuotaManager.java  |  8 +-
 .../AbstractMessageIdManagerSideEffectTest.java | 11 ++-
 .../mailbox/store/quota/QuotaCheckerTest.java   | 21 ++---
 .../mailbox/store/quota/QuotaImplTest.java      | 81 -----------------
 .../store/quota/StoreQuotaManagerTest.java      | 12 +--
 .../imap/encode/QuotaResponseEncoderTest.java   |  6 +-
 .../imap/processor/GetQuotaProcessorTest.java   |  5 +-
 .../processor/GetQuotaRootProcessorTest.java    |  5 +-
 12 files changed, 177 insertions(+), 240 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/api/src/main/java/org/apache/james/mailbox/model/Quota.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Quota.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Quota.java
index 5e303a3..da0ec14 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Quota.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Quota.java
@@ -18,47 +18,78 @@
  ****************************************************************/
 package org.apache.james.mailbox.model;
 
-/**
- * A {@link Quota} restriction
- */
-public interface Quota {
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 
-    /**
-     * Unlimited value
-     */
-    long UNLIMITED = -1;
+public class Quota {
 
-    /**
-     * Value not known
-     */
-    long UNKNOWN = Long.MIN_VALUE;
+    public static final long UNLIMITED = -1;
 
-    /**
-     * Return the maximum value for the {@link Quota}
-     *
-     * @return max
-     */
-    long getMax();
+    public static final long UNKNOWN = Long.MIN_VALUE;
 
-    /**
-     * Return the currently used for the {@link Quota}
-     *
-     * @return used
-     */
-    long getUsed();
+    private static final Quota UNLIMITED_QUOTA = new Quota(UNKNOWN, UNLIMITED);
 
-    /**
-     *  Adds the value to the quota.
-     */
-    void addValueToQuota(long value);
+    public static Quota unlimited() {
+        return UNLIMITED_QUOTA;
+    }
+
+    public static Quota quota(long used, long max) {
+        return new Quota(used, max);
+    }
+
+    private final long max;
+    private long used;
+
+    private Quota(long used, long max) {
+        this.used = used;
+        this.max = max;
+    }
+
+    public long getMax() {
+        return max;
+    }
+
+    public long getUsed() {
+        return used;
+    }
+
+    public void addValueToQuota(long value) {
+        used += value;
+    }
 
     /**
      * Tells us if the quota is reached
      *
      * @return True if the user over uses the resource of this quota
      */
-    boolean isOverQuota();
+    public boolean isOverQuota() {
+        return isOverQuotaWithAdditionalValue(0);
+    }
+
+    public boolean isOverQuotaWithAdditionalValue(long additionalValue) {
+        Preconditions.checkArgument(additionalValue >= 0);
+        return max != UNLIMITED
+            && used + additionalValue > max;
+    }
+
+    @Override
+    public String toString() {
+        return used + "/" + max;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || ! (o instanceof  Quota)) {
+            return false;
+        }
+        Quota other = (Quota) o;
+        return used == other.getUsed()
+            && max == other.getMax();
+    }
 
-    boolean isOverQuotaWithAdditionalValue(long additionalValue);
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(used, max);
+    }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/api/src/test/java/org/apache/james/mailbox/model/QuotaTest.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/model/QuotaTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/model/QuotaTest.java
new file mode 100644
index 0000000..143886d
--- /dev/null
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/model/QuotaTest.java
@@ -0,0 +1,81 @@
+/****************************************************************
+ * 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.mailbox.model;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.mailbox.model.Quota;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class QuotaTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void unlimitedQuotaShouldNotBeOverQuota() {
+        assertThat(Quota.unlimited().isOverQuota()).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaShouldReturnFalseWhenQuotaIsNotExceeded() {
+        assertThat(Quota.quota(36, 360).isOverQuota()).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaShouldReturnFalseWhenMaxValueIsUnlimited() {
+        assertThat(Quota.quota(36, Quota.UNLIMITED).isOverQuota()).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaShouldReturnFalseWhenUsedValueIsUnknown() {
+        assertThat(Quota.quota(Quota.UNKNOWN, 36).isOverQuota()).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaShouldReturnTrueWhenQuotaIsExceeded() {
+        assertThat(Quota.quota(360, 36).isOverQuota()).isTrue();
+    }
+
+    @Test
+    public void isOverQuotaWithAdditionalValueShouldReturnTrueWhenOverLimit() {
+        assertThat(Quota.quota(36, 36).isOverQuotaWithAdditionalValue(1)).isTrue();
+    }
+
+    @Test
+    public void isOverQuotaWithAdditionalValueShouldReturnTrueWhenUnderLimit() {
+        assertThat(Quota.quota(34, 36).isOverQuotaWithAdditionalValue(1)).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaWithAdditionalValueShouldReturnFalseWhenAtLimit() {
+        assertThat(Quota.quota(36, 36).isOverQuotaWithAdditionalValue(0)).isFalse();
+    }
+
+    @Test
+    public void isOverQuotaWithAdditionalValueShouldThrowOnNegativeValue() {
+        expectedException.expect(IllegalArgumentException.class);
+
+        Quota.quota(25, 36).isOverQuotaWithAdditionalValue(-1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/NoQuotaManager.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/NoQuotaManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/NoQuotaManager.java
index 64b58b2..bebc32c 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/NoQuotaManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/NoQuotaManager.java
@@ -31,11 +31,11 @@ public class NoQuotaManager implements QuotaManager {
 
     @Override
     public Quota getMessageQuota(QuotaRoot quotaRoot) throws MailboxException {
-        return QuotaImpl.unlimited();
+        return Quota.unlimited();
     }
 
     @Override
     public Quota getStorageQuota(QuotaRoot quotaRoot) throws MailboxException {
-        return QuotaImpl.unlimited();
+        return Quota.unlimited();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaImpl.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaImpl.java
deleted file mode 100644
index 294de6e..0000000
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaImpl.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/****************************************************************
- * 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.mailbox.store.quota;
-
-import org.apache.james.mailbox.model.Quota;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public final class QuotaImpl implements Quota {
-
-    private static final Quota UNLIMITED_QUOTA = new QuotaImpl(UNKNOWN, UNLIMITED);
-
-    public static Quota unlimited() {
-        return UNLIMITED_QUOTA;
-    }
-
-    public static Quota quota(long used, long max) {
-        return new QuotaImpl(used, max);
-    }
-
-    private final long max;
-    private long used;
-
-    private QuotaImpl(long used, long max) {
-        this.used = used;
-        this.max = max;
-    }
-
-    @Override
-    public long getMax() {
-        return max;
-    }
-
-    @Override
-    public long getUsed() {
-        return used;
-    }
-
-    @Override
-    public void addValueToQuota(long value) {
-        used += value;
-    }
-
-    @Override
-    public boolean isOverQuota() {
-        return isOverQuotaWithAdditionalValue(0);
-    }
-
-    @Override
-    public String toString() {
-        return used + "/" + max;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == null || ! (o instanceof  Quota)) {
-            return false;
-        }
-        Quota other = (Quota) o;
-        return used == other.getUsed()
-            && max == other.getMax();
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(used, max);
-    }
-
-    @Override
-    public boolean isOverQuotaWithAdditionalValue(long additionalValue) {
-        Preconditions.checkArgument(additionalValue >= 0);
-        return max != UNLIMITED
-            && used + additionalValue > max;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/StoreQuotaManager.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/StoreQuotaManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/StoreQuotaManager.java
index 5c5cef4..59dc23e 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/StoreQuotaManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/StoreQuotaManager.java
@@ -51,18 +51,18 @@ public class StoreQuotaManager implements QuotaManager {
     public Quota getMessageQuota(QuotaRoot quotaRoot) throws MailboxException {
         long maxValue = maxQuotaManager.getMaxMessage(quotaRoot);
         if (maxValue == Quota.UNLIMITED && !calculateWhenUnlimited) {
-            return QuotaImpl.quota(Quota.UNKNOWN, Quota.UNLIMITED);
+            return Quota.quota(Quota.UNKNOWN, Quota.UNLIMITED);
         }
-        return QuotaImpl.quota(currentQuotaManager.getCurrentMessageCount(quotaRoot), maxValue);
+        return Quota.quota(currentQuotaManager.getCurrentMessageCount(quotaRoot), maxValue);
     }
 
 
     public Quota getStorageQuota(QuotaRoot quotaRoot) throws MailboxException {
         long maxValue = maxQuotaManager.getMaxStorage(quotaRoot);
         if (maxValue == Quota.UNLIMITED && !calculateWhenUnlimited) {
-            return QuotaImpl.quota(Quota.UNKNOWN, Quota.UNLIMITED);
+            return Quota.quota(Quota.UNKNOWN, Quota.UNLIMITED);
         }
-        return QuotaImpl.quota(currentQuotaManager.getCurrentStorage(quotaRoot), maxValue);
+        return Quota.quota(currentQuotaManager.getCurrentStorage(quotaRoot), maxValue);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
index c414601..629256f 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
@@ -54,7 +54,6 @@ import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.store.event.MailboxEventDispatcher;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
-import org.apache.james.mailbox.store.quota.QuotaImpl;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -62,7 +61,7 @@ import org.junit.rules.ExpectedException;
 import com.google.common.collect.ImmutableList;
 
 public abstract class AbstractMessageIdManagerSideEffectTest {
-    private static final Quota OVER_QUOTA = QuotaImpl.quota(102, 100);
+    private static final Quota OVER_QUOTA = Quota.quota(102, 100);
     private static final MessageUid messageUid1 = MessageUid.of(111);
 
     public static final Flags FLAGS = new Flags();
@@ -163,9 +162,9 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
     public void setInMailboxesShouldThrowExceptionWhenOverQuota() throws Exception {
         MessageId messageId = testingData.persist(mailbox1.getMailboxId(), messageUid1, FLAGS, session);
         reset(dispatcher);
-        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(QuotaImpl.unlimited());
+        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(Quota.unlimited());
         when(quotaManager.getMessageQuota(any(QuotaRoot.class))).thenReturn(OVER_QUOTA);
-        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(QuotaImpl.unlimited());
+        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(Quota.unlimited());
 
         expectedException.expect(OverQuotaException.class);
 
@@ -307,8 +306,8 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
     }
 
     private void givenUnlimitedQuota() throws MailboxException {
-        when(quotaManager.getMessageQuota(any(QuotaRoot.class))).thenReturn(QuotaImpl.unlimited());
-        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(QuotaImpl.unlimited());
+        when(quotaManager.getMessageQuota(any(QuotaRoot.class))).thenReturn(Quota.unlimited());
+        when(quotaManager.getStorageQuota(any(QuotaRoot.class))).thenReturn(Quota.unlimited());
     }
 
     private SimpleMessageMetaData fromMessageResult(MessageId messageId, MessageResult messageResult) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
index 7566e88..f7ff670 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.OverQuotaException;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
@@ -52,8 +53,8 @@ public class QuotaCheckerTest {
     @Test
     public void quotaCheckerShouldNotThrowOnRegularQuotas() throws MailboxException {
         when(mockedQuotaRootResolver.getQuotaRoot(MAILBOX_PATH)).thenReturn(QUOTA_ROOT);
-        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(10, 100));
-        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(100, 1000));
+        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(10, 100));
+        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(100, 1000));
         QuotaChecker quotaChecker = new QuotaChecker(mockedQuotaManager, mockedQuotaRootResolver, MAILBOX);
         assertThat(quotaChecker.tryAddition(0, 0)).isTrue();
     }
@@ -61,8 +62,8 @@ public class QuotaCheckerTest {
     @Test
     public void quotaCheckerShouldNotThrowOnRegularModifiedQuotas() throws MailboxException {
         when(mockedQuotaRootResolver.getQuotaRoot(MAILBOX_PATH)).thenReturn(QUOTA_ROOT);
-        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(10, 100));
-        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(100, 1000));
+        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(10, 100));
+        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(100, 1000));
         QuotaChecker quotaChecker = new QuotaChecker(mockedQuotaManager, mockedQuotaRootResolver, MAILBOX);
         assertThat(quotaChecker.tryAddition(89, 899)).isTrue();
     }
@@ -70,8 +71,8 @@ public class QuotaCheckerTest {
     @Test
     public void quotaCheckerShouldNotThrowOnReachedMaximumQuotas() throws MailboxException {
         when(mockedQuotaRootResolver.getQuotaRoot(MAILBOX_PATH)).thenReturn(QUOTA_ROOT);
-        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(10, 100));
-        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(100, 1000));
+        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(10, 100));
+        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(100, 1000));
         QuotaChecker quotaChecker = new QuotaChecker(mockedQuotaManager, mockedQuotaRootResolver, MAILBOX);
         assertThat(quotaChecker.tryAddition(90, 900)).isTrue();
     }
@@ -79,8 +80,8 @@ public class QuotaCheckerTest {
     @Test
     public void quotaCheckerShouldThrowOnExceededMessages() throws MailboxException {
         when(mockedQuotaRootResolver.getQuotaRoot(MAILBOX_PATH)).thenReturn(QUOTA_ROOT);
-        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(10, 100));
-        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(100, 1000));
+        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(10, 100));
+        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(100, 1000));
         QuotaChecker quotaChecker = new QuotaChecker(mockedQuotaManager, mockedQuotaRootResolver, MAILBOX);
 
         assertThatThrownBy(() -> quotaChecker.tryAddition(91, 899))
@@ -90,8 +91,8 @@ public class QuotaCheckerTest {
     @Test
     public void quotaCheckerShouldThrowOnExceededStorage() throws MailboxException {
         when(mockedQuotaRootResolver.getQuotaRoot(MAILBOX_PATH)).thenReturn(QUOTA_ROOT);
-        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(10, 100));
-        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(QuotaImpl.quota(100, 1000));
+        when(mockedQuotaManager.getMessageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(10, 100));
+        when(mockedQuotaManager.getStorageQuota(QUOTA_ROOT)).thenReturn(Quota.quota(100, 1000));
         QuotaChecker quotaChecker = new QuotaChecker(mockedQuotaManager, mockedQuotaRootResolver, MAILBOX);
 
         assertThatThrownBy(() -> quotaChecker.tryAddition(89, 901))

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaImplTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaImplTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaImplTest.java
deleted file mode 100644
index 3faca34..0000000
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaImplTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************
- * 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.mailbox.store.quota;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.apache.james.mailbox.model.Quota;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class QuotaImplTest {
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @Test
-    public void unlimitedQuotaShouldNotBeOverQuota() {
-        assertThat(QuotaImpl.unlimited().isOverQuota()).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaShouldReturnFalseWhenQuotaIsNotExceeded() {
-        assertThat(QuotaImpl.quota(36, 360).isOverQuota()).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaShouldReturnFalseWhenMaxValueIsUnlimited() {
-        assertThat(QuotaImpl.quota(36, Quota.UNLIMITED).isOverQuota()).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaShouldReturnFalseWhenUsedValueIsUnknown() {
-        assertThat(QuotaImpl.quota(Quota.UNKNOWN, 36).isOverQuota()).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaShouldReturnTrueWhenQuotaIsExceeded() {
-        assertThat(QuotaImpl.quota(360, 36).isOverQuota()).isTrue();
-    }
-
-    @Test
-    public void isOverQuotaWithAdditionalValueShouldReturnTrueWhenOverLimit() {
-        assertThat(QuotaImpl.quota(36, 36).isOverQuotaWithAdditionalValue(1)).isTrue();
-    }
-
-    @Test
-    public void isOverQuotaWithAdditionalValueShouldReturnTrueWhenUnderLimit() {
-        assertThat(QuotaImpl.quota(34, 36).isOverQuotaWithAdditionalValue(1)).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaWithAdditionalValueShouldReturnFalseWhenAtLimit() {
-        assertThat(QuotaImpl.quota(36, 36).isOverQuotaWithAdditionalValue(0)).isFalse();
-    }
-
-    @Test
-    public void isOverQuotaWithAdditionalValueShouldThrowOnNegativeValue() {
-        expectedException.expect(IllegalArgumentException.class);
-
-        QuotaImpl.quota(25, 36).isOverQuotaWithAdditionalValue(-1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
index 4b576f6..064be67 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
@@ -51,14 +51,14 @@ public class StoreQuotaManagerTest {
     public void getMessageQuotaShouldWorkWithNumericValues() throws Exception {
         when(mockedMaxQuotaManager.getMaxMessage(quotaRoot)).thenReturn(360L);
         when(mockedCurrentQuotaManager.getCurrentMessageCount(quotaRoot)).thenReturn(36L);
-        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(36, 360));
+        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(Quota.quota(36, 360));
     }
 
     @Test
     public void getStorageQuotaShouldWorkWithNumericValues() throws Exception {
         when(mockedMaxQuotaManager.getMaxStorage(quotaRoot)).thenReturn(360L);
         when(mockedCurrentQuotaManager.getCurrentStorage(quotaRoot)).thenReturn(36L);
-        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(36, 360));
+        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(Quota.quota(36, 360));
     }
 
     @Test
@@ -66,7 +66,7 @@ public class StoreQuotaManagerTest {
         testee.setCalculateWhenUnlimited(false);
         when(mockedMaxQuotaManager.getMaxStorage(quotaRoot)).thenReturn(Quota.UNLIMITED);
 
-        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(Quota.UNKNOWN, Quota.UNLIMITED));
+        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(Quota.quota(Quota.UNKNOWN, Quota.UNLIMITED));
         verify(mockedCurrentQuotaManager, never()).getCurrentStorage(quotaRoot);
     }
 
@@ -75,7 +75,7 @@ public class StoreQuotaManagerTest {
         testee.setCalculateWhenUnlimited(false);
         when(mockedMaxQuotaManager.getMaxMessage(quotaRoot)).thenReturn(Quota.UNLIMITED);
 
-        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(Quota.UNKNOWN, Quota.UNLIMITED));
+        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(Quota.quota(Quota.UNKNOWN, Quota.UNLIMITED));
         verify(mockedCurrentQuotaManager, never()).getCurrentMessageCount(quotaRoot);
     }
 
@@ -85,7 +85,7 @@ public class StoreQuotaManagerTest {
         when(mockedMaxQuotaManager.getMaxStorage(quotaRoot)).thenReturn(Quota.UNLIMITED);
         when(mockedCurrentQuotaManager.getCurrentStorage(quotaRoot)).thenReturn(36L);
 
-        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(36, Quota.UNLIMITED));
+        assertThat(testee.getStorageQuota(quotaRoot)).isEqualTo(Quota.quota(36, Quota.UNLIMITED));
     }
 
     @Test
@@ -94,7 +94,7 @@ public class StoreQuotaManagerTest {
         when(mockedMaxQuotaManager.getMaxMessage(quotaRoot)).thenReturn(Quota.UNLIMITED);
         when(mockedCurrentQuotaManager.getCurrentMessageCount(quotaRoot)).thenReturn(36L);
 
-        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(QuotaImpl.quota(36, Quota.UNLIMITED));
+        assertThat(testee.getMessageQuota(quotaRoot)).isEqualTo(Quota.quota(36, Quota.UNLIMITED));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/protocols/imap/src/test/java/org/apache/james/imap/encode/QuotaResponseEncoderTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/QuotaResponseEncoderTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/QuotaResponseEncoderTest.java
index 8bd49e9..4bfdf5e 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/QuotaResponseEncoderTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/QuotaResponseEncoderTest.java
@@ -25,7 +25,7 @@ import org.apache.james.imap.encode.base.ByteImapResponseWriter;
 import org.apache.james.imap.encode.base.EndImapEncoder;
 import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
 import org.apache.james.imap.message.response.QuotaResponse;
-import org.apache.james.mailbox.store.quota.QuotaImpl;
+import org.apache.james.mailbox.model.Quota;
 import org.junit.Test;
 
 /**
@@ -35,7 +35,7 @@ public class QuotaResponseEncoderTest {
 
     @Test
     public void quotaMessageResponseShouldBeWellFormatted() throws Exception {
-        QuotaResponse response = new QuotaResponse("MESSAGE", "root", QuotaImpl.quota(231, 1024));
+        QuotaResponse response = new QuotaResponse("MESSAGE", "root", Quota.quota(231, 1024));
         ByteImapResponseWriter byteImapResponseWriter = new ByteImapResponseWriter();
         ImapResponseComposer composer = new ImapResponseComposerImpl(byteImapResponseWriter, 1024);
         QuotaResponseEncoder encoder = new QuotaResponseEncoder(new EndImapEncoder());
@@ -46,7 +46,7 @@ public class QuotaResponseEncoderTest {
 
     @Test
     public void quotaStorageResponseShouldBeWellFormatted() throws Exception {
-        QuotaResponse response = new QuotaResponse("STORAGE", "root", QuotaImpl.quota(231 * 1024, 1024 * 1024));
+        QuotaResponse response = new QuotaResponse("STORAGE", "root", Quota.quota(231 * 1024, 1024 * 1024));
         ByteImapResponseWriter byteImapResponseWriter = new ByteImapResponseWriter();
         ImapResponseComposer composer = new ImapResponseComposerImpl(byteImapResponseWriter, 1024);
         QuotaResponseEncoder encoder = new QuotaResponseEncoder(new EndImapEncoder());

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
index e78f679..7984cf4 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
@@ -45,7 +45,6 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
-import org.apache.james.mailbox.store.quota.QuotaImpl;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
@@ -57,8 +56,8 @@ public class GetQuotaProcessorTest {
 
     private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("plop");
     public static final MailboxPath MAILBOX_PATH = new MailboxPath("namespace", "plop", "INBOX");
-    public static final Quota MESSAGE_QUOTA = QuotaImpl.quota(24, 1589);
-    public static final Quota STORAGE_QUOTA = QuotaImpl.quota(240, 15890);
+    public static final Quota MESSAGE_QUOTA = Quota.quota(24, 1589);
+    public static final Quota STORAGE_QUOTA = Quota.quota(240, 15890);
 
     private GetQuotaProcessor testee;
     private ImapSession mockedImapSession;

http://git-wip-us.apache.org/repos/asf/james-project/blob/fc5c1eaa/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
index c435874..93b378f 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
@@ -39,7 +39,6 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
-import org.apache.james.mailbox.store.quota.QuotaImpl;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -51,8 +50,8 @@ public class GetQuotaRootProcessorTest {
 
     private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("plop");
     public static final MailboxPath MAILBOX_PATH = MailboxPath.forUser("plop", "INBOX");
-    public static final Quota MESSAGE_QUOTA = QuotaImpl.quota(24, 1589);
-    public static final Quota STORAGE_QUOTA = QuotaImpl.quota(240, 15890);
+    public static final Quota MESSAGE_QUOTA = Quota.quota(24, 1589);
+    public static final Quota STORAGE_QUOTA = Quota.quota(240, 15890);
 
     private GetQuotaRootProcessor testee;
     private Mockery mockery;


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


[3/5] james-project git commit: JAMES-2344 QuotaRoot is part of mailbox-api and should not require an implementation project to create instances

Posted by ro...@apache.org.
JAMES-2344 QuotaRoot is part of mailbox-api and should not require an implementation project to create instances


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/159886f0
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/159886f0
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/159886f0

Branch: refs/heads/master
Commit: 159886f08bcd73adb2ef43938f0bca014566e43d
Parents: dbe65ce
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Feb 20 16:00:28 2018 +0100
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Feb 27 09:59:23 2018 +0100

----------------------------------------------------------------------
 .../apache/james/mailbox/model/QuotaRoot.java   | 29 ++++++++++-
 .../quota/InMemoryCurrentQuotaManagerTest.java  |  3 +-
 .../store/quota/DefaultQuotaRootResolver.java   |  4 +-
 .../mailbox/store/quota/QuotaRootImpl.java      | 55 --------------------
 .../quota/DefaultQuotaRootResolverTest.java     |  4 +-
 .../store/quota/GenericMaxQuotaManagerTest.java |  2 +-
 .../quota/ListeningCurrentQuotaUpdaterTest.java |  2 +-
 .../mailbox/store/quota/QuotaCheckerTest.java   |  2 +-
 .../quota/StoreCurrentQuotaManagerTest.java     |  2 +-
 .../store/quota/StoreQuotaManagerTest.java      |  2 +-
 .../imap/processor/GetQuotaProcessorTest.java   |  3 +-
 .../processor/GetQuotaRootProcessorTest.java    |  3 +-
 .../james/cli/QuotaCommandsIntegrationTest.java |  3 +-
 13 files changed, 40 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
index ad181d2..885540b 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
@@ -19,11 +19,36 @@
 
 package org.apache.james.mailbox.model;
 
+import com.google.common.base.Objects;
+
 /**
  * Represents RFC 2087 Quota root
  */
-public interface QuotaRoot {
+public class QuotaRoot {
+
+    public static QuotaRoot quotaRoot(String value) {
+        return new QuotaRoot(value);
+    }
+
+    private final String value;
+
+    private QuotaRoot(String value) {
+        this.value = value;
+    }
+
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof QuotaRoot)) {
+            return false;
+        }
+        return value.equals(((QuotaRoot) o).getValue());
+    }
+
+    public int hashCode() {
+        return Objects.hashCode(value);
+    }
 
-    String getValue();
+    public String getValue() {
+        return value;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java
index 9a82bc7..abc5cdb 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/quota/InMemoryCurrentQuotaManagerTest.java
@@ -26,13 +26,12 @@ import static org.mockito.Mockito.when;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.store.quota.CurrentQuotaCalculator;
-import org.apache.james.mailbox.store.quota.QuotaRootImpl;
 import org.junit.Before;
 import org.junit.Test;
 
 public class InMemoryCurrentQuotaManagerTest {
 
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("benwa");
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa");
 
     private InMemoryCurrentQuotaManager testee;
     private CurrentQuotaCalculator mockedCurrentQuotaCalculator;

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolver.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolver.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolver.java
index 793c854..3125b6f 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolver.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolver.java
@@ -48,14 +48,14 @@ public class DefaultQuotaRootResolver implements QuotaRootResolver {
 
     @Override
     public QuotaRoot createQuotaRoot(String quotaRootValue) {
-        return QuotaRootImpl.quotaRoot(quotaRootValue);
+        return QuotaRoot.quotaRoot(quotaRootValue);
     }
 
     @Override
     public QuotaRoot getQuotaRoot(MailboxPath mailboxPath) throws MailboxException {
         Preconditions.checkArgument(!mailboxPath.getNamespace().contains(SEPARATOR), "Namespace should not contain " + SEPARATOR);
         Preconditions.checkArgument(!mailboxPath.getUser().contains(SEPARATOR), "Username should not contain " + SEPARATOR);
-        return QuotaRootImpl.quotaRoot(mailboxPath.getNamespace() + SEPARATOR + mailboxPath.getUser());
+        return QuotaRoot.quotaRoot(mailboxPath.getNamespace() + SEPARATOR + mailboxPath.getUser());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaRootImpl.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaRootImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaRootImpl.java
deleted file mode 100644
index 6ef8e4e..0000000
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/quota/QuotaRootImpl.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************
- * 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.mailbox.store.quota;
-
-import org.apache.james.mailbox.model.QuotaRoot;
-
-import com.google.common.base.Objects;
-
-public class QuotaRootImpl implements QuotaRoot {
-
-    public static QuotaRoot quotaRoot(String value) {
-        return new QuotaRootImpl(value);
-    }
-
-    private final String value;
-
-    private QuotaRootImpl(String value) {
-        this.value = value;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == null || !(o instanceof QuotaRoot)) {
-            return false;
-        }
-        return value.equals(((QuotaRoot) o).getValue());
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(value);
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolverTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolverTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolverTest.java
index bc18ae8..89c46da 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolverTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/DefaultQuotaRootResolverTest.java
@@ -41,7 +41,7 @@ public class DefaultQuotaRootResolverTest {
     public static final MailboxPath PATH_LIKE = MailboxPath.forUser("benwa", "%");
     public static final MailboxPath MAILBOX_PATH_2 = MailboxPath.forUser("benwa", "test");
     public static final SimpleMailbox MAILBOX_2 = new SimpleMailbox(MAILBOX_PATH_2, 10);
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("#private&benwa");
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&benwa");
 
     private DefaultQuotaRootResolver testee;
     private MailboxSessionMapperFactory mockedFactory;
@@ -77,7 +77,7 @@ public class DefaultQuotaRootResolverTest {
 
     @Test(expected = MailboxException.class)
     public void retrieveAssociatedMailboxesShouldThrowWhenQuotaRootNotContainsSeparator2Times() throws Exception {
-        testee.retrieveAssociatedMailboxes(QuotaRootImpl.quotaRoot("#private&be&nwa"), null);
+        testee.retrieveAssociatedMailboxes(QuotaRoot.quotaRoot("#private&be&nwa"), null);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/GenericMaxQuotaManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/GenericMaxQuotaManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/GenericMaxQuotaManagerTest.java
index e0de93a..148a899 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/GenericMaxQuotaManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/GenericMaxQuotaManagerTest.java
@@ -37,7 +37,7 @@ public abstract class GenericMaxQuotaManagerTest {
     @Before
     public void setUp() {
         maxQuotaManager = provideMaxQuotaManager();
-        quotaRoot = QuotaRootImpl.quotaRoot("benwa");
+        quotaRoot = QuotaRoot.quotaRoot("benwa");
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/ListeningCurrentQuotaUpdaterTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/ListeningCurrentQuotaUpdaterTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/ListeningCurrentQuotaUpdaterTest.java
index 2e56542..3fe73df 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/ListeningCurrentQuotaUpdaterTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/ListeningCurrentQuotaUpdaterTest.java
@@ -44,7 +44,7 @@ public class ListeningCurrentQuotaUpdaterTest {
 
     public static final int SIZE = 45;
     public static final MailboxPath MAILBOX_PATH = MailboxPath.forUser("benwa", "INBOX");
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("benwa");
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa");
 
     private StoreCurrentQuotaManager mockedCurrentQuotaManager;
     private QuotaRootResolver mockedQuotaRootResolver;

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
index 1902e84..7566e88 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/QuotaCheckerTest.java
@@ -36,7 +36,7 @@ import org.junit.Test;
 
 public class QuotaCheckerTest {
 
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("benwa");
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa");
     public static final MailboxPath MAILBOX_PATH = MailboxPath.forUser("benwa", "INBOX");
     public static final SimpleMailbox MAILBOX = new SimpleMailbox(MAILBOX_PATH, 10);
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java
index c5aa4d3..fcec1c7 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreCurrentQuotaManagerTest.java
@@ -26,7 +26,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 public abstract class StoreCurrentQuotaManagerTest {
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("benwa");
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("benwa");
     
     protected abstract StoreCurrentQuotaManager provideTestee();
     

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
index a73a34e..4b576f6 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/quota/StoreQuotaManagerTest.java
@@ -44,7 +44,7 @@ public class StoreQuotaManagerTest {
         mockedCurrentQuotaManager = mock(CurrentQuotaManager.class);
         mockedMaxQuotaManager = mock(MaxQuotaManager.class);
         testee = new StoreQuotaManager(mockedCurrentQuotaManager, mockedMaxQuotaManager);
-        quotaRoot = QuotaRootImpl.quotaRoot("benwa");
+        quotaRoot = QuotaRoot.quotaRoot("benwa");
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
index fadbc3b..e78f679 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
@@ -46,7 +46,6 @@ import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.quota.QuotaImpl;
-import org.apache.james.mailbox.store.quota.QuotaRootImpl;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
@@ -56,7 +55,7 @@ import com.google.common.collect.ImmutableList;
 
 public class GetQuotaProcessorTest {
 
-    private static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("plop");
+    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("plop");
     public static final MailboxPath MAILBOX_PATH = new MailboxPath("namespace", "plop", "INBOX");
     public static final Quota MESSAGE_QUOTA = QuotaImpl.quota(24, 1589);
     public static final Quota STORAGE_QUOTA = QuotaImpl.quota(240, 15890);

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
index f4057df..c435874 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
@@ -40,7 +40,6 @@ import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
 import org.apache.james.mailbox.store.quota.QuotaImpl;
-import org.apache.james.mailbox.store.quota.QuotaRootImpl;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -50,7 +49,7 @@ import org.junit.Test;
 
 public class GetQuotaRootProcessorTest {
 
-    private static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("plop");
+    private static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("plop");
     public static final MailboxPath MAILBOX_PATH = MailboxPath.forUser("plop", "INBOX");
     public static final Quota MESSAGE_QUOTA = QuotaImpl.quota(24, 1589);
     public static final Quota STORAGE_QUOTA = QuotaImpl.quota(240, 15890);

http://git-wip-us.apache.org/repos/asf/james-project/blob/159886f0/server/container/cli-integration/src/test/java/org/apache/james/cli/QuotaCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/container/cli-integration/src/test/java/org/apache/james/cli/QuotaCommandsIntegrationTest.java b/server/container/cli-integration/src/test/java/org/apache/james/cli/QuotaCommandsIntegrationTest.java
index 551a5f0..fc8fb7a 100644
--- a/server/container/cli-integration/src/test/java/org/apache/james/cli/QuotaCommandsIntegrationTest.java
+++ b/server/container/cli-integration/src/test/java/org/apache/james/cli/QuotaCommandsIntegrationTest.java
@@ -26,7 +26,6 @@ import org.apache.james.GuiceJamesServer;
 import org.apache.james.MemoryJmapTestRule;
 import org.apache.james.cli.util.OutputCapture;
 import org.apache.james.mailbox.model.QuotaRoot;
-import org.apache.james.mailbox.store.quota.QuotaRootImpl;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
 import org.apache.james.modules.QuotaProbesImpl;
 import org.apache.james.modules.server.JMXServerModule;
@@ -37,7 +36,7 @@ import org.junit.Test;
 
 public class QuotaCommandsIntegrationTest {
     public static final String USER = "user";
-    public static final QuotaRoot QUOTA_ROOT = QuotaRootImpl.quotaRoot("#private&" + USER);
+    public static final QuotaRoot QUOTA_ROOT = QuotaRoot.quotaRoot("#private&" + USER);
     private OutputCapture outputCapture;
 
     @Rule


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


[4/5] james-project git commit: JAMES-2344 First implementation of admin API for User Quota

Posted by ro...@apache.org.
JAMES-2344 First implementation of admin API for User Quota


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/e87c0553
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/e87c0553
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/e87c0553

Branch: refs/heads/master
Commit: e87c05530de5d53d1d38d83fce86717cd2ef6f79
Parents: 159886f
Author: Matthieu Baechler <ma...@apache.org>
Authored: Tue Feb 20 18:39:52 2018 +0100
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Tue Feb 27 09:59:23 2018 +0100

----------------------------------------------------------------------
 .../apache/james/mailbox/model/QuotaRoot.java   |   6 +
 .../protocols/webadmin/webadmin-mailbox/pom.xml |   6 +
 .../james/webadmin/routes/UserQuotaRoutes.java  | 281 ++++++++++++
 .../webadmin/service/UserQuotaService.java      |  77 ++++
 .../webadmin/routes/UserQuotaRoutesTest.java    | 457 +++++++++++++++++++
 5 files changed, 827 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/e87c0553/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
index 885540b..debb37a 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/QuotaRoot.java
@@ -26,6 +26,12 @@ import com.google.common.base.Objects;
  */
 public class QuotaRoot {
 
+    private static final String USER = "user-";
+
+    public static QuotaRoot forUser(String value) {
+        return new QuotaRoot(USER + value);
+    }
+
     public static QuotaRoot quotaRoot(String value) {
         return new QuotaRoot(value);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e87c0553/server/protocols/webadmin/webadmin-mailbox/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/pom.xml b/server/protocols/webadmin/webadmin-mailbox/pom.xml
index dfe3820..bfed1ee 100644
--- a/server/protocols/webadmin/webadmin-mailbox/pom.xml
+++ b/server/protocols/webadmin/webadmin-mailbox/pom.xml
@@ -35,6 +35,12 @@
     <dependencies>
         <dependency>
             <groupId>${project.groupId}</groupId>
+            <artifactId>james-server-dnsservice-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
             <artifactId>apache-james-mailbox-api</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/e87c0553/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
new file mode 100644
index 0000000..b72d65f
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java
@@ -0,0 +1,281 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import javax.inject.Inject;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.dto.QuotaDTO;
+import org.apache.james.webadmin.dto.QuotaRequest;
+import org.apache.james.webadmin.service.UserQuotaService;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
+import org.apache.james.webadmin.utils.JsonExtractException;
+import org.apache.james.webadmin.utils.JsonExtractor;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import spark.Request;
+import spark.Service;
+
+@Api(tags = "UserQuota")
+@Path(UserQuotaRoutes.QUOTA_ENDPOINT)
+@Produces("application/json")
+public class UserQuotaRoutes implements Routes {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(Routes.class);
+
+    private static final String USER = "user";
+    static final String QUOTA_ENDPOINT = "/quota/users/:" + USER;
+    private static final String COUNT_ENDPOINT = QUOTA_ENDPOINT + "/count";
+    private static final String SIZE_ENDPOINT = QUOTA_ENDPOINT + "/size";
+
+    private final UsersRepository usersRepository;
+    private final UserQuotaService userQuotaService;
+    private final JsonTransformer jsonTransformer;
+    private final JsonExtractor<QuotaDTO> jsonExtractor;
+    private Service service;
+
+    @Inject
+    public UserQuotaRoutes(UsersRepository usersRepository, UserQuotaService userQuotaService, JsonTransformer jsonTransformer) {
+        this.usersRepository = usersRepository;
+        this.userQuotaService = userQuotaService;
+        this.jsonTransformer = jsonTransformer;
+        this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class);
+    }
+
+    @Override
+    public void define(Service service) {
+        this.service = service;
+
+        defineGetQuotaCount();
+        defineDeleteQuotaCount();
+        defineUpdateQuotaCount();
+
+        defineGetQuotaSize();
+        defineDeleteQuotaSize();
+        defineUpdateQuotaSize();
+
+        defineGetQuota();
+        defineUpdateQuota();
+    }
+
+    @PUT
+    @ApiOperation(value = "Updating count and size at the same time")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "org.apache.james.webadmin.dto.QuotaDTO", paramType = "body")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. The value has been updated."),
+            @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The body is not a positive integer or not unlimited value (-1)."),
+            @ApiResponse(code = HttpStatus.CONFLICT_409, message = "The requested restriction can't be enforced right now."),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineUpdateQuota() {
+        service.put(QUOTA_ENDPOINT, ((request, response) -> {
+            String user = checkUserExist(request);
+            QuotaDTO quotaDTO = parseQuotaDTO(request);
+            userQuotaService.defineQuota(user, quotaDTO);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
+        }));
+    }
+
+    @GET
+    @ApiOperation(
+        value = "Reading count and size at the same time",
+        notes = "If there is no limitation for count and/or size, the returned value will be -1"
+    )
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = QuotaDTO.class),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineGetQuota() {
+        service.get(QUOTA_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            return userQuotaService.getQuota(user);
+        }, jsonTransformer);
+    }
+
+    @DELETE
+    @Path("/size")
+    @ApiOperation(value = "Removing per user mail size limitation by updating to unlimited value")
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "The value is updated to unlimited value."),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineDeleteQuotaSize() {
+        service.delete(SIZE_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            userQuotaService.deleteMaxSizeQuota(user);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
+        });
+    }
+
+    @PUT
+    @Path("/size")
+    @ApiOperation(value = "Updating per user mail size limitation")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "integer", paramType = "body")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. The value has been updated."),
+            @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The body is not a positive integer."),
+            @ApiResponse(code = HttpStatus.CONFLICT_409, message = "The requested restriction can't be enforced right now."),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineUpdateQuotaSize() {
+        service.put(SIZE_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            QuotaRequest quotaRequest = parseQuotaRequest(request);
+            userQuotaService.defineMaxSizeQuota(user, quotaRequest);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
+        });
+    }
+
+    @GET
+    @Path("/size")
+    @ApiOperation(value = "Reading per user mail size limitation")
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = Long.class),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineGetQuotaSize() {
+        service.get(SIZE_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            return userQuotaService.getMaxSizeQuota(user);
+        }, jsonTransformer);
+    }
+
+    @DELETE
+    @Path("/count")
+    @ApiOperation(value = "Removing per user mail count limitation by updating to unlimited value")
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "The value is updated to unlimited value."),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineDeleteQuotaCount() {
+        service.delete(COUNT_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            userQuotaService.deleteMaxCountQuota(user);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
+        });
+    }
+
+    @PUT
+    @Path("/count")
+    @ApiOperation(value = "Updating per user mail count limitation")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "integer", paramType = "body")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. The value has been updated."),
+            @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The body is not a positive integer."),
+            @ApiResponse(code = HttpStatus.CONFLICT_409, message = "The requested restriction can't be enforced right now."),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineUpdateQuotaCount() {
+        service.put(COUNT_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            QuotaRequest quotaRequest = parseQuotaRequest(request);
+            userQuotaService.defineMaxCountQuota(user, quotaRequest);
+            response.status(HttpStatus.NO_CONTENT_204);
+            return response;
+        });
+    }
+
+    @GET
+    @Path("/count")
+    @ApiOperation(value = "Reading per user mail count limitation")
+    @ApiResponses(value = {
+            @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = Long.class),
+            @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
+    })
+    public void defineGetQuotaCount() {
+        service.get(COUNT_ENDPOINT, (request, response) -> {
+            String user = checkUserExist(request);
+            return userQuotaService.getMaxCountQuota(user);
+        }, jsonTransformer);
+    }
+
+    private String checkUserExist(Request request) throws UsersRepositoryException {
+        String user = request.params(USER);
+        if (!usersRepository.contains(user)) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.NOT_FOUND_404)
+                .type(ErrorType.NOT_FOUND)
+                .message("User not found")
+                .haltError();
+        }
+        return user;
+    }
+
+    private QuotaDTO parseQuotaDTO(Request request) {
+        try {
+            return jsonExtractor.parse(request.body());
+        } catch (IllegalArgumentException e) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorType.INVALID_ARGUMENT)
+                .message("Quota should be positive or unlimited (-1)")
+                .cause(e)
+                .haltError();
+        } catch (JsonExtractException e) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorType.INVALID_ARGUMENT)
+                .message("Malformed JSON input")
+                .cause(e)
+                .haltError();
+        }
+    }
+
+    private QuotaRequest parseQuotaRequest(Request request) {
+        try {
+            return QuotaRequest.parse(request.body());
+        } catch (IllegalArgumentException e) {
+            LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorType.INVALID_ARGUMENT)
+                .message("Invalid quota. Need to be an integer value greater than 0")
+                .cause(e)
+                .haltError();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/e87c0553/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
new file mode 100644
index 0000000..ddaf630
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserQuotaService.java
@@ -0,0 +1,77 @@
+/****************************************************************
+ * 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.webadmin.service;
+
+import javax.inject.Inject;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.webadmin.dto.QuotaDTO;
+import org.apache.james.webadmin.dto.QuotaRequest;
+
+public class UserQuotaService {
+
+    private final MaxQuotaManager maxQuotaManager;
+
+    @Inject
+    public UserQuotaService(MaxQuotaManager maxQuotaManager) {
+        this.maxQuotaManager = maxQuotaManager;
+    }
+
+    public void defineQuota(String user, QuotaDTO quota) throws MailboxException {
+        QuotaRoot quotaRoot = QuotaRoot.forUser(user);
+        maxQuotaManager.setMaxMessage(quotaRoot, quota.getCount());
+        maxQuotaManager.setMaxStorage(quotaRoot, quota.getSize());
+    }
+
+    public QuotaDTO getQuota(String user) throws MailboxException {
+        QuotaRoot quotaRoot = QuotaRoot.forUser(user);
+        return QuotaDTO
+            .builder()
+            .count(maxQuotaManager.getMaxMessage(quotaRoot))
+            .size(maxQuotaManager.getMaxStorage(quotaRoot))
+            .build();
+    }
+
+    public Long getMaxSizeQuota(String user) throws MailboxException {
+        return maxQuotaManager.getMaxStorage(QuotaRoot.forUser(user));
+    }
+
+    public void defineMaxSizeQuota(String user, QuotaRequest quotaRequest) throws MailboxException {
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), quotaRequest.getValue());
+    }
+
+    public void deleteMaxSizeQuota(String user) throws MailboxException {
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), Quota.UNLIMITED);
+    }
+
+    public Long getMaxCountQuota(String user) throws MailboxException {
+        return maxQuotaManager.getMaxMessage(QuotaRoot.forUser(user));
+    }
+
+    public void defineMaxCountQuota(String user, QuotaRequest quotaRequest) throws MailboxException {
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), quotaRequest.getValue());
+    }
+
+    public void deleteMaxCountQuota(String user) throws MailboxException {
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), Quota.UNLIMITED);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/e87c0553/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
new file mode 100644
index 0000000..86a09af
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java
@@ -0,0 +1,457 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static com.jayway.restassured.RestAssured.given;
+import static com.jayway.restassured.RestAssured.when;
+import static org.apache.james.mailbox.model.Quota.UNLIMITED;
+import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
+
+import org.apache.james.dnsservice.api.InMemoryDNSService;
+import org.apache.james.domainlist.memory.MemoryDomainList;
+import org.apache.james.mailbox.inmemory.quota.InMemoryPerUserMaxQuotaManager;
+import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.memory.MemoryUsersRepository;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.service.UserQuotaService;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.path.json.JsonPath;
+
+public class UserQuotaRoutesTest {
+
+    private static final String QUOTA_USERS = "/quota/users";
+    private static final String PERDU_COM = "perdu.com";
+    private static final String BOB = "bob@" + PERDU_COM;
+    private static final String JOE = "joe@" + PERDU_COM;
+    private static final String PASSWORD = "secret";
+    private static final String COUNT = "count";
+    private static final String SIZE = "size";
+    private WebAdminServer webAdminServer;
+    private InMemoryPerUserMaxQuotaManager maxQuotaManager;
+    private MemoryUsersRepository usersRepository;
+
+    @Before
+    public void setUp() throws Exception {
+        maxQuotaManager = new InMemoryPerUserMaxQuotaManager();
+        MemoryDomainList memoryDomainList = new MemoryDomainList(new InMemoryDNSService());
+        memoryDomainList.setAutoDetect(false);
+        memoryDomainList.addDomain(PERDU_COM);
+        usersRepository = MemoryUsersRepository.withVirtualHosting();
+        usersRepository.setDomainList(memoryDomainList);
+        usersRepository.addUser(BOB, PASSWORD);
+        UserQuotaService userQuotaService = new UserQuotaService(maxQuotaManager);
+        UserQuotaRoutes userQuotaRoutes = new UserQuotaRoutes(usersRepository, userQuotaService, new JsonTransformer());
+        webAdminServer = WebAdminUtils.createWebAdminServer(
+            new NoopMetricFactory(),
+            userQuotaRoutes);
+        webAdminServer.configure(NO_CONFIGURATION);
+        webAdminServer.await();
+
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+            .build();
+        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+    }
+
+    @After
+    public void stop() {
+        webAdminServer.destroy();
+    }
+
+    @Test
+    public void getCountShouldReturnNotFoundWhenUserDoesntExist() {
+        when()
+            .get(QUOTA_USERS + "/" + JOE + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void getCountShouldReturnUnlimitedByDefault() throws UsersRepositoryException {
+        long quota =
+            given()
+                .get(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(quota).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getCountShouldReturnStoredValue() throws Exception {
+        int value = 42;
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(BOB), value);
+
+        Long actual =
+            given()
+                .get(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(actual).isEqualTo(value);
+    }
+
+    @Test
+    public void putCountShouldReturnNotFoundWhenUserDoesntExist() {
+        given()
+            .body("invalid")
+        .when()
+            .put(QUOTA_USERS + "/" + JOE + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+
+    @Test
+    public void putCountShouldRejectInvalid() throws Exception {
+        Map<String, Object> errors = given()
+            .body("invalid")
+            .put(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .contentType(ContentType.JSON)
+            .extract()
+            .body()
+            .jsonPath()
+            .getMap(".");
+
+        assertThat(errors)
+            .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+            .containsEntry("type", "InvalidArgument")
+            .containsEntry("message", "Invalid quota. Need to be an integer value greater than 0")
+            .containsEntry("cause", "For input string: \"invalid\"");
+    }
+
+    @Test
+    public void putCountShouldRejectNegative() throws Exception {
+        Map<String, Object> errors = given()
+            .body("-1")
+            .put(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .contentType(ContentType.JSON)
+            .extract()
+            .body()
+            .jsonPath()
+            .getMap(".");
+
+        assertThat(errors)
+            .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+            .containsEntry("type", "InvalidArgument")
+            .containsEntry("message", "Invalid quota. Need to be an integer value greater than 0");
+    }
+
+    @Test
+    public void putCountShouldAcceptValidValue() throws Exception {
+        given()
+            .body("42")
+            .put(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxMessage(QuotaRoot.forUser(BOB))).isEqualTo(42);
+    }
+
+
+    @Test
+    @Ignore("no link between quota and mailbox for now")
+    public void putCountShouldRejectTooSmallValue() throws Exception {
+        given()
+            .body("42")
+            .put(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+            .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxMessage(QuotaRoot.forUser(BOB))).isEqualTo(42);
+    }
+
+    @Test
+    public void deleteCountShouldReturnNotFoundWhenUserDoesntExist() {
+        when()
+            .delete(QUOTA_USERS + "/" + JOE + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+
+    @Test
+    public void deleteCountShouldSetQuotaToUnlimited() throws Exception {
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(BOB), 42);
+
+        given()
+            .delete(QUOTA_USERS + "/" + BOB + "/" + COUNT)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxMessage(QuotaRoot.forUser(BOB))).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getSizeShouldReturnNotFoundWhenUserDoesntExist() {
+            when()
+                .get(QUOTA_USERS + "/" + JOE + "/" + SIZE)
+            .then()
+                .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void getSizeShouldReturnUnlimitedByDefault() throws UsersRepositoryException {
+        long quota =
+            given()
+                .get(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(quota).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getSizeShouldReturnStoredValue() throws Exception {
+        long value = 42;
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(BOB), value);
+
+
+        long quota =
+            given()
+                .get(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(quota).isEqualTo(value);
+    }
+
+    @Test
+    public void putSizeShouldRejectInvalid() throws Exception {
+        Map<String, Object> errors = given()
+            .body("invalid")
+            .put(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .contentType(ContentType.JSON)
+            .extract()
+            .body()
+            .jsonPath()
+            .getMap(".");
+
+        assertThat(errors)
+            .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+            .containsEntry("type", "InvalidArgument")
+            .containsEntry("message", "Invalid quota. Need to be an integer value greater than 0")
+            .containsEntry("cause", "For input string: \"invalid\"");
+    }
+
+    @Test
+    public void putSizeShouldReturnNotFoundWhenUserDoesntExist() throws Exception {
+        given()
+            .body("123")
+        .when()
+            .put(QUOTA_USERS + "/" + JOE + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void putSizeShouldRejectNegative() throws Exception {
+        Map<String, Object> errors = given()
+            .body("-1")
+            .put(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .contentType(ContentType.JSON)
+            .extract()
+            .body()
+            .jsonPath()
+            .getMap(".");
+
+        assertThat(errors)
+            .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+            .containsEntry("type", "InvalidArgument")
+            .containsEntry("message", "Invalid quota. Need to be an integer value greater than 0");
+    }
+
+    @Test
+    public void putSizeShouldAcceptValidValue() throws Exception {
+        given()
+            .body("42")
+            .put(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxStorage(QuotaRoot.forUser(BOB))).isEqualTo(42);
+    }
+
+    @Test
+    public void deleteSizeShouldReturnNotFoundWhenUserDoesntExist() throws Exception {
+        when()
+            .delete(QUOTA_USERS + "/" + JOE + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void deleteSizeShouldSetQuotaToUnlimited() throws Exception {
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(BOB), 42);
+
+        given()
+            .delete(QUOTA_USERS + "/" + BOB + "/" + SIZE)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxStorage(QuotaRoot.forUser(BOB))).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getQuotaShouldReturnNotFoundWhenUserDoesntExist() throws Exception {
+        when()
+            .get(QUOTA_USERS + "/" + JOE)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void getQuotaShouldReturnBothWhenValueSpecified() throws Exception {
+        int maxStorage = 42;
+        int maxMessage = 52;
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(BOB), maxStorage);
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(BOB), maxMessage);
+
+        JsonPath jsonPath =
+            given()
+                .get(QUOTA_USERS + "/" + BOB)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .jsonPath();
+
+        assertThat(jsonPath.getLong(SIZE)).isEqualTo(maxStorage);
+        assertThat(jsonPath.getLong(COUNT)).isEqualTo(maxMessage);
+    }
+
+    @Test
+    public void getQuotaShouldReturnBothDefaultValues() throws Exception {
+        JsonPath jsonPath =
+            given()
+                .get(QUOTA_USERS + "/" + BOB)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .jsonPath();
+
+        assertThat(jsonPath.getLong(SIZE)).isEqualTo(UNLIMITED);
+        assertThat(jsonPath.getLong(COUNT)).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getQuotaShouldReturnBothWhenNoCount() throws Exception {
+        int maxStorage = 42;
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(BOB), maxStorage);
+
+        JsonPath jsonPath =
+            given()
+                .get(QUOTA_USERS + "/" + BOB)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .jsonPath();
+
+        assertThat(jsonPath.getLong(SIZE)).isEqualTo(maxStorage);
+        assertThat(jsonPath.getLong(COUNT)).isEqualTo(UNLIMITED);
+    }
+
+    @Test
+    public void getQuotaShouldReturnBothWhenNoSize() throws Exception {
+        int maxMessage = 42;
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(BOB), maxMessage);
+
+
+        JsonPath jsonPath =
+            given()
+                .get(QUOTA_USERS + "/" + BOB)
+                .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .jsonPath();
+
+        assertThat(jsonPath.getLong(SIZE)).isEqualTo(UNLIMITED);
+        assertThat(jsonPath.getLong(COUNT)).isEqualTo(maxMessage);
+    }
+
+    @Test
+    public void putQuotaShouldReturnNotFoundWhenUserDoesntExist() throws Exception {
+        when()
+            .put(QUOTA_USERS + "/" + JOE)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void putQuotaShouldUpdateBothQuota() throws Exception {
+        given()
+            .body("{\"" + COUNT + "\":52,\"" + SIZE + "\":42}")
+            .put(QUOTA_USERS + "/" + BOB)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxMessage(QuotaRoot.forUser(BOB))).isEqualTo(52);
+        assertThat(maxQuotaManager.getMaxStorage(QuotaRoot.forUser(BOB))).isEqualTo(42);
+    }
+
+    @Test
+    public void putQuotaShouldBeAbleToRemoveBothQuota() throws Exception {
+        given()
+            .body("{\"" + COUNT + "\":-1,\"" + SIZE + "\":-1}")
+            .put(QUOTA_USERS + "/" + BOB)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(maxQuotaManager.getMaxMessage(QuotaRoot.forUser(BOB))).isEqualTo(UNLIMITED);
+        assertThat(maxQuotaManager.getMaxStorage(QuotaRoot.forUser(BOB))).isEqualTo(UNLIMITED);
+    }
+
+}


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