This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 8ba14ba0184a7b8b9a716e0ffcd241894b68c8e2 Author: Rene Cordier <[email protected]> AuthorDate: Wed May 20 11:06:27 2020 +0700 JAMES-3171 Port QuotaLoader to jmap-rfc8621 --- .../scala/org/apache/james/jmap/mail/Quotas.scala | 10 ++-- .../org/apache/james/jmap/model/UnsignedInt.scala | 12 ++++- .../quotas/QuotaLoader.scala} | 25 ++++----- .../quotas/QuotaLoaderWithPreloadedDefault.scala | 60 ++++++++++++++++++++++ .../james/jmap/utils/quotas/QuotaReader.scala | 52 +++++++++++++++++++ 5 files changed, 142 insertions(+), 17 deletions(-) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Quotas.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Quotas.scala index c9d4212..e107efe 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Quotas.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Quotas.scala @@ -21,16 +21,16 @@ package org.apache.james.jmap.mail import org.apache.james.core.Domain import org.apache.james.jmap.model.UnsignedInt.UnsignedInt -import org.apache.james.mailbox.model.{QuotaRoot => JavaQuotaRoot} +import org.apache.james.mailbox.model.{QuotaRoot => ModelQuotaRoot} import scala.compat.java8.OptionConverters._ object QuotaRoot{ - def fromJava(quotaRoot: JavaQuotaRoot) = QuotaRoot(quotaRoot.getValue, quotaRoot.getDomain.asScala) + def toJmap(quotaRoot: ModelQuotaRoot) = QuotaRoot(quotaRoot.getValue, quotaRoot.getDomain.asScala) } case class QuotaRoot(value: String, domain: Option[Domain]) { - def asJava: JavaQuotaRoot = JavaQuotaRoot.quotaRoot(value, domain.asJava) + def toModel: ModelQuotaRoot = ModelQuotaRoot.quotaRoot(value, domain.asJava) } object Quotas { @@ -51,6 +51,10 @@ case class QuotaId(quotaRoot: QuotaRoot) extends AnyVal { def getName: String = quotaRoot.value } +object Quota { + def from(quota: Map[Quotas.Type, Value]) = new Quota(quota) +} + case class Quota(quota: Map[Quotas.Type, Value]) extends AnyVal case class Value(used: UnsignedInt, max: Option[UnsignedInt]) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala index 3b51240..2fae439 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala @@ -19,11 +19,19 @@ package org.apache.james.jmap.model +import eu.timepit.refined import eu.timepit.refined.api.Refined import eu.timepit.refined.numeric.Interval.Closed object UnsignedInt { -//Unsigned int between [0, 2^53] -type UnsignedInt = Long Refined Closed[0L, 9007199254740992L] + //Unsigned int between [0, 2^53] + type UnsignedIntConstraint = Closed[0L, 9007199254740992L] + type UnsignedInt = Long Refined UnsignedIntConstraint + + def liftOrThrow(value: Long): UnsignedInt = + refined.refineV[UnsignedIntConstraint](value) match { + case Right(value) => value + case Left(error) => throw new IllegalArgumentException(error) + } } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoader.scala similarity index 56% copy from server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala copy to server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoader.scala index 3b51240..0c770c7 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/UnsignedInt.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoader.scala @@ -1,4 +1,4 @@ -/** ************************************************************** +/**************************************************************** * 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 * @@ -6,24 +6,25 @@ * 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 * - * * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * * Unless required by applicable law or agreed to in writing, * * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * - * ***************************************************************/ + ****************************************************************/ -package org.apache.james.jmap.model +package org.apache.james.jmap.utils.quotas -import eu.timepit.refined.api.Refined -import eu.timepit.refined.numeric.Interval.Closed - -object UnsignedInt { -//Unsigned int between [0, 2^53] -type UnsignedInt = Long Refined Closed[0L, 9007199254740992L] +import org.apache.james.jmap.mail.Quotas +import org.apache.james.mailbox.exception.MailboxException +import org.apache.james.mailbox.model.MailboxPath +import reactor.core.scala.publisher.SMono +trait QuotaLoader { + @throws[MailboxException] + def getQuotas(mailboxPath: MailboxPath): SMono[Quotas] } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoaderWithPreloadedDefault.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoaderWithPreloadedDefault.scala new file mode 100644 index 0000000..8a4c458 --- /dev/null +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaLoaderWithPreloadedDefault.scala @@ -0,0 +1,60 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap.utils.quotas + +import javax.inject.Inject +import org.apache.james.jmap.mail.{QuotaRoot, Quotas} +import org.apache.james.mailbox.MailboxSession +import org.apache.james.mailbox.exception.MailboxException +import org.apache.james.mailbox.model.{MailboxPath, QuotaRoot => ModelQuotaRoot} +import org.apache.james.mailbox.quota.UserQuotaRootResolver +import reactor.core.scala.publisher.SMono + + +class QuotaLoaderWithPreloadedDefaultFactory @Inject()(quotaRootResolver: UserQuotaRootResolver, quotaReader: QuotaReader) { + + def loadFor(session: MailboxSession): SMono[QuotaLoaderWithPreloadedDefault] = + SMono.fromCallable(() => new QuotaLoaderWithPreloadedDefault( + quotaRootResolver, + quotaReader, + session, + getUserDefaultQuotas(session))) + + + @throws[MailboxException] + private def getUserDefaultQuotas(session:MailboxSession): SMono[Quotas] = { + val quotaRoot: ModelQuotaRoot = quotaRootResolver.forUser(session.getUser) + quotaReader.retrieveQuotas(QuotaRoot.toJmap(quotaRoot)) + } +} + +class QuotaLoaderWithPreloadedDefault(quotaRootResolver: UserQuotaRootResolver, + quotaReader: QuotaReader, + session: MailboxSession, + preloadedUserDefaultQuotas: SMono[Quotas]) extends QuotaLoader { + @throws[MailboxException] + override def getQuotas(mailboxPath: MailboxPath): SMono[Quotas] = + if (mailboxPath.belongsTo(session)) { + preloadedUserDefaultQuotas + } else { + val quotaRoot: ModelQuotaRoot = quotaRootResolver.getQuotaRoot(mailboxPath) + quotaReader.retrieveQuotas(QuotaRoot.toJmap(quotaRoot)) + } +} diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaReader.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaReader.scala new file mode 100644 index 0000000..2545c83 --- /dev/null +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/utils/quotas/QuotaReader.scala @@ -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.jmap.utils.quotas + +import javax.inject.Inject +import org.apache.james.core.quota.{QuotaLimitValue, QuotaUsageValue} +import org.apache.james.jmap.mail._ +import org.apache.james.jmap.model.UnsignedInt +import org.apache.james.jmap.model.UnsignedInt.UnsignedInt +import org.apache.james.mailbox.exception.MailboxException +import org.apache.james.mailbox.model.{Quota => ModelQuota} +import org.apache.james.mailbox.quota.QuotaManager +import reactor.core.scala.publisher.SMono + +class QuotaReader @Inject() (quotaManager: QuotaManager) { + @throws[MailboxException] + def retrieveQuotas(quotaRoot: QuotaRoot): SMono[Quotas] = + SMono.just(Quotas.from( + QuotaId.fromQuotaRoot(quotaRoot), + Quota.from(Map( + Quotas.Storage -> quotaToValue(quotaManager.getStorageQuota(quotaRoot.toModel)), + Quotas.Message -> quotaToValue(quotaManager.getMessageQuota(quotaRoot.toModel)))))) + + private def quotaToValue[T <: QuotaLimitValue[T], U <: QuotaUsageValue[U, T]](quota: ModelQuota[T, U]): Value = + Value( + UnsignedInt.liftOrThrow(quota.getUsed.asLong), + asNumber(quota.getLimit)) + + private def asNumber(value: QuotaLimitValue[_]): Option[UnsignedInt] = + if (value.isUnlimited) { + None + } else { + Some(UnsignedInt.liftOrThrow(value.asLong)) + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
