http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 4bfdf5e..135b4a5 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
@@ -26,6 +26,8 @@ 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.model.Quota;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.junit.Test;
 
 /**
@@ -35,7 +37,7 @@ public class QuotaResponseEncoderTest {
 
     @Test
     public void quotaMessageResponseShouldBeWellFormatted() throws Exception {
-        QuotaResponse response = new QuotaResponse("MESSAGE", "root", 
Quota.quota(231, 1024));
+        QuotaResponse response = new QuotaResponse("MESSAGE", "root", 
Quota.quota(QuotaCount.count(231), QuotaCount.count(1024)));
         ByteImapResponseWriter byteImapResponseWriter = new 
ByteImapResponseWriter();
         ImapResponseComposer composer = new 
ImapResponseComposerImpl(byteImapResponseWriter, 1024);
         QuotaResponseEncoder encoder = new QuotaResponseEncoder(new 
EndImapEncoder());
@@ -46,7 +48,7 @@ public class QuotaResponseEncoderTest {
 
     @Test
     public void quotaStorageResponseShouldBeWellFormatted() throws Exception {
-        QuotaResponse response = new QuotaResponse("STORAGE", "root", 
Quota.quota(231 * 1024, 1024 * 1024));
+        QuotaResponse response = new QuotaResponse("STORAGE", "root", 
Quota.quota(QuotaSize.size(231 * 1024), QuotaSize.size(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/ebcb09a0/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 7984cf4..9f52053 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
@@ -43,8 +43,10 @@ import org.apache.james.mailbox.model.MailboxACL;
 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.QuotaCount;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
@@ -56,8 +58,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 = Quota.quota(24, 1589);
-    public static final Quota STORAGE_QUOTA = Quota.quota(240, 15890);
+    public static final Quota<QuotaCount> MESSAGE_QUOTA = 
Quota.quota(QuotaCount.count(24), QuotaCount.count(1589));
+    public static final Quota<QuotaSize> STORAGE_QUOTA = 
Quota.quota(QuotaSize.size(240), QuotaSize.size(15890));
 
     private GetQuotaProcessor testee;
     private ImapSession mockedImapSession;

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 93b378f..9021b65 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
@@ -37,8 +37,10 @@ import org.apache.james.mailbox.model.MailboxACL;
 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.QuotaCount;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.metrics.api.NoopMetricFactory;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -50,8 +52,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 = Quota.quota(24, 1589);
-    public static final Quota STORAGE_QUOTA = Quota.quota(240, 15890);
+    public static final Quota<QuotaCount> MESSAGE_QUOTA = 
Quota.quota(QuotaCount.count(24), QuotaCount.count(1589));
+    public static final Quota<QuotaSize> STORAGE_QUOTA = 
Quota.quota(QuotaSize.size(240), QuotaSize.size(15890));
 
     private GetQuotaRootProcessor testee;
     private Mockery mockery;

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/cli/src/main/java/org/apache/james/cli/ServerCmd.java
----------------------------------------------------------------------
diff --git 
a/server/container/cli/src/main/java/org/apache/james/cli/ServerCmd.java 
b/server/container/cli/src/main/java/org/apache/james/cli/ServerCmd.java
index 2c4d73f..54e4eaf 100644
--- a/server/container/cli/src/main/java/org/apache/james/cli/ServerCmd.java
+++ b/server/container/cli/src/main/java/org/apache/james/cli/ServerCmd.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
@@ -44,7 +45,8 @@ import org.apache.james.cli.probe.impl.JmxQuotaProbe;
 import org.apache.james.cli.probe.impl.JmxSieveProbe;
 import org.apache.james.cli.type.CmdType;
 import org.apache.james.cli.utils.ValueWithUnit;
-import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 import org.apache.james.mailbox.store.probe.MailboxProbe;
 import org.apache.james.mailbox.store.probe.QuotaProbe;
@@ -283,16 +285,16 @@ public class ServerCmd {
             printStream.println("MailboxMessage count allowed for Quota Root " 
+ arguments[1] + ": " + 
formatMessageValue(quotaProbe.getMaxMessageCount(arguments[1])));
             break;
         case SETMAXSTORAGEQUOTA:
-            quotaProbe.setMaxStorage(arguments[1], 
ValueWithUnit.parse(arguments[2]).getConvertedValue());
+            quotaProbe.setMaxStorage(arguments[1], 
QuotaSize.size(ValueWithUnit.parse(arguments[2]).getConvertedValue()));
             break;
         case SETMAXMESSAGECOUNTQUOTA:
-            quotaProbe.setMaxMessageCount(arguments[1], 
Long.parseLong(arguments[2]));
+            quotaProbe.setMaxMessageCount(arguments[1], 
QuotaCount.count(Long.parseLong(arguments[2])));
             break;
         case SETDEFAULTMAXSTORAGEQUOTA:
-            
quotaProbe.setDefaultMaxStorage(ValueWithUnit.parse(arguments[1]).getConvertedValue());
+            
quotaProbe.setDefaultMaxStorage(QuotaSize.size(ValueWithUnit.parse(arguments[1]).getConvertedValue()));
             break;
         case SETDEFAULTMAXMESSAGECOUNTQUOTA:
-            quotaProbe.setDefaultMaxMessageCount(Long.parseLong(arguments[1]));
+            
quotaProbe.setDefaultMaxMessageCount(QuotaCount.count(Long.parseLong(arguments[1])));
             break;
         case GETDEFAULTMAXSTORAGEQUOTA:
             printStream.println("Default Maximum Storage Quota: " + 
formatStorageValue(quotaProbe.getDefaultMaxStorage()));
@@ -343,40 +345,58 @@ public class ServerCmd {
         }
     }
 
-    private void printStorageQuota(String quotaRootString, SerializableQuota 
quota, PrintStream printStream) {
+    private void printStorageQuota(String quotaRootString, 
SerializableQuota<QuotaSize> quota, PrintStream printStream) {
         printStream.println(String.format("Storage quota for %s is: %s / %s",
             quotaRootString,
             formatStorageValue(quota.getUsed()),
-            formatStorageValue(quota.getMax())));
+            formatStorageValue(quota.encodeAsLong())));
     }
 
-    private void printMessageQuota(String quotaRootString, SerializableQuota 
quota, PrintStream printStream) {
+    private void printMessageQuota(String quotaRootString, 
SerializableQuota<QuotaCount> quota, PrintStream printStream) {
         printStream.println(String.format("MailboxMessage count quota for %s 
is: %s / %s",
             quotaRootString,
             formatMessageValue(quota.getUsed()),
-            formatMessageValue(quota.getMax())));
+            formatMessageValue(quota.encodeAsLong())));
     }
 
-    private String formatStorageValue(long value) {
-        if (value == Quota.UNKNOWN) {
+    private String formatStorageValue(Long value) {
+        if (value == null) {
             return ValueWithUnit.UNKNOWN;
         }
-        if (value == Quota.UNLIMITED) {
+        if (value == SerializableQuota.UNLIMITED) {
             return ValueWithUnit.UNLIMITED;
         }
         return FileUtils.byteCountToDisplaySize(value);
     }
 
-    private String formatMessageValue(long value) {
-        if (value == Quota.UNKNOWN) {
+    private String formatStorageValue(Optional<QuotaSize> value) {
+        return value.map(size -> {
+            if (size.isUnlimited()) {
+                return ValueWithUnit.UNLIMITED;
+            }
+            return FileUtils.byteCountToDisplaySize(size.asLong());
+        }).orElse(ValueWithUnit.UNKNOWN);
+    }
+
+    private String formatMessageValue(Long value) {
+        if (value == null) {
             return ValueWithUnit.UNKNOWN;
         }
-        if (value == Quota.UNLIMITED) {
+        if (value == SerializableQuota.UNLIMITED) {
             return ValueWithUnit.UNLIMITED;
         }
         return String.valueOf(value);
     }
 
+    private String formatMessageValue(Optional<QuotaCount> value) {
+        return value.map(count -> {
+            if (count.isUnlimited()) {
+                return ValueWithUnit.UNLIMITED;
+            }
+            return String.valueOf(count.asLong());
+        }).orElse(ValueWithUnit.UNKNOWN);
+    }
+
     private void print(Map<String, Mappings> map, PrintStream out) {
         if (map != null) {
             for (Entry<String, Mappings> entry : map.entrySet()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxQuotaProbe.java
----------------------------------------------------------------------
diff --git 
a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxQuotaProbe.java
 
b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxQuotaProbe.java
index 05d35b2..a03c89a 100644
--- 
a/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxQuotaProbe.java
+++ 
b/server/container/cli/src/main/java/org/apache/james/cli/probe/impl/JmxQuotaProbe.java
@@ -20,11 +20,14 @@
 package org.apache.james.cli.probe.impl;
 
 import java.io.IOException;
+import java.util.Optional;
 
 import javax.management.MalformedObjectNameException;
 
 import org.apache.james.adapter.mailbox.QuotaManagementMBean;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 import org.apache.james.mailbox.store.probe.QuotaProbe;
 
@@ -48,52 +51,52 @@ public class JmxQuotaProbe implements QuotaProbe, JmxProbe {
     }
 
     @Override
-    public SerializableQuota getMessageCountQuota(String quotaRoot) throws 
MailboxException {
+    public SerializableQuota<QuotaCount> getMessageCountQuota(String 
quotaRoot) throws MailboxException {
         return quotaManagement.getMessageCountQuota(quotaRoot);
     }
 
     @Override
-    public SerializableQuota getStorageQuota(String quotaRoot) throws 
MailboxException {
+    public SerializableQuota<QuotaSize> getStorageQuota(String quotaRoot) 
throws MailboxException {
         return quotaManagement.getStorageQuota(quotaRoot);
     }
 
     @Override
-    public long getMaxMessageCount(String quotaRoot) throws MailboxException {
+    public Optional<QuotaCount> getMaxMessageCount(String quotaRoot) throws 
MailboxException {
         return quotaManagement.getMaxMessageCount(quotaRoot);
     }
 
     @Override
-    public long getMaxStorage(String quotaRoot) throws MailboxException {
+    public Optional<QuotaSize> getMaxStorage(String quotaRoot) throws 
MailboxException {
         return quotaManagement.getMaxStorage(quotaRoot);
     }
 
     @Override
-    public long getDefaultMaxMessageCount() throws MailboxException {
+    public Optional<QuotaCount> getDefaultMaxMessageCount() throws 
MailboxException {
         return quotaManagement.getDefaultMaxMessageCount();
     }
 
     @Override
-    public long getDefaultMaxStorage() throws MailboxException {
+    public Optional<QuotaSize> getDefaultMaxStorage() throws MailboxException {
         return quotaManagement.getDefaultMaxStorage();
     }
 
     @Override
-    public void setMaxMessageCount(String quotaRoot, long maxMessageCount) 
throws MailboxException {
+    public void setMaxMessageCount(String quotaRoot, QuotaCount 
maxMessageCount) throws MailboxException {
         quotaManagement.setMaxMessageCount(quotaRoot, maxMessageCount);
     }
 
     @Override
-    public void setMaxStorage(String quotaRoot, long maxSize) throws 
MailboxException {
+    public void setMaxStorage(String quotaRoot, QuotaSize maxSize) throws 
MailboxException {
         quotaManagement.setMaxStorage(quotaRoot, maxSize);
     }
 
     @Override
-    public void setDefaultMaxMessageCount(long maxDefaultMessageCount) throws 
MailboxException {
+    public void setDefaultMaxMessageCount(QuotaCount maxDefaultMessageCount) 
throws MailboxException {
         quotaManagement.setDefaultMaxMessageCount(maxDefaultMessageCount);
     }
 
     @Override
-    public void setDefaultMaxStorage(long maxDefaultSize) throws 
MailboxException {
+    public void setDefaultMaxStorage(QuotaSize maxDefaultSize) throws 
MailboxException {
         quotaManagement.setDefaultMaxStorage(maxDefaultSize);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/cli/src/main/java/org/apache/james/cli/utils/ValueWithUnit.java
----------------------------------------------------------------------
diff --git 
a/server/container/cli/src/main/java/org/apache/james/cli/utils/ValueWithUnit.java
 
b/server/container/cli/src/main/java/org/apache/james/cli/utils/ValueWithUnit.java
index 0bac5ff..b61d653 100644
--- 
a/server/container/cli/src/main/java/org/apache/james/cli/utils/ValueWithUnit.java
+++ 
b/server/container/cli/src/main/java/org/apache/james/cli/utils/ValueWithUnit.java
@@ -19,8 +19,6 @@
 
 package org.apache.james.cli.utils;
 
-import org.apache.james.mailbox.model.Quota;
-
 import com.google.common.math.LongMath;
 
 /**
@@ -30,6 +28,8 @@ public class ValueWithUnit {
 
     public static final String UNKNOWN = "UNKNOWN";
     public static final String UNLIMITED = "UNLIMITED";
+    public static final long UNKNOWN_VALUE = Long.MIN_VALUE;
+    public static final long UNLIMITED_VALUE = -1;
 
     /**
      * supported units : B ( 2^0 ), K ( 2^10 ), M ( 2^20 ), G ( 2^30 )
@@ -55,10 +55,10 @@ public class ValueWithUnit {
 
     public static ValueWithUnit parse(String providedLongWithUnitString) 
throws Exception {
         if (providedLongWithUnitString.equalsIgnoreCase(UNKNOWN)) {
-            return new ValueWithUnit(Unit.NoUnit, Quota.UNKNOWN);
+            return new ValueWithUnit(Unit.NoUnit, UNKNOWN_VALUE);
         }
         if (providedLongWithUnitString.equalsIgnoreCase(UNLIMITED)) {
-            return new ValueWithUnit(Unit.NoUnit, Quota.UNLIMITED);
+            return new ValueWithUnit(Unit.NoUnit, UNLIMITED_VALUE);
         }
         char lastChar = 
providedLongWithUnitString.charAt(providedLongWithUnitString.length() - 1);
         Unit unit = getUnit(lastChar);

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/cli/src/test/java/org/apache/james/cli/ServerCmdTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/cli/src/test/java/org/apache/james/cli/ServerCmdTest.java 
b/server/container/cli/src/test/java/org/apache/james/cli/ServerCmdTest.java
index 6d340ac..37d15de 100644
--- a/server/container/cli/src/test/java/org/apache/james/cli/ServerCmdTest.java
+++ b/server/container/cli/src/test/java/org/apache/james/cli/ServerCmdTest.java
@@ -27,6 +27,7 @@ import static org.easymock.EasyMock.expectLastCall;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Optional;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.ParseException;
@@ -36,6 +37,8 @@ import 
org.apache.james.cli.exceptions.UnrecognizedCommandException;
 import org.apache.james.cli.type.CmdType;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 import org.apache.james.mailbox.store.probe.MailboxProbe;
 import org.apache.james.mailbox.store.probe.QuotaProbe;
@@ -381,7 +384,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETDEFAULTMAXMESSAGECOUNTQUOTA.getCommand()};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        expect(quotaProbe.getDefaultMaxMessageCount()).andReturn(1024L * 
1024L);
+        
expect(quotaProbe.getDefaultMaxMessageCount()).andReturn(Optional.of(QuotaCount.count(1024L
 * 1024L)));
 
         control.replay();
         testee.executeCommandLine(commandLine);
@@ -393,7 +396,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETDEFAULTMAXSTORAGEQUOTA.getCommand()};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        expect(quotaProbe.getDefaultMaxStorage()).andReturn(1024L * 1024L * 
1024L);
+        
expect(quotaProbe.getDefaultMaxStorage()).andReturn(Optional.of(QuotaSize.size(1024L
 * 1024L * 1024L)));
 
         control.replay();
         testee.executeCommandLine(commandLine);
@@ -405,7 +408,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.SETDEFAULTMAXMESSAGECOUNTQUOTA.getCommand(), "1054"};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        quotaProbe.setDefaultMaxMessageCount(1054);
+        quotaProbe.setDefaultMaxMessageCount(QuotaCount.count(1054));
         expectLastCall();
 
         control.replay();
@@ -418,7 +421,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.SETDEFAULTMAXSTORAGEQUOTA.getCommand(), "1G"};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        quotaProbe.setDefaultMaxStorage(1024 * 1024 * 1024);
+        quotaProbe.setDefaultMaxStorage(QuotaSize.size(1024 * 1024 * 1024));
         expectLastCall();
 
         control.replay();
@@ -432,7 +435,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.SETMAXMESSAGECOUNTQUOTA.getCommand(), quotaroot, "1000"};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        quotaProbe.setMaxMessageCount(quotaroot, 1000);
+        quotaProbe.setMaxMessageCount(quotaroot, QuotaCount.count(1000));
         expectLastCall();
 
         control.replay();
@@ -446,7 +449,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.SETMAXSTORAGEQUOTA.getCommand(), quotaroot, "5M"};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        quotaProbe.setMaxStorage(quotaroot, 5 * 1024 * 1024);
+        quotaProbe.setMaxStorage(quotaroot, QuotaSize.size(5 * 1024 * 1024));
         expectLastCall();
 
         control.replay();
@@ -460,7 +463,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETMAXMESSAGECOUNTQUOTA.getCommand(), quotaroot};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        
expect(quotaProbe.getMaxMessageCount(quotaroot)).andReturn(Quota.UNLIMITED);
+        
expect(quotaProbe.getMaxMessageCount(quotaroot)).andReturn(Optional.of(QuotaCount.unlimited()));
 
         control.replay();
         testee.executeCommandLine(commandLine);
@@ -473,7 +476,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETMAXSTORAGEQUOTA.getCommand(), quotaroot};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        expect(quotaProbe.getMaxStorage(quotaroot)).andReturn(Quota.UNLIMITED);
+        
expect(quotaProbe.getMaxStorage(quotaroot)).andReturn(Optional.of(QuotaSize.unlimited()));
 
         control.replay();
         testee.executeCommandLine(commandLine);
@@ -486,7 +489,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETSTORAGEQUOTA.getCommand(), quotaroot};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        expect(quotaProbe.getStorageQuota(quotaroot)).andReturn(new 
SerializableQuota(Quota.UNLIMITED, Quota.UNKNOWN));
+        expect(quotaProbe.getStorageQuota(quotaroot)).andReturn(new 
SerializableQuota<>(Quota.unknownUsedQuota(QuotaSize.unlimited())));
 
         control.replay();
         testee.executeCommandLine(commandLine);
@@ -499,7 +502,7 @@ public class ServerCmdTest {
         String[] arguments = { "-h", "127.0.0.1", "-p", "9999", 
CmdType.GETMESSAGECOUNTQUOTA.getCommand(), quotaroot};
         CommandLine commandLine = ServerCmd.parseCommandLine(arguments);
 
-        expect(quotaProbe.getMessageCountQuota(quotaroot)).andReturn(new 
SerializableQuota(Quota.UNLIMITED, Quota.UNKNOWN));
+        expect(quotaProbe.getMessageCountQuota(quotaroot)).andReturn(new 
SerializableQuota<>(Quota.unknownUsedQuota(QuotaCount.unlimited())));
 
         control.replay();
         testee.executeCommandLine(commandLine);

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/cli/src/test/java/org/apache/james/cli/utils/ValueWithUnitTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/cli/src/test/java/org/apache/james/cli/utils/ValueWithUnitTest.java
 
b/server/container/cli/src/test/java/org/apache/james/cli/utils/ValueWithUnitTest.java
index 355101f..fe897dc 100644
--- 
a/server/container/cli/src/test/java/org/apache/james/cli/utils/ValueWithUnitTest.java
+++ 
b/server/container/cli/src/test/java/org/apache/james/cli/utils/ValueWithUnitTest.java
@@ -21,7 +21,6 @@ package org.apache.james.cli.utils;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.apache.james.mailbox.model.Quota;
 import org.junit.Test;
 
 public class ValueWithUnitTest {
@@ -53,12 +52,12 @@ public class ValueWithUnitTest {
 
     @Test
     public void testUnknown() throws Exception {
-        
assertThat(ValueWithUnit.parse("unknown").getConvertedValue()).isEqualTo(Quota.UNKNOWN);
+        
assertThat(ValueWithUnit.parse("unknown").getConvertedValue()).isEqualTo(ValueWithUnit.UNKNOWN_VALUE);
     }
 
     @Test
     public void testUnlimited() throws Exception {
-        
assertThat(ValueWithUnit.parse("unlimited").getConvertedValue()).isEqualTo(Quota.UNLIMITED);
+        
assertThat(ValueWithUnit.parse("unlimited").getConvertedValue()).isEqualTo(ValueWithUnit.UNLIMITED_VALUE);
     }
 
     @Test(expected = Exception.class)

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/guice/mailbox/src/main/java/org/apache/james/modules/QuotaProbesImpl.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/QuotaProbesImpl.java
 
b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/QuotaProbesImpl.java
index 2277f1a..8e42a7c 100644
--- 
a/server/container/guice/mailbox/src/main/java/org/apache/james/modules/QuotaProbesImpl.java
+++ 
b/server/container/guice/mailbox/src/main/java/org/apache/james/modules/QuotaProbesImpl.java
@@ -19,13 +19,17 @@
 
 package org.apache.james.modules;
 
+import java.util.Optional;
+
 import javax.inject.Inject;
 
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaCount;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 import org.apache.james.mailbox.store.probe.QuotaProbe;
 import org.apache.james.utils.GuiceProbe;
@@ -49,54 +53,54 @@ public class QuotaProbesImpl implements QuotaProbe, 
GuiceProbe {
     }
 
     @Override
-    public SerializableQuota getMessageCountQuota(String quotaRoot) throws 
MailboxException {
-        return new 
SerializableQuota(quotaManager.getMessageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
+    public SerializableQuota<QuotaCount> getMessageCountQuota(String 
quotaRoot) throws MailboxException {
+        return new 
SerializableQuota<>(quotaManager.getMessageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
     }
 
     @Override
-    public SerializableQuota getStorageQuota(String quotaRoot) throws 
MailboxException {
-        return new 
SerializableQuota(quotaManager.getStorageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
+    public SerializableQuota<QuotaSize> getStorageQuota(String quotaRoot) 
throws MailboxException {
+        return new 
SerializableQuota<>(quotaManager.getStorageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
     }
 
     @Override
-    public long getMaxMessageCount(String quotaRoot) throws MailboxException {
+    public Optional<QuotaCount> getMaxMessageCount(String quotaRoot) throws 
MailboxException {
         return 
maxQuotaManager.getMaxMessage(quotaRootResolver.createQuotaRoot(quotaRoot));
     }
 
     @Override
-    public long getMaxStorage(String quotaRoot) throws MailboxException {
+    public Optional<QuotaSize> getMaxStorage(String quotaRoot) throws 
MailboxException {
         return 
maxQuotaManager.getMaxStorage(quotaRootResolver.createQuotaRoot(quotaRoot));
     }
 
     @Override
-    public long getDefaultMaxMessageCount() throws MailboxException {
+    public Optional<QuotaCount> getDefaultMaxMessageCount() throws 
MailboxException {
         return maxQuotaManager.getDefaultMaxMessage();
     }
 
     @Override
-    public long getDefaultMaxStorage() throws MailboxException {
+    public Optional<QuotaSize> getDefaultMaxStorage() throws MailboxException {
         return maxQuotaManager.getDefaultMaxStorage();
     }
 
     @Override
-    public void setMaxMessageCount(String quotaRoot, long maxMessageCount) 
throws MailboxException {
+    public void setMaxMessageCount(String quotaRoot, QuotaCount 
maxMessageCount) throws MailboxException {
         
maxQuotaManager.setMaxMessage(quotaRootResolver.createQuotaRoot(quotaRoot),
             maxMessageCount);
     }
 
     @Override
-    public void setMaxStorage(String quotaRoot, long maxSize) throws 
MailboxException {
+    public void setMaxStorage(String quotaRoot, QuotaSize maxSize) throws 
MailboxException {
         
maxQuotaManager.setMaxStorage(quotaRootResolver.createQuotaRoot(quotaRoot),
             maxSize);
     }
 
     @Override
-    public void setDefaultMaxMessageCount(long maxDefaultMessageCount) throws 
MailboxException {
+    public void setDefaultMaxMessageCount(QuotaCount maxDefaultMessageCount) 
throws MailboxException {
         maxQuotaManager.setDefaultMaxMessage(maxDefaultMessageCount);
     }
 
     @Override
-    public void setDefaultMaxStorage(long maxDefaultSize) throws 
MailboxException {
+    public void setDefaultMaxStorage(QuotaSize maxDefaultSize) throws 
MailboxException {
         maxQuotaManager.setDefaultMaxStorage(maxDefaultSize);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
 
b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
index 7faba1f..d6431dc 100644
--- 
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
+++ 
b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MailboxRoutesModule.java
@@ -20,8 +20,10 @@
 package org.apache.james.modules.server;
 
 import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.jackson.QuotaModule;
 import org.apache.james.webadmin.routes.GlobalQuotaRoutes;
 import org.apache.james.webadmin.routes.UserMailboxesRoutes;
+import org.apache.james.webadmin.utils.JsonTransformerModule;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
@@ -33,5 +35,7 @@ public class MailboxRoutesModule extends AbstractModule {
         Multibinder<Routes> routesMultibinder = 
Multibinder.newSetBinder(binder(), Routes.class);
         routesMultibinder.addBinding().to(UserMailboxesRoutes.class);
         routesMultibinder.addBinding().to(GlobalQuotaRoutes.class);
+        Multibinder<JsonTransformerModule> jsonTransformerModuleMultibinder = 
Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
+        jsonTransformerModuleMultibinder.addBinding().to(QuotaModule.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
 
b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 6142be1..94b763e 100644
--- 
a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ 
b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -42,6 +42,7 @@ import 
org.apache.james.webadmin.authentication.AuthenticationFilter;
 import org.apache.james.webadmin.authentication.JwtFilter;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 import org.apache.james.webadmin.utils.JsonTransformer;
+import org.apache.james.webadmin.utils.JsonTransformerModule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -76,6 +77,7 @@ public class WebAdminServerModule extends AbstractModule {
 
         Multibinder.newSetBinder(binder(), 
ConfigurationPerformer.class).addBinding().to(WebAdminServerModuleConfigurationPerformer.class);
         Multibinder.newSetBinder(binder(), 
GuiceProbe.class).addBinding().to(WebAdminGuiceProbe.class);
+        Multibinder.newSetBinder(binder(), JsonTransformerModule.class);
     }
 
     @Provides

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagement.java
----------------------------------------------------------------------
diff --git 
a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagement.java
 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagement.java
index 7a05c3d..cf35f78 100644
--- 
a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagement.java
+++ 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagement.java
@@ -21,14 +21,17 @@ package org.apache.james.adapter.mailbox;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.Optional;
 
 import javax.inject.Inject;
 
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaCount;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 import org.apache.james.util.MDCBuilder;
 
@@ -61,7 +64,7 @@ public class QuotaManagement implements QuotaManagementMBean {
     }
 
     @Override
-    public long getMaxMessageCount(String quotaRoot) throws MailboxException {
+    public Optional<QuotaCount> getMaxMessageCount(String quotaRoot) throws 
MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -74,7 +77,7 @@ public class QuotaManagement implements QuotaManagementMBean {
     }
 
     @Override
-    public long getMaxStorage(String quotaRoot) throws MailboxException {
+    public Optional<QuotaSize> getMaxStorage(String quotaRoot) throws 
MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -87,7 +90,7 @@ public class QuotaManagement implements QuotaManagementMBean {
     }
 
     @Override
-    public long getDefaultMaxMessageCount() throws MailboxException {
+    public Optional<QuotaCount> getDefaultMaxMessageCount() throws 
MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -100,7 +103,7 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public long getDefaultMaxStorage() throws MailboxException {
+    public Optional<QuotaSize> getDefaultMaxStorage() throws MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -113,7 +116,7 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public void setMaxMessageCount(String quotaRoot, long maxMessageCount) 
throws MailboxException {
+    public void setMaxMessageCount(String quotaRoot, QuotaCount 
maxMessageCount) throws MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -126,7 +129,7 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public void setMaxStorage(String quotaRoot, long maxSize) throws 
MailboxException {
+    public void setMaxStorage(String quotaRoot, QuotaSize maxSize) throws 
MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -139,7 +142,7 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public void setDefaultMaxMessageCount(long maxDefaultMessageCount) throws 
MailboxException {
+    public void setDefaultMaxMessageCount(QuotaCount maxDefaultMessageCount) 
throws MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -152,7 +155,7 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public void setDefaultMaxStorage(long maxDefaultSize) throws 
MailboxException {
+    public void setDefaultMaxStorage(QuotaSize maxDefaultSize) throws 
MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
@@ -165,26 +168,26 @@ public class QuotaManagement implements 
QuotaManagementMBean {
     }
 
     @Override
-    public SerializableQuota getMessageCountQuota(String quotaRoot) throws 
MailboxException {
+    public SerializableQuota<QuotaCount> getMessageCountQuota(String 
quotaRoot) throws MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
                      .addContext(MDCBuilder.ACTION, "getMessageCountQuota")
                      .build()) {
-            return new 
SerializableQuota(quotaManager.getMessageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
+            return new 
SerializableQuota<>(quotaManager.getMessageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
         } catch (IOException e) {
             throw Throwables.propagate(e);
         }
     }
 
     @Override
-    public SerializableQuota getStorageQuota(String quotaRoot) throws 
MailboxException {
+    public SerializableQuota<QuotaSize> getStorageQuota(String quotaRoot) 
throws MailboxException {
         try (Closeable closeable =
                  MDCBuilder.create()
                      .addContext(MDCBuilder.PROTOCOL, "CLI")
                      .addContext(MDCBuilder.ACTION, "getStorageQuota")
                      .build()) {
-            return new 
SerializableQuota(quotaManager.getStorageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
+            return new 
SerializableQuota<>(quotaManager.getStorageQuota(quotaRootResolver.createQuotaRoot(quotaRoot)));
         } catch (IOException e) {
             throw Throwables.propagate(e);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagementMBean.java
----------------------------------------------------------------------
diff --git 
a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagementMBean.java
 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagementMBean.java
index 95cea22..866b587 100644
--- 
a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagementMBean.java
+++ 
b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/QuotaManagementMBean.java
@@ -19,29 +19,33 @@
 
 package org.apache.james.adapter.mailbox;
 
+import java.util.Optional;
+
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.mail.model.SerializableQuota;
 
 public interface QuotaManagementMBean {
     String getQuotaRoot(String namespace, String user, String name) throws 
MailboxException;
 
-    SerializableQuota getMessageCountQuota(String quotaRoot) throws 
MailboxException;
+    SerializableQuota<QuotaCount> getMessageCountQuota(String quotaRoot) 
throws MailboxException;
 
-    SerializableQuota getStorageQuota(String quotaRoot) throws 
MailboxException;
+    SerializableQuota<QuotaSize> getStorageQuota(String quotaRoot) throws 
MailboxException;
 
-    long getMaxMessageCount(String quotaRoot) throws MailboxException;
+    Optional<QuotaCount> getMaxMessageCount(String quotaRoot) throws 
MailboxException;
 
-    long getMaxStorage(String quotaRoot) throws MailboxException;
+    Optional<QuotaSize> getMaxStorage(String quotaRoot) throws 
MailboxException;
 
-    long getDefaultMaxMessageCount() throws MailboxException;
+    Optional<QuotaCount> getDefaultMaxMessageCount() throws MailboxException;
 
-    long getDefaultMaxStorage() throws MailboxException;
+    Optional<QuotaSize> getDefaultMaxStorage() throws MailboxException;
 
-    void setMaxMessageCount(String quotaRoot, long maxMessageCount) throws 
MailboxException;
+    void setMaxMessageCount(String quotaRoot, QuotaCount maxMessageCount) 
throws MailboxException;
 
-    void setMaxStorage(String quotaRoot, long maxSize) throws MailboxException;
+    void setMaxStorage(String quotaRoot, QuotaSize maxSize) throws 
MailboxException;
 
-    void setDefaultMaxMessageCount(long maxDefaultMessageCount) throws 
MailboxException;
+    void setDefaultMaxMessageCount(QuotaCount maxDefaultMessageCount) throws 
MailboxException;
 
-    void setDefaultMaxStorage(long maxDefaultSize) throws MailboxException;
+    void setDefaultMaxStorage(QuotaSize maxDefaultSize) throws 
MailboxException;
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/container/spring/src/main/java/org/apache/james/container/spring/mailbox/MaxQuotaConfigurationReader.java
----------------------------------------------------------------------
diff --git 
a/server/container/spring/src/main/java/org/apache/james/container/spring/mailbox/MaxQuotaConfigurationReader.java
 
b/server/container/spring/src/main/java/org/apache/james/container/spring/mailbox/MaxQuotaConfigurationReader.java
index 0b50d10..b5ab1d6 100644
--- 
a/server/container/spring/src/main/java/org/apache/james/container/spring/mailbox/MaxQuotaConfigurationReader.java
+++ 
b/server/container/spring/src/main/java/org/apache/james/container/spring/mailbox/MaxQuotaConfigurationReader.java
@@ -28,7 +28,9 @@ import 
org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.mailbox.quota.QuotaCount;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
+import org.apache.james.mailbox.quota.QuotaSize;
 
 public class MaxQuotaConfigurationReader implements Configurable {
 
@@ -65,19 +67,19 @@ public class MaxQuotaConfigurationReader implements 
Configurable {
 
     private void configureDefaultValues(Long defaultMaxMessage, Long 
defaultMaxStorage) throws MailboxException {
         if (defaultMaxMessage != null) {
-            maxQuotaManager.setDefaultMaxMessage(defaultMaxMessage);
+            
maxQuotaManager.setDefaultMaxMessage(QuotaCount.count(defaultMaxMessage));
         }
         if (defaultMaxStorage != null) {
-            maxQuotaManager.setDefaultMaxStorage(defaultMaxStorage);
+            
maxQuotaManager.setDefaultMaxStorage(QuotaSize.size(defaultMaxStorage));
         }
     }
 
     private void configureQuotaRootSpecificValues(Map<String, Long> 
maxMessage, Map<String, Long> maxStorage) throws MailboxException {
         for (Map.Entry<String, Long> entry : maxMessage.entrySet()) {
-            
maxQuotaManager.setMaxMessage(quotaRootResolver.createQuotaRoot(entry.getKey()),
 entry.getValue());
+            
maxQuotaManager.setMaxMessage(quotaRootResolver.createQuotaRoot(entry.getKey()),
 QuotaCount.count(entry.getValue()));
         }
         for (Map.Entry<String, Long> entry : maxStorage.entrySet()) {
-            
maxQuotaManager.setMaxStorage(quotaRootResolver.createQuotaRoot(entry.getKey()),
 entry.getValue());
+            
maxQuotaManager.setMaxStorage(quotaRootResolver.createQuotaRoot(entry.getKey()),
 QuotaSize.size(entry.getValue()));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/mailet/mailets/src/test/java/org/apache/james/transport/matchers/IsOverQuotaTest.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/test/java/org/apache/james/transport/matchers/IsOverQuotaTest.java
 
b/server/mailet/mailets/src/test/java/org/apache/james/transport/matchers/IsOverQuotaTest.java
index ac56bbc..bc64c64 100644
--- 
a/server/mailet/mailets/src/test/java/org/apache/james/transport/matchers/IsOverQuotaTest.java
+++ 
b/server/mailet/mailets/src/test/java/org/apache/james/transport/matchers/IsOverQuotaTest.java
@@ -32,6 +32,8 @@ import 
org.apache.james.mailbox.inmemory.quota.InMemoryCurrentQuotaManager;
 import org.apache.james.mailbox.inmemory.quota.InMemoryPerUserMaxQuotaManager;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.QuotaRoot;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.mailbox.store.StoreMailboxManager;
 import org.apache.james.mailbox.store.quota.CurrentQuotaCalculator;
 import org.apache.james.mailbox.store.quota.DefaultQuotaRootResolver;
@@ -84,7 +86,7 @@ public class IsOverQuotaTest {
 
     @Test
     public void matchShouldKeepAddressesWithTooBigSize() throws Exception {
-        maxQuotaManager.setDefaultMaxStorage(100);
+        maxQuotaManager.setDefaultMaxStorage(QuotaSize.size(100));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)
@@ -97,7 +99,7 @@ public class IsOverQuotaTest {
 
     @Test
     public void matchShouldReturnEmptyAtSizeQuotaLimit() throws Exception {
-        maxQuotaManager.setDefaultMaxStorage(1000);
+        maxQuotaManager.setDefaultMaxStorage(QuotaSize.size(1000));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)
@@ -110,7 +112,7 @@ public class IsOverQuotaTest {
 
     @Test
     public void matchShouldKeepAddressesWithTooMuchMessages() throws Exception 
{
-        maxQuotaManager.setDefaultMaxMessage(0);
+        maxQuotaManager.setDefaultMaxMessage(QuotaCount.count(0));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)
@@ -122,7 +124,7 @@ public class IsOverQuotaTest {
 
     @Test
     public void matchShouldReturnEmptyOnMessageLimit() throws Exception {
-        maxQuotaManager.setDefaultMaxMessage(1);
+        maxQuotaManager.setDefaultMaxMessage(QuotaCount.count(1));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)
@@ -136,7 +138,7 @@ public class IsOverQuotaTest {
     public void matchShouldNotIncludeRecipientNotOverQuota() throws Exception {
         String username = MailAddressFixture.ANY_AT_JAMES.getLocalPart();
         QuotaRoot quotaRoot = 
quotaRootResolver.getQuotaRoot(MailboxPath.inbox(mailboxManager.createSystemSession(username)));
-        maxQuotaManager.setMaxStorage(quotaRoot, 100);
+        maxQuotaManager.setMaxStorage(quotaRoot, QuotaSize.size(100));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)
@@ -154,7 +156,7 @@ public class IsOverQuotaTest {
         
when(usersRepository.getUser(MailAddressFixture.OTHER_AT_JAMES)).thenReturn(MailAddressFixture.OTHER_AT_JAMES.asString());
         String username = MailAddressFixture.ANY_AT_JAMES.asString();
         QuotaRoot quotaRoot = 
quotaRootResolver.getQuotaRoot(MailboxPath.inbox(mailboxManager.createSystemSession(username)));
-        maxQuotaManager.setMaxStorage(quotaRoot, 100);
+        maxQuotaManager.setMaxStorage(quotaRoot, QuotaSize.size(100));
 
         FakeMail fakeMail = FakeMail.builder()
             .recipient(MailAddressFixture.ANY_AT_JAMES)

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java
 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java
index c3ecf81..3f62d89 100644
--- 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java
+++ 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java
@@ -20,18 +20,26 @@
 package org.apache.james.webadmin.utils;
 
 import java.io.IOException;
+import java.util.List;
 
+import com.fasterxml.jackson.databind.Module;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.google.common.collect.ImmutableList;
 
 public class JsonExtractor<RequestT> {
 
     private final ObjectMapper objectMapper;
     private final Class<RequestT> type;
 
-    public JsonExtractor(Class<RequestT> type) {
+    public JsonExtractor(Class<RequestT> type, Module... modules) {
+        this(type, ImmutableList.copyOf(modules));
+    }
+
+    public JsonExtractor(Class<RequestT> type, List<Module> modules) {
         this.objectMapper = new ObjectMapper()
-            .registerModule(new Jdk8Module());
+            .registerModule(new Jdk8Module())
+            .registerModules(modules);
         this.type = type;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformer.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformer.java
 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformer.java
index ad7fe30..907cc3f 100644
--- 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformer.java
+++ 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformer.java
@@ -19,24 +19,44 @@
 
 package org.apache.james.webadmin.utils;
 
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.Module;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-
+import com.google.common.collect.ImmutableSet;
 import spark.ResponseTransformer;
 
 public class JsonTransformer implements ResponseTransformer {
 
     private final ObjectMapper objectMapper;
 
-    public JsonTransformer() {
+    public JsonTransformer(JsonTransformerModule... modules) {
+        this(ImmutableSet.copyOf(modules));
+    }
+
+    @Inject
+    public JsonTransformer(Set<JsonTransformerModule> jsonTransformerModules) {
+        this(jsonTransformerModules
+            .stream()
+            .map(JsonTransformerModule::asJacksonModule)
+            .collect(Collectors.toList()));
+    }
+
+    private JsonTransformer(Collection<Module> modules) {
         objectMapper = new ObjectMapper()
             .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
             .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
             .registerModule(new Jdk8Module())
-            .registerModule(new JavaTimeModule());
+            .registerModule(new JavaTimeModule())
+            .registerModules(modules);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformerModule.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformerModule.java
 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformerModule.java
new file mode 100644
index 0000000..b8fd279
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonTransformerModule.java
@@ -0,0 +1,28 @@
+/****************************************************************
+ * 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.utils;
+
+import com.fasterxml.jackson.databind.Module;
+
+public interface JsonTransformerModule {
+
+    Module asJacksonModule();
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
index 829cc14..b48f1f9 100644
--- 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
+++ 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
@@ -20,29 +20,39 @@
 
 package org.apache.james.webadmin.dto;
 
-import org.apache.james.mailbox.model.Quota;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.google.common.base.Preconditions;
+import com.google.common.base.MoreObjects;
 
 @JsonDeserialize(builder = QuotaDTO.Builder.class)
 public class QuotaDTO {
+
     public static Builder builder() {
         return new Builder();
     }
 
     @JsonPOJOBuilder(withPrefix = "")
     public static class Builder {
-        private long count;
-        private long size;
+        private Optional<QuotaCount> count;
+        private Optional<QuotaSize> size;
+
+        private Builder() {
+            count = Optional.empty();
+            size = Optional.empty();
+        }
 
-        public Builder count(long count) {
+        public Builder count(Optional<QuotaCount> count) {
             this.count = count;
             return this;
         }
 
-        public Builder size(long size) {
+        public Builder size(Optional<QuotaSize> size) {
             this.size = size;
             return this;
         }
@@ -50,24 +60,47 @@ public class QuotaDTO {
         public QuotaDTO build() {
             return new QuotaDTO(count, size);
         }
-
     }
 
-    private final long count;
-    private final long size;
+    private final Optional<QuotaCount> count;
+    private final Optional<QuotaSize> size;
 
-    private QuotaDTO(long count, long size) {
-        Preconditions.checkArgument(count >= Quota.UNLIMITED);
-        Preconditions.checkArgument(size >= Quota.UNLIMITED);
+    private QuotaDTO(Optional<QuotaCount> count, Optional<QuotaSize> size) {
         this.count = count;
         this.size = size;
     }
 
-    public long getCount() {
+    public Optional<QuotaCount> getCount() {
         return count;
     }
 
-    public long getSize() {
+    public Optional<QuotaSize> getSize() {
         return size;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof QuotaDTO) {
+            QuotaDTO that = (QuotaDTO) o;
+
+            return Objects.equals(this.count, that.count) &&
+                Objects.equals(this.size, that.size);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(count, size);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("count", count)
+            .add("size", size)
+            .toString();
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueDeserializer.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueDeserializer.java
 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueDeserializer.java
new file mode 100644
index 0000000..52cef2e
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueDeserializer.java
@@ -0,0 +1,52 @@
+/****************************************************************
+ * 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 java.io.IOException;
+import java.util.function.Function;
+
+import org.apache.james.mailbox.quota.QuotaValue;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+public class QuotaValueDeserializer<T extends QuotaValue<T>> extends 
JsonDeserializer<T> {
+
+    private final T unlimited;
+    private final Function<Long, T> quotaFactory;
+
+    public QuotaValueDeserializer(T unlimited, Function<Long, T> quotaFactory) 
{
+        this.unlimited = unlimited;
+        this.quotaFactory = quotaFactory;
+    }
+
+    @Override
+    public T deserialize(JsonParser parser, DeserializationContext ctxt) 
throws IOException {
+        return deserialize(parser.getValueAsLong());
+    }
+
+    private T deserialize(Long value) {
+        if (value == -1) {
+            return unlimited;
+        }
+        return quotaFactory.apply(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueSerializer.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueSerializer.java
 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueSerializer.java
new file mode 100644
index 0000000..f683558
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaValueSerializer.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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 java.io.IOException;
+
+import org.apache.james.mailbox.quota.QuotaValue;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+public class QuotaValueSerializer<T extends QuotaValue<T>> extends 
JsonSerializer<T> {
+
+    @Override
+    public void serialize(T value, JsonGenerator generator, SerializerProvider 
serializers) throws IOException {
+        generator.writeNumber(serialize(value));
+    }
+
+    private long serialize(T value) {
+        if (value.isUnlimited()) {
+            return -1;
+        }
+        return value.asLong();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/jackson/QuotaModule.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/jackson/QuotaModule.java
 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/jackson/QuotaModule.java
new file mode 100644
index 0000000..2188fd5
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/jackson/QuotaModule.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * 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.jackson;
+
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
+import org.apache.james.webadmin.dto.QuotaValueDeserializer;
+import org.apache.james.webadmin.dto.QuotaValueSerializer;
+import org.apache.james.webadmin.utils.JsonTransformerModule;
+
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+public class QuotaModule implements JsonTransformerModule {
+
+    private final SimpleModule simpleModule;
+
+    public QuotaModule() {
+        simpleModule = new SimpleModule()
+            .addSerializer(QuotaSize.class, new QuotaValueSerializer<>())
+            .addSerializer(QuotaCount.class, new QuotaValueSerializer<>())
+            .addDeserializer(QuotaSize.class, new 
QuotaValueDeserializer<>(QuotaSize.unlimited(), QuotaSize::size))
+            .addDeserializer(QuotaCount.class, new 
QuotaValueDeserializer<>(QuotaCount.unlimited(), QuotaCount::count));
+    }
+
+    @Override
+    public Module asJacksonModule() {
+        return simpleModule;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 d036606..1054ad4 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
@@ -19,6 +19,8 @@
 
 package org.apache.james.webadmin.routes;
 
+import java.util.Optional;
+
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -26,17 +28,19 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.QuotaDTO;
+import org.apache.james.webadmin.jackson.QuotaModule;
 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.apache.james.webadmin.validation.Quotas;
 import org.eclipse.jetty.http.HttpStatus;
 
 import io.swagger.annotations.Api;
@@ -45,6 +49,8 @@ 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.Response;
 import spark.Service;
 
 @Api(tags = "GlobalQuota")
@@ -65,7 +71,7 @@ public class GlobalQuotaRoutes implements Routes {
     public GlobalQuotaRoutes(GlobalQuotaService globalQuotaService, 
JsonTransformer jsonTransformer) {
         this.globalQuotaService = globalQuotaService;
         this.jsonTransformer = jsonTransformer;
-        this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class);
+        this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class, new 
QuotaModule().asJacksonModule());
     }
 
     @Override
@@ -165,7 +171,7 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaSize() {
         service.put(SIZE_ENDPOINT, (request, response) -> {
-            QuotaSize quotaSize = QuotaValue.quotaSize(request.body());
+            QuotaSize quotaSize = Quotas.quotaSize(request.body());
             globalQuotaService.defineMaxSizeQuota(quotaSize);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
@@ -180,7 +186,16 @@ 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) -> 
globalQuotaService.getMaxSizeQuota(), jsonTransformer);
+        service.get(SIZE_ENDPOINT, this::getQuotaSize, jsonTransformer);
+    }
+
+    private QuotaSize getQuotaSize(Request request, Response response) throws 
MailboxException {
+        Optional<QuotaSize> maxSizeQuota = 
globalQuotaService.getMaxSizeQuota();
+        if (maxSizeQuota.isPresent()) {
+            return maxSizeQuota.get();
+        }
+        response.status(HttpStatus.NO_CONTENT_204);
+        return null;
     }
 
     @DELETE
@@ -211,7 +226,7 @@ public class GlobalQuotaRoutes implements Routes {
     })
     public void defineUpdateQuotaCount() {
         service.put(COUNT_ENDPOINT, (request, response) -> {
-            QuotaCount quotaRequest = QuotaValue.quotaCount(request.body());
+            QuotaCount quotaRequest = Quotas.quotaCount(request.body());
             globalQuotaService.defineMaxCountQuota(quotaRequest);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
@@ -223,10 +238,19 @@ public class GlobalQuotaRoutes implements Routes {
     @ApiOperation(value = "Reading per quotaroot mail count limitation")
     @ApiResponses(value = {
             @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = 
Long.class),
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "Quota is 
not defined"),
             @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) -> 
globalQuotaService.getMaxCountQuota(), jsonTransformer);
+        service.get(COUNT_ENDPOINT, this::getQuotaCount, jsonTransformer);
     }
 
+    private QuotaCount getQuotaCount(Request request, Response response) 
throws MailboxException {
+        Optional<QuotaCount> maxCountQuota = 
globalQuotaService.getMaxCountQuota();
+        if (maxCountQuota.isPresent()) {
+            return maxCountQuota.get();
+        }
+        response.status(HttpStatus.NO_CONTENT_204);
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 1a4deaf..2196fc4 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
@@ -19,6 +19,10 @@
 
 package org.apache.james.webadmin.routes;
 
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import javax.inject.Inject;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -26,6 +30,8 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
+import org.apache.james.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.webadmin.Routes;
@@ -36,9 +42,8 @@ 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.apache.james.webadmin.utils.JsonTransformerModule;
+import org.apache.james.webadmin.validation.Quotas;
 import org.eclipse.jetty.http.HttpStatus;
 
 import io.swagger.annotations.Api;
@@ -67,11 +72,11 @@ public class UserQuotaRoutes implements Routes {
     private Service service;
 
     @Inject
-    public UserQuotaRoutes(UsersRepository usersRepository, UserQuotaService 
userQuotaService, JsonTransformer jsonTransformer) {
+    public UserQuotaRoutes(UsersRepository usersRepository, UserQuotaService 
userQuotaService, JsonTransformer jsonTransformer, Set<JsonTransformerModule> 
modules) {
         this.usersRepository = usersRepository;
         this.userQuotaService = userQuotaService;
         this.jsonTransformer = jsonTransformer;
-        this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class);
+        this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class, 
modules.stream().map(JsonTransformerModule::asJacksonModule).collect(Collectors.toList()));
     }
 
     @Override
@@ -158,7 +163,7 @@ public class UserQuotaRoutes implements Routes {
     public void defineUpdateQuotaSize() {
         service.put(SIZE_ENDPOINT, (request, response) -> {
             String user = checkUserExist(request);
-            QuotaSize quotaSize = QuotaValue.quotaSize(request.body());
+            QuotaSize quotaSize = Quotas.quotaSize(request.body());
             userQuotaService.defineMaxSizeQuota(user, quotaSize);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
@@ -170,12 +175,18 @@ public class UserQuotaRoutes implements Routes {
     @ApiOperation(value = "Reading per user mail size limitation")
     @ApiResponses(value = {
             @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = 
Long.class),
+            @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "No value 
defined"),
             @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);
+            Optional<QuotaSize> maxSizeQuota = 
userQuotaService.getMaxSizeQuota(user);
+            if (maxSizeQuota.isPresent()) {
+                return maxSizeQuota;
+            }
+            response.status(HttpStatus.NO_CONTENT_204);
+            return null;
         }, jsonTransformer);
     }
 
@@ -210,7 +221,7 @@ public class UserQuotaRoutes implements Routes {
     public void defineUpdateQuotaCount() {
         service.put(COUNT_ENDPOINT, (request, response) -> {
             String user = checkUserExist(request);
-            QuotaCount quotaCount = QuotaValue.quotaCount(request.body());
+            QuotaCount quotaCount = Quotas.quotaCount(request.body());
             userQuotaService.defineMaxCountQuota(user, quotaCount);
             response.status(HttpStatus.NO_CONTENT_204);
             return response;
@@ -227,7 +238,12 @@ public class UserQuotaRoutes implements Routes {
     public void defineGetQuotaCount() {
         service.get(COUNT_ENDPOINT, (request, response) -> {
             String user = checkUserExist(request);
-            return userQuotaService.getMaxCountQuota(user);
+            Optional<QuotaCount> maxCountQuota = 
userQuotaService.getMaxCountQuota(user);
+            if (maxCountQuota.isPresent()) {
+                return maxCountQuota;
+            }
+            response.status(HttpStatus.NO_CONTENT_204);
+            return null;
         }, jsonTransformer);
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 a5902ce..06b986d 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
@@ -18,14 +18,15 @@
  ****************************************************************/
 package org.apache.james.webadmin.service;
 
+import java.util.Optional;
+
 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.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
-import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
 
 public class GlobalQuotaService {
 
@@ -37,8 +38,19 @@ public class GlobalQuotaService {
     }
 
     public void defineQuota(QuotaDTO quota) throws MailboxException {
-        maxQuotaManager.setDefaultMaxMessage(quota.getCount());
-        maxQuotaManager.setDefaultMaxStorage(quota.getSize());
+        Optional<QuotaCount> count = quota.getCount();
+        if (count.isPresent()) {
+            maxQuotaManager.setDefaultMaxMessage(count.get());
+        } else {
+            maxQuotaManager.removeDefaultMaxMessage();
+        }
+
+        Optional<QuotaSize> size = quota.getSize();
+        if (size.isPresent()) {
+            maxQuotaManager.setDefaultMaxStorage(size.get());
+        } else {
+            maxQuotaManager.removeDefaultMaxStorage();
+        }
     }
 
     public QuotaDTO getQuota() throws MailboxException {
@@ -49,27 +61,27 @@ public class GlobalQuotaService {
             .build();
     }
 
-    public Long getMaxSizeQuota() throws MailboxException {
+    public Optional<QuotaSize> getMaxSizeQuota() throws MailboxException {
         return maxQuotaManager.getDefaultMaxStorage();
     }
 
     public void defineMaxSizeQuota(QuotaSize quotaRequest) throws 
MailboxException {
-        maxQuotaManager.setDefaultMaxStorage(quotaRequest.asLong());
+        maxQuotaManager.setDefaultMaxStorage(quotaRequest);
     }
 
     public void deleteMaxSizeQuota() throws MailboxException {
-        maxQuotaManager.setDefaultMaxStorage(Quota.UNLIMITED);
+        maxQuotaManager.removeDefaultMaxStorage();
     }
 
-    public Long getMaxCountQuota() throws MailboxException {
+    public Optional<QuotaCount> getMaxCountQuota() throws MailboxException {
         return maxQuotaManager.getDefaultMaxMessage();
     }
 
     public void defineMaxCountQuota(QuotaCount value) throws MailboxException {
-        maxQuotaManager.setDefaultMaxMessage(value.asLong());
+        maxQuotaManager.setDefaultMaxMessage(value);
     }
 
     public void deleteMaxCountQuota() throws MailboxException {
-        maxQuotaManager.setDefaultMaxMessage(Quota.UNLIMITED);
+        maxQuotaManager.removeDefaultMaxMessage();
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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 31440b3..3b50cc4 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
@@ -18,15 +18,18 @@
  ****************************************************************/
 package org.apache.james.webadmin.service;
 
+import java.util.Optional;
+
 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.mailbox.quota.QuotaCount;
+import org.apache.james.mailbox.quota.QuotaSize;
 import org.apache.james.webadmin.dto.QuotaDTO;
-import org.apache.james.webadmin.validation.QuotaValue.QuotaCount;
-import org.apache.james.webadmin.validation.QuotaValue.QuotaSize;
+
+import com.github.fge.lambdas.Throwing;
 
 public class UserQuotaService {
 
@@ -37,10 +40,12 @@ public class UserQuotaService {
         this.maxQuotaManager = maxQuotaManager;
     }
 
-    public void defineQuota(String user, QuotaDTO quota) throws 
MailboxException {
+    public void defineQuota(String user, QuotaDTO quota) {
         QuotaRoot quotaRoot = QuotaRoot.forUser(user);
-        maxQuotaManager.setMaxMessage(quotaRoot, quota.getCount());
-        maxQuotaManager.setMaxStorage(quotaRoot, quota.getSize());
+        quota.getCount()
+            .ifPresent(Throwing.consumer(count -> 
maxQuotaManager.setMaxMessage(quotaRoot, count)));
+        quota.getSize()
+            .ifPresent(Throwing.consumer(size -> 
maxQuotaManager.setMaxStorage(quotaRoot, size)));
     }
 
     public QuotaDTO getQuota(String user) throws MailboxException {
@@ -52,27 +57,27 @@ public class UserQuotaService {
             .build();
     }
 
-    public Long getMaxSizeQuota(String user) throws MailboxException {
+    public Optional<QuotaSize> getMaxSizeQuota(String user) throws 
MailboxException {
         return maxQuotaManager.getMaxStorage(QuotaRoot.forUser(user));
     }
 
     public void defineMaxSizeQuota(String user, QuotaSize quotaSize) throws 
MailboxException {
-        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), 
quotaSize.asLong());
+        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), quotaSize);
     }
 
     public void deleteMaxSizeQuota(String user) throws MailboxException {
-        maxQuotaManager.setMaxStorage(QuotaRoot.forUser(user), 
Quota.UNLIMITED);
+        maxQuotaManager.removeMaxStorage(QuotaRoot.forUser(user));
     }
 
-    public Long getMaxCountQuota(String user) throws MailboxException {
+    public Optional<QuotaCount> getMaxCountQuota(String user) throws 
MailboxException {
         return maxQuotaManager.getMaxMessage(QuotaRoot.forUser(user));
     }
 
     public void defineMaxCountQuota(String user, QuotaCount quotaCount) throws 
MailboxException {
-        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), 
quotaCount.asLong());
+        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), quotaCount);
     }
 
     public void deleteMaxCountQuota(String user) throws MailboxException {
-        maxQuotaManager.setMaxMessage(QuotaRoot.forUser(user), 
Quota.UNLIMITED);
+        maxQuotaManager.removeMaxMessage(QuotaRoot.forUser(user));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ebcb09a0/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
deleted file mode 100644
index a0ea65f..0000000
--- 
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/validation/QuotaValue.java
+++ /dev/null
@@ -1,78 +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.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;
-    }
-
-}


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

Reply via email to