You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2017/09/29 07:21:42 UTC
[04/31] james-project git commit: MAILBOX-307 Refactor ACL handling
MAILBOX-307 Refactor ACL handling
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f388ff94
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f388ff94
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f388ff94
Branch: refs/heads/master
Commit: f388ff94128009549b05fcd653199d7dab1b6d7b
Parents: 45c3dfb
Author: benwa <bt...@linagora.com>
Authored: Mon Sep 25 11:35:29 2017 +0700
Committer: Matthieu Baechler <ma...@apache.org>
Committed: Fri Sep 29 09:20:39 2017 +0200
----------------------------------------------------------------------
mailbox/api/pom.xml | 4 +
.../mailbox/acl/UnionMailboxACLResolver.java | 10 +-
.../exception/UnsupportedRightException.java | 2 +-
.../apache/james/mailbox/model/MailboxACL.java | 2 +-
.../james/mailbox/model/SimpleMailboxACL.java | 1002 +++++-------------
.../acl/UnionMailboxACLResolverTest.java | 541 +++++-----
.../james/mailbox/model/Rfc4314RightsTest.java | 72 +-
.../model/SimpleMailboxACLEntryKeyTest.java | 160 +--
.../mailbox/model/SimpleMailboxACLTest.java | 46 +-
.../cassandra/mail/CassandraACLMapperTest.java | 18 +-
.../json/SimpleMailboxACLJsonConverter.java | 16 +-
.../json/SimpleMailboxACLJsonConverterTest.java | 25 +-
.../imap/processor/DeleteACLProcessor.java | 9 +-
.../james/imap/processor/GetACLProcessor.java | 8 +-
.../james/imap/processor/GetQuotaProcessor.java | 4 +-
.../imap/processor/GetQuotaRootProcessor.java | 4 +-
.../imap/processor/ListRightsProcessor.java | 10 +-
.../james/imap/processor/MyRightsProcessor.java | 14 +-
.../james/imap/processor/SetACLProcessor.java | 8 +-
.../imap/processor/DeleteACLProcessorTest.java | 13 +-
.../imap/processor/GetACLProcessorTest.java | 11 +-
.../imap/processor/GetQuotaProcessorTest.java | 6 +-
.../processor/GetQuotaRootProcessorTest.java | 7 +-
.../imap/processor/ListRightsProcessorTest.java | 12 +-
.../imap/processor/SetACLProcessorTest.java | 14 +-
25 files changed, 810 insertions(+), 1208 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/f388ff94/mailbox/api/pom.xml
----------------------------------------------------------------------
diff --git a/mailbox/api/pom.xml b/mailbox/api/pom.xml
index df8c254..d34d3ba 100644
--- a/mailbox/api/pom.xml
+++ b/mailbox/api/pom.xml
@@ -37,6 +37,10 @@
<artifactId>apache-mime4j-dom</artifactId>
</dependency>
<dependency>
+ <groupId>com.github.fge</groupId>
+ <artifactId>throwing-lambdas</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.github.steveash.guavate</groupId>
<artifactId>guavate</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/james-project/blob/f388ff94/mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java b/mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
index 7ba49ea..545d5df 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
@@ -287,7 +287,7 @@ public class UnionMailboxACLResolver implements MailboxACLResolver {
@Override
public boolean isReadWrite(MailboxACLRights mailboxACLRights, Flags sharedFlags) throws UnsupportedRightException {
/* the two fast cases first */
- if (mailboxACLRights.contains(Rfc4314Rights.i_Insert_RIGHT) || mailboxACLRights.contains(Rfc4314Rights.e_PerformExpunge_RIGHT)) {
+ if (mailboxACLRights.contains(SimpleMailboxACL.Right.Insert) || mailboxACLRights.contains(SimpleMailboxACL.Right.PerformExpunge)) {
return true;
}
/*
@@ -303,12 +303,12 @@ public class UnionMailboxACLResolver implements MailboxACLResolver {
* flags.
*/
else if (sharedFlags != null) {
- if (sharedFlags.contains(Flag.DELETED) && mailboxACLRights.contains(Rfc4314Rights.t_DeleteMessages_RIGHT)) {
+ if (sharedFlags.contains(Flag.DELETED) && mailboxACLRights.contains(SimpleMailboxACL.Right.DeleteMessages)) {
return true;
- } else if (sharedFlags.contains(Flag.SEEN) && mailboxACLRights.contains(Rfc4314Rights.s_WriteSeenFlag_RIGHT)) {
+ } else if (sharedFlags.contains(Flag.SEEN) && mailboxACLRights.contains(SimpleMailboxACL.Right.WriteSeenFlag)) {
return true;
} else {
- boolean hasWriteRight = mailboxACLRights.contains(Rfc4314Rights.w_Write_RIGHT);
+ boolean hasWriteRight = mailboxACLRights.contains(SimpleMailboxACL.Right.Write);
return hasWriteRight && (sharedFlags.contains(Flag.ANSWERED) || sharedFlags.contains(Flag.DRAFT) || sharedFlags.contains(Flag.FLAGGED) || sharedFlags.contains(Flag.RECENT) || sharedFlags.contains(Flag.USER));
}
}
@@ -377,7 +377,7 @@ public class UnionMailboxACLResolver implements MailboxACLResolver {
}
private static MailboxACLRights[] toListRightsArray(MailboxACLRights implicitRights) throws UnsupportedRightException {
- List<MailboxACLRights> result = new ArrayList<>(Rfc4314Rights.FIELD_COUNT);
+ List<MailboxACLRights> result = new ArrayList<>();
result.add(implicitRights);
for (MailboxACLRight right : SimpleMailboxACL.FULL_RIGHTS) {
if (!implicitRights.contains(right)) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/f388ff94/mailbox/api/src/main/java/org/apache/james/mailbox/exception/UnsupportedRightException.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/exception/UnsupportedRightException.java b/mailbox/api/src/main/java/org/apache/james/mailbox/exception/UnsupportedRightException.java
index a2cfccd..8ca5dcd 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/exception/UnsupportedRightException.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/exception/UnsupportedRightException.java
@@ -42,7 +42,7 @@ public class UnsupportedRightException extends MailboxSecurityException {
}
public UnsupportedRightException(MailboxACLRight unsupportedRight) {
- this(unsupportedRight.getValue());
+ this(unsupportedRight.asCharacter());
}
public UnsupportedRightException(String msg, Exception cause) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/f388ff94/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
index 235ddce..b6e97d2 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
@@ -117,7 +117,7 @@ public interface MailboxACL {
*
* @return char representation of this right
*/
- char getValue();
+ char asCharacter();
}
/**
http://git-wip-us.apache.org/repos/asf/james-project/blob/f388ff94/mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
----------------------------------------------------------------------
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
index 884e625..2191526 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
@@ -19,492 +19,269 @@
package org.apache.james.mailbox.model;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.EnumSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.mailbox.exception.UnsupportedRightException;
+import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
/**
* Default implementation of {@link MailboxACL}.
*
*/
public class SimpleMailboxACL implements MailboxACL {
- /**
- * Supports only the Standard Rights of RFC 4314 section 2.1. The rights are
- * stored as single bits in 32 bit int {@link #value} field.
- */
- public static class Rfc4314Rights implements MailboxACLRights {
- /**
- * See RFC 4314 section 2.1.1. Obsolete Rights.
- */
- public enum CompatibilityMode {
- ck_detx, ckx_det, NO_COMPATIBILITY
- }
-
- private class Rfc4314RightsIterator implements Iterator<MailboxACLRight> {
-
- int position = 0;
-
- public Rfc4314RightsIterator() {
- super();
- nextPostion();
- }
-
- @Override
- public boolean hasNext() {
- return position < FIELD_COUNT;
- }
-
- @Override
- public MailboxACLRight next() {
- if (!hasNext()) {
- throw new IndexOutOfBoundsException("No next element at position " + position + " from " + FIELD_COUNT + " in " + Rfc4314RightsIterator.class.getName());
- }
- MailboxACLRight result = indexRightLookup[position];
- position++;
- nextPostion();
- return result;
- }
-
- /**
- */
- private void nextPostion() {
- while (position < FIELD_COUNT && (value & (1 << position)) == 0) {
- position++;
- }
- }
-
- @Override
- public void remove() {
- throw new java.lang.UnsupportedOperationException("Cannot remove rights through this " + Rfc4314RightsIterator.class.getName());
- }
-
- }
-
- /**
- * a - administer (perform SETACL/DELETEACL/GETACL/LISTRIGHTS)
- *
- */
- public static final char a_Administer = 'a';
-
- static final int a_Administer_MASK = 1;
- public static final MailboxACLRight a_Administer_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(a_Administer);
- public static final char c_ObsoleteCreate = 'c';
- public static final char d_ObsoleteDelete = 'd';
- /**
- * e - perform EXPUNGE and expunge as a part of CLOSE
- *
- */
- public static final char e_PerformExpunge = 'e';
- static final int e_PerformExpunge_MASK = 1 << 1;
- public static final MailboxACLRight e_PerformExpunge_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(e_PerformExpunge);
- public static final int EMPTY_MASK = 0;
- public static final int FIELD_COUNT = 11;
- /**
- * i - insert (perform APPEND, COPY into mailbox)
- *
- */
- public static final char i_Insert = 'i';
- static final int i_Insert_MASK = 1 << 2;
-
- public static final MailboxACLRight i_Insert_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(i_Insert);
- private static final char[] indexFlagLookup;
- private static final MailboxACLRight[] indexRightLookup;
- /**
- * k - create mailboxes (CREATE new sub-mailboxes in any
- * implementation-defined hierarchy, parent mailbox for the new mailbox
- * name in RENAME)
- *
- */
- public static final char k_CreateMailbox = 'k';
- static final int k_CreateMailbox_MASK = 1 << 3;
- public static final MailboxACLRight k_CreateMailbox_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(k_CreateMailbox);
+ public enum Right implements MailboxACLRight {
+ Administer('a'), // (perform SETACL/DELETEACL/GETACL/LISTRIGHTS)
+ PerformExpunge('e'), //perform EXPUNGE and expunge as a part of CLOSE
+ Insert('i'), //insert (perform APPEND, COPY into mailbox)
+ /*
+ * create mailboxes (CREATE new sub-mailboxes in any
+ * implementation-defined hierarchy, parent mailbox for the new mailbox
+ * name in RENAME)
+ * */
+ CreateMailbox('k'),
+ Lookup('l'), //lookup (mailbox is visible to LIST/LSUB commands, SUBSCRIBE mailbox)
+ Post('p'), //post (send mail to submission address for mailbox, not enforced by IMAP4 itself)
+ Read('r'), //read (SELECT the mailbox, perform STATUS)
/**
- * l - lookup (mailbox is visible to LIST/LSUB commands, SUBSCRIBE
- * mailbox)
- *
+ * keep seen/unseen information across sessions (set or clear \SEEN
+ * flag via STORE, also set \SEEN during APPEND/COPY/ FETCH BODY[...])
*/
- public static final char l_Lookup = 'l';
- static final int l_Lookup_MASK = 1 << 4;
- public static final MailboxACLRight l_Lookup_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(l_Lookup);
+ WriteSeenFlag('s'),
+ DeleteMessages('t'), //delete messages (set or clear \DELETED flag via STORE, set \DELETED flag during APPEND/COPY)
/**
- * p - post (send mail to submission address for mailbox, not enforced
- * by IMAP4 itself)
- *
+ * write (set or clear flags other than \SEEN and \DELETED via
+ * STORE, also set them during APPEND/COPY)
*/
- public static final char p_Post = 'p';
- static final int p_Post_MASK = 1 << 5;
- public static final MailboxACLRight p_Post_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(p_Post);
+ Write('w'),
+ DeleteMailbox('x'); //delete mailbox (DELETE mailbox, old mailbox name in RENAME)
- /**
- * r - read (SELECT the mailbox, perform STATUS)
- *
- */
- public static final char r_Read = 'r';
- static final int r_Read_MASK = 1 << 6;
+ private final char rightCharacter;
- public static final MailboxACLRight r_Read_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(r_Read);
- /**
- * s - keep seen/unseen information across sessions (set or clear \SEEN
- * flag via STORE, also set \SEEN during APPEND/COPY/ FETCH BODY[...])
- *
- */
- public static final char s_WriteSeenFlag = 's';
+ Right(char rightCharacter) {
+ this.rightCharacter = rightCharacter;
+ }
- static final int s_WriteSeenFlag_MASK = 1 << 7;
+ @Override
+ public char asCharacter() {
+ return rightCharacter;
+ }
- public static final MailboxACLRight s_WriteSeenFlag_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(s_WriteSeenFlag);
+ public static final EnumSet<Right> allRights = EnumSet.allOf(Right.class);
- public static final char t_DeleteMessages = 't';
+ public static Right forChar(char c) throws UnsupportedRightException {
+ return Right.allRights
+ .stream()
+ .filter(r -> r.asCharacter() == c)
+ .findFirst()
+ .orElseThrow(() -> new UnsupportedRightException(c));
+ }
+ }
+ /**
+ * Supports only the Standard Rights of RFC 4314 section 2.1. The rights are
+ * stored as single bits in 32 bit int {@link #value} field.
+ */
+ public static class Rfc4314Rights implements MailboxACLRights {
/**
- * t - delete messages (set or clear \DELETED flag via STORE, set
- * \DELETED flag during APPEND/COPY)
- *
- */
- static final int t_DeleteMessages_MASK = 1 << 8;
- public static final MailboxACLRight t_DeleteMessages_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(t_DeleteMessages);
- /**
- * w - write (set or clear flags other than \SEEN and \DELETED via
- * STORE, also set them during APPEND/COPY)
- *
- */
- public static final char w_Write = 'w';
- static final int w_Write_MASK = 1 << 9;
- public static final MailboxACLRight w_Write_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(w_Write);
- /**
- * x - delete mailbox (DELETE mailbox, old mailbox name in RENAME)
- *
+ * See RFC 4314 section 2.1.1. Obsolete Rights.
*/
- public static final char x_DeleteMailbox = 'x';
- static final int x_DeleteMailbox_MASK = 1 << 10;
- public static final MailboxACLRight x_DeleteMailbox_RIGHT = new SimpleMailboxACL.SimpleMailboxACLRight(x_DeleteMailbox);
- static {
- indexFlagLookup = new char[] { a_Administer, e_PerformExpunge, i_Insert, k_CreateMailbox, l_Lookup, p_Post, r_Read, s_WriteSeenFlag, t_DeleteMessages, w_Write, x_DeleteMailbox };
- indexRightLookup = new MailboxACLRight[] { a_Administer_RIGHT, e_PerformExpunge_RIGHT, i_Insert_RIGHT, k_CreateMailbox_RIGHT, l_Lookup_RIGHT, p_Post_RIGHT, r_Read_RIGHT, s_WriteSeenFlag_RIGHT, t_DeleteMessages_RIGHT, w_Write_RIGHT, x_DeleteMailbox_RIGHT };
+ public enum CompatibilityMode {
+ ck_detx, ckx_det, NO_COMPATIBILITY
}
- private static int flagMaskLookup(char flag) throws UnsupportedRightException {
- switch (flag) {
- case a_Administer:
- return a_Administer_MASK;
- case e_PerformExpunge:
- return e_PerformExpunge_MASK;
- case i_Insert:
- return i_Insert_MASK;
- case k_CreateMailbox:
- return k_CreateMailbox_MASK;
- case l_Lookup:
- return l_Lookup_MASK;
- case p_Post:
- return p_Post_MASK;
- case r_Read:
- return r_Read_MASK;
- case s_WriteSeenFlag:
- return s_WriteSeenFlag_MASK;
- case t_DeleteMessages:
- return t_DeleteMessages_MASK;
- case w_Write:
- return w_Write_MASK;
- case x_DeleteMailbox:
- return x_DeleteMailbox_MASK;
- default:
- throw new UnsupportedRightException(flag);
- }
- }
+ private static final char c_ObsoleteCreate = 'c';
+ private static final char d_ObsoleteDelete = 'd';
/**
* See RFC 4314 section 2.1.1. Obsolete Rights.
*/
private final CompatibilityMode compatibilityMode = CompatibilityMode.ckx_det;
- /**
- * 32 bit <code>int</code> to store the rights.
- */
- private final int value;
+ private final EnumSet<Right> value;
- private Rfc4314Rights() {
- this.value = EMPTY_MASK;
+ private Rfc4314Rights(EnumSet<Right> rights) {
+ this.value = EnumSet.copyOf(rights);
}
- public Rfc4314Rights(boolean canAdminister, boolean canCreateMailbox, boolean canDeleteMailbox, boolean canDeleteMessages, boolean canInsert, boolean canLookup, boolean canPerformExpunge, boolean canPost, boolean canRead, boolean canWrite, boolean canWriteSeenFlag) {
- super();
- int v = 0;
-
- if (canAdminister) {
- v |= a_Administer_MASK;
- }
- if (canCreateMailbox) {
- v |= k_CreateMailbox_MASK;
- }
- if (canDeleteMailbox) {
- v |= x_DeleteMailbox_MASK;
- }
- if (canDeleteMessages) {
- v |= t_DeleteMessages_MASK;
- }
- if (canInsert) {
- v |= i_Insert_MASK;
- }
- if (canLookup) {
- v |= l_Lookup_MASK;
- }
- if (canPerformExpunge) {
- v |= e_PerformExpunge_MASK;
- }
- if (canPost) {
- v |= p_Post_MASK;
- }
- if (canRead) {
- v |= r_Read_MASK;
- }
- if (canWrite) {
- v |= w_Write_MASK;
- }
- if (canWriteSeenFlag) {
- v |= s_WriteSeenFlag_MASK;
- }
+ private Rfc4314Rights() {
+ this(EnumSet.noneOf(Right.class));
+ }
- this.value = v;
+ public Rfc4314Rights(Right... rights) {
+ this(EnumSet.copyOf(Arrays.asList(rights)));
+ }
+ public Rfc4314Rights(MailboxACLRight right) throws UnsupportedRightException {
+ this.value = EnumSet.of(Right.forChar(right.asCharacter()));
}
- public Rfc4314Rights(int value) throws UnsupportedRightException {
- if ((value >> FIELD_COUNT) != 0) {
- throw new UnsupportedRightException();
+ /* Used for json serialization (probably a bad idea) */
+ public Rfc4314Rights(int serializedRights) {
+ List<Right> rights = Right.allRights.stream()
+ .filter(right -> ((serializedRights >> right.ordinal()) & 1) != 0)
+ .collect(Collectors.toList());
+ if (rights.isEmpty()) {
+ this.value = EnumSet.noneOf(Right.class);
+ } else {
+ this.value = EnumSet.copyOf(rights);
}
- this.value = value;
- }
-
- public Rfc4314Rights(MailboxACLRight right) throws UnsupportedRightException {
- this.value = flagMaskLookup(right.getValue());
}
public Rfc4314Rights(String serializedRfc4314Rights) throws UnsupportedRightException {
- int v = 0;
-
- for (int i = 0; i < serializedRfc4314Rights.length(); i++) {
- char flag = serializedRfc4314Rights.charAt(i);
- switch (flag) {
- case c_ObsoleteCreate:
- switch (compatibilityMode) {
- case ck_detx:
- v |= k_CreateMailbox_MASK;
- break;
- case ckx_det:
- v |= k_CreateMailbox_MASK;
- v |= x_DeleteMailbox_MASK;
- break;
- case NO_COMPATIBILITY:
- throw new UnsupportedRightException(flag);
- default:
- throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
- }
- break;
- case d_ObsoleteDelete:
- switch (compatibilityMode) {
- case ck_detx:
- v |= e_PerformExpunge_MASK;
- v |= t_DeleteMessages_MASK;
- v |= x_DeleteMailbox_MASK;
- break;
- case ckx_det:
- v |= e_PerformExpunge_MASK;
- v |= t_DeleteMessages_MASK;
- break;
- case NO_COMPATIBILITY:
- throw new UnsupportedRightException(flag);
- default:
- throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
- }
- break;
- default:
- v |= flagMaskLookup(flag);
- }
+ List<Right> rights = serializedRfc4314Rights.chars()
+ .mapToObj(i -> (char) i)
+ .flatMap(Throwing.function(this::convert).sneakyThrow())
+ .collect(Collectors.toList());
+ if (rights.isEmpty()) {
+ this.value = EnumSet.noneOf(Right.class);
+ } else {
+ this.value = EnumSet.copyOf(rights);
}
- this.value = v;
-
}
- public boolean contains(char flag) throws UnsupportedRightException {
-
+ private Stream<Right> convert(char flag) throws UnsupportedRightException {
switch (flag) {
case c_ObsoleteCreate:
- switch (compatibilityMode) {
- case ck_detx:
- return (value & k_CreateMailbox_MASK) != 0;
- case ckx_det:
- return (value & (k_CreateMailbox_MASK | x_DeleteMailbox_MASK)) != 0;
- case NO_COMPATIBILITY:
- throw new UnsupportedRightException(flag);
- default:
- throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
- }
+ return convertObsoleteCreate(flag);
case d_ObsoleteDelete:
- switch (compatibilityMode) {
- case ck_detx:
- return (value & (e_PerformExpunge_MASK | t_DeleteMessages_MASK | x_DeleteMailbox_MASK)) != 0;
- case ckx_det:
- return (value & (e_PerformExpunge_MASK | t_DeleteMessages_MASK)) != 0;
- case NO_COMPATIBILITY:
- throw new UnsupportedRightException(flag);
- default:
- throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
- }
+ return convertObsoleteDelete(flag);
default:
- return (value & flagMaskLookup(flag)) != 0;
+ return Stream.of(Right.forChar(flag));
}
}
- /**
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLRights#contains(org
- * .apache.james.mailbox.MailboxACL.MailboxACLRight)
- */
+ private Stream<Right> convertObsoleteDelete(char flag) throws UnsupportedRightException {
+ switch (compatibilityMode) {
+ case ck_detx:
+ return Stream.of(Right.PerformExpunge, Right.DeleteMessages, Right.DeleteMailbox);
+ case ckx_det:
+ return Stream.of(Right.PerformExpunge, Right.DeleteMessages);
+ case NO_COMPATIBILITY:
+ throw new UnsupportedRightException(flag);
+ default:
+ throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
+ }
+ }
+
+ private Stream<Right> convertObsoleteCreate(char flag) throws UnsupportedRightException {
+ switch (compatibilityMode) {
+ case ck_detx:
+ return Stream.of(Right.CreateMailbox);
+ case ckx_det:
+ return Stream.of(Right.CreateMailbox, Right.DeleteMailbox);
+ case NO_COMPATIBILITY:
+ throw new UnsupportedRightException(flag);
+ default:
+ throw new IllegalStateException("Unexpected enum member: " + CompatibilityMode.class.getName() + "." + compatibilityMode.name());
+ }
+ }
+
+ public boolean contains(char flag) throws UnsupportedRightException {
+ return contains(Right.forChar(flag));
+ }
+
@Override
public boolean contains(MailboxACLRight right) throws UnsupportedRightException {
- return contains(right.getValue());
+ return value.contains(Right.forChar(right.asCharacter()));
+ }
+
+ /* Used for json serialization (probably a bad idea) */
+ public int serializeAsInteger() {
+ return value.stream().mapToInt(x -> 1 << x.ordinal()).sum();
}
@Override
public boolean equals(Object o) {
if (o instanceof Rfc4314Rights) {
- return this.value == ((Rfc4314Rights) o).value;
+ Rfc4314Rights that = (Rfc4314Rights) o;
+ return this.value.equals(that.value);
} else if (o instanceof MailboxACLRights) {
try {
- return this.value == new Rfc4314Rights(((MailboxACLRights) o).serialize()).value;
+ MailboxACLRights that = (MailboxACLRights) o;
+ return this.value == new Rfc4314Rights(that.serialize()).value;
} catch (UnsupportedRightException e) {
throw new RuntimeException(e);
}
- } else {
- return false;
}
+ return false;
}
- /**
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLRights#except(org.apache
- * .james.mailbox.MailboxACL.MailboxACLRights)
- */
@Override
public MailboxACLRights except(MailboxACLRights toRemove) throws UnsupportedRightException {
- if (this.value == EMPTY_MASK || toRemove == null || toRemove.isEmpty()) {
- /* nothing to remove */
- return this;
- } else if (toRemove instanceof Rfc4314Rights) {
- Rfc4314Rights other = (Rfc4314Rights) toRemove;
- if (other.value == EMPTY_MASK) {
- /* toRemove is an identity element */
- return this;
- } else {
- return new Rfc4314Rights(this.value & (~((other).value)));
- }
- } else {
- return new Rfc4314Rights(this.value & (~(new Rfc4314Rights(toRemove.serialize()).value)));
- }
+ EnumSet<Right> copy = EnumSet.copyOf(value);
+ copy.removeAll(convertRightsToList(toRemove));
+ return new Rfc4314Rights(copy);
}
- public int getValue() {
- return value;
- }
-
- /**
- * Returns {@link #value}.
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return value;
- }
-
- /**
- * @see org.apache.james.mailbox.model.MailboxACL.MailboxACLRights#isEmpty()
- */
@Override
public boolean isEmpty() {
- return value == EMPTY_MASK;
+ return value.isEmpty();
}
- /**
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLRights#isSupported(
- * org.apache.james.mailbox.MailboxACL.MailboxACLRight)
- */
@Override
public boolean isSupported(MailboxACLRight right) {
try {
- contains(right.getValue());
+ contains(right.asCharacter());
return true;
} catch (UnsupportedRightException e) {
return false;
}
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Iterable#iterator()
- */
@Override
public Iterator<MailboxACLRight> iterator() {
- return new Rfc4314RightsIterator();
+ ImmutableList<MailboxACLRight> rights = ImmutableList.copyOf(value);
+ return rights.iterator();
}
- /*
- * (non-Javadoc)
- *
- * @see org.apache.james.mailbox.MailboxACL.MailboxACLRights#serialize()
- */
@Override
public String serialize() {
- StringBuilder result = new StringBuilder(FIELD_COUNT);
- for (int i = 0; i < FIELD_COUNT; i++) {
- if ((value & (1 << i)) != 0) {
- result.append(indexFlagLookup[i]);
- }
- }
- return result.toString();
+ return value.stream()
+ .map(Right::asCharacter)
+ .map(String::valueOf)
+ .collect(Collectors.joining());
}
- /**
- * Returns {@link #serialize()}
- *
- * @see java.lang.Object#toString()
- */
@Override
public String toString() {
return serialize();
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLRights#union(org.apache
- * .james.mailbox.MailboxACL.MailboxACLRights)
- */
@Override
public MailboxACLRights union(MailboxACLRights toAdd) throws UnsupportedRightException {
- if (this.value == EMPTY_MASK) {
- /* this is an identity element */
- return toAdd;
- } else if (toAdd instanceof Rfc4314Rights) {
- Rfc4314Rights other = (Rfc4314Rights) toAdd;
- if (other.value == EMPTY_MASK) {
- /* toAdd is an identity element */
- return this;
- } else {
- return new Rfc4314Rights(this.value | other.value);
- }
- } else {
- return new Rfc4314Rights(this.value | new Rfc4314Rights(toAdd.serialize()).value);
- }
+ Preconditions.checkNotNull(toAdd);
+ EnumSet<Right> rightUnion = EnumSet.noneOf(Right.class);
+ rightUnion.addAll(value);
+ rightUnion.addAll(convertRightsToList(toAdd));
+ return new Rfc4314Rights(rightUnion);
+ }
+
+ private List<Right> convertRightsToList(MailboxACLRights toAdd) {
+ return ImmutableList.copyOf(Optional.ofNullable(toAdd).orElse(Rfc4314Rights.empty()))
+ .stream()
+ .map(Throwing.function(right -> Right.forChar(right.asCharacter())))
+ .collect(Guavate.toImmutableList());
+ }
+
+ private static MailboxACLRights empty() {
+ return new Rfc4314Rights();
}
}
@@ -524,24 +301,14 @@ public class SimpleMailboxACL implements MailboxACL {
this.value = value;
}
public SimpleMailboxACLEntry(String key, String value) throws UnsupportedRightException {
- this(new SimpleMailboxACLEntryKey(key), new Rfc4314Rights(value));
+ this(SimpleMailboxACLEntryKey.deserialize(key), new Rfc4314Rights(value));
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Map.Entry#getKey()
- */
@Override
public MailboxACLEntryKey getKey() {
return key;
}
- /*
- * (non-Javadoc)
- *
- * @see java.util.Map.Entry#getValue()
- */
@Override
public MailboxACLRights getValue() {
return value;
@@ -554,7 +321,7 @@ public class SimpleMailboxACL implements MailboxACL {
*/
@Override
public MailboxACLRights setValue(MailboxACLRights value) {
- throw new java.lang.UnsupportedOperationException("Fields of " + MailboxACLRights.class.getName() + " are read only.");
+ throw new UnsupportedOperationException("Fields of " + MailboxACLRights.class.getName() + " are read only.");
}
}
@@ -579,7 +346,6 @@ public class SimpleMailboxACL implements MailboxACL {
return new SimpleMailboxACLEntryKey(name, NameType.user, negative);
}
- private final int hash;
private final String name;
private final NameType nameType;
private final boolean negative;
@@ -592,109 +358,67 @@ public class SimpleMailboxACL implements MailboxACL {
*
* @param serialized
*/
- public SimpleMailboxACLEntryKey(String serialized) {
+ public static SimpleMailboxACLEntryKey deserialize(String serialized) {
+ Preconditions.checkNotNull(serialized, "Cannot parse null");
+ Preconditions.checkArgument(!serialized.isEmpty(), "Cannot parse an empty string");
- if (serialized == null) {
- throw new IllegalStateException("Cannot parse null to a " + getClass().getName());
- }
- if (serialized.length() == 0) {
- throw new IllegalStateException("Cannot parse an empty string to a " + getClass().getName());
- }
- int start = 0;
- if (serialized.charAt(start) == DEFAULT_NEGATIVE_MARKER) {
- negative = true;
- start++;
- } else {
- negative = false;
- }
- if (serialized.charAt(start) == DEFAULT_GROUP_MARKER) {
- nameType = NameType.group;
- start++;
- name = serialized.substring(start);
- if (name.length() == 0) {
- throw new IllegalStateException("Cannot parse a string with empty name to a " + getClass().getName());
- }
- } else {
- name = serialized.substring(start);
- if (name.length() == 0) {
- throw new IllegalStateException("Cannot parse a string with empty name to a " + getClass().getName());
- }
- NameType nt = NameType.user;
- for (SpecialName specialName : SpecialName.values()) {
- if (specialName.name().equals(name)) {
- nt = NameType.special;
- break;
- }
- }
- this.nameType = nt;
+ boolean negative = serialized.charAt(0) == DEFAULT_NEGATIVE_MARKER;
+ int nameStart = negative ? 1 : 0;
+ boolean isGroup = serialized.charAt(nameStart) == DEFAULT_GROUP_MARKER;
+ Optional<NameType> explicitNameType = isGroup ? Optional.of(NameType.group) : Optional.empty();
+ String name = isGroup ? serialized.substring(nameStart + 1) : serialized.substring(nameStart);
+
+ if (name.isEmpty()) {
+ throw new IllegalStateException("Cannot parse a string with empty name");
}
+ NameType nameType = explicitNameType.orElseGet(() -> computeImplicitNameType(name));
- this.hash = hash();
+ return new SimpleMailboxACLEntryKey(name, nameType, negative);
+ }
+ private static NameType computeImplicitNameType(String name) {
+ boolean isSpecialName = Arrays.stream(SpecialName.values())
+ .anyMatch(specialName -> specialName.name().equals(name));
+ if (isSpecialName) {
+ return NameType.special;
+ }
+ return NameType.user;
}
public SimpleMailboxACLEntryKey(String name, NameType nameType, boolean negative) {
- super();
- if (name == null) {
- throw new NullPointerException("Provide a name for this " + getClass().getName());
- }
- if (nameType == null) {
- throw new NullPointerException("Provide a nameType for this " + getClass().getName());
- }
+ Preconditions.checkNotNull(name, "Provide a name for this " + getClass().getName());
+ Preconditions.checkNotNull(nameType, "Provide a nameType for this " + getClass().getName());
+
this.name = name;
this.nameType = nameType;
this.negative = negative;
- this.hash = hash();
}
@Override
public boolean equals(Object o) {
if (o instanceof MailboxACLEntryKey) {
MailboxACLEntryKey other = (MailboxACLEntryKey) o;
- return this.name.equals(other.getName()) && this.nameType.equals(other.getNameType()) && this.negative == other.isNegative();
- } else {
- return false;
+ return Objects.equals(this.name, other.getName())
+ && Objects.equals(this.nameType, other.getNameType())
+ && Objects.equals(this.negative, other.isNegative());
}
+ return false;
}
- /*
- * (non-Javadoc)
- *
- * @see org.apache.james.mailbox.MailboxACL.MailboxACLEntryKey#getName()
- */
+
public String getName() {
return name;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLEntryKey#getNameType()
- */
public NameType getNameType() {
return nameType;
}
- private int hash() {
- final int PRIME = 31;
- int hash = negative ? 1 : 0;
- hash = PRIME * hash + nameType.hashCode();
- hash = PRIME * hash + name.hashCode();
- return hash;
- }
-
@Override
- public int hashCode() {
- return hash;
+ public final int hashCode() {
+ return Objects.hash(negative, nameType, name);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.james.mailbox.MailboxACL.MailboxACLEntryKey#isNegative()
- */
public boolean isNegative() {
return negative;
}
@@ -708,94 +432,18 @@ public class SimpleMailboxACL implements MailboxACL {
*/
@Override
public String serialize() {
- if (!negative) {
- switch (nameType) {
- case special:
- case user:
- return name;
- case group:
- return new StringBuilder(name.length() + 1).append(DEFAULT_GROUP_MARKER).append(name).toString();
- default:
- throw new IllegalStateException();
- }
- } else {
- StringBuilder result = new StringBuilder(name.length() + 2).append(DEFAULT_NEGATIVE_MARKER);
- switch (nameType) {
- case special:
- case user:
- break;
- case group:
- result.append(DEFAULT_GROUP_MARKER);
- break;
- default:
- throw new IllegalStateException();
- }
- return result.append(name).toString();
- }
+ String negativePart = negative ? String.valueOf(DEFAULT_NEGATIVE_MARKER) : "";
+ String nameTypePart = nameType == NameType.group ? String.valueOf(DEFAULT_GROUP_MARKER) : "";
+
+ return negativePart + nameTypePart + name;
}
@Override
public String toString() {
return serialize();
}
-
}
- /**
- * Default implementation of {@link MailboxACLRight}.
- */
- public static final class SimpleMailboxACLRight implements MailboxACLRight {
- private final char value;
-
- public SimpleMailboxACLRight(char value) {
- super();
- this.value = value;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object o) {
- if (o instanceof MailboxACLRight) {
- return ((MailboxACLRight) o).getValue() == this.value;
- }
- return false;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.apache.james.mailbox.MailboxACL.MailboxACLRight#getValue()
- */
- @Override
- public char getValue() {
- return value;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return (int) value;
- }
-
- /**
- * Returns <code>String.valueOf(value)</code>.
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return String.valueOf(value);
- }
-
- }
public static class SimpleMailboxACLCommand implements MailboxACLCommand {
private final MailboxACLEntryKey key;
@@ -824,24 +472,20 @@ public class SimpleMailboxACL implements MailboxACL {
}
@Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof SimpleMailboxACLCommand)) return false;
-
- SimpleMailboxACLCommand that = (SimpleMailboxACLCommand) o;
-
- if (key != null ? !key.equals(that.key) : that.key != null) return false;
- if (editMode != that.editMode) return false;
- return !(rights != null ? !rights.equals(that.rights) : that.rights != null);
+ public final boolean equals(Object o) {
+ if (o instanceof SimpleMailboxACLCommand) {
+ SimpleMailboxACLCommand that = (SimpleMailboxACLCommand) o;
+ return Objects.equals(this.key, that.key)
+ && Objects.equals(this.editMode, that.editMode)
+ && Objects.equals(this.rights, that.rights);
+ }
+ return false;
}
@Override
- public int hashCode() {
- int result = key != null ? key.hashCode() : 0;
- result = 31 * result + (editMode != null ? editMode.hashCode() : 0);
- result = 31 * result + (rights != null ? rights.hashCode() : 0);
- return result;
+ public final int hashCode() {
+ return Objects.hash(key, editMode, rights);
}
}
@@ -867,16 +511,24 @@ public class SimpleMailboxACL implements MailboxACL {
AUTHENTICATED_KEY = new SimpleMailboxACLEntryKey(SpecialName.authenticated.name(), NameType.special, false);
AUTHENTICATED_NEGATIVE_KEY = new SimpleMailboxACLEntryKey(SpecialName.authenticated.name(), NameType.special, true);
EMPTY = new SimpleMailboxACL();
- FULL_RIGHTS = new Rfc4314Rights(true, true, true, true, true, true, true, true, true, true, true);
+ FULL_RIGHTS = new Rfc4314Rights(Right.allRights);
NO_RIGHTS = new Rfc4314Rights();
OWNER_KEY = new SimpleMailboxACLEntryKey(SpecialName.owner.name(), NameType.special, false);
OWNER_NEGATIVE_KEY = new SimpleMailboxACLEntryKey(SpecialName.owner.name(), NameType.special, true);
OWNER_FULL_ACL = new SimpleMailboxACL(new SimpleMailboxACL.SimpleMailboxACLEntry[] { new SimpleMailboxACL.SimpleMailboxACLEntry(SimpleMailboxACL.OWNER_KEY, SimpleMailboxACL.FULL_RIGHTS) });
- OWNER_FULL_EXCEPT_ADMINISTRATION_ACL = new SimpleMailboxACL(new SimpleMailboxACL.SimpleMailboxACLEntry[] { new SimpleMailboxACL.SimpleMailboxACLEntry(SimpleMailboxACL.OWNER_KEY, SimpleMailboxACL.FULL_RIGHTS.except(new Rfc4314Rights(Rfc4314Rights.a_Administer_MASK))) });
+ OWNER_FULL_EXCEPT_ADMINISTRATION_ACL = new SimpleMailboxACL(new SimpleMailboxACL.SimpleMailboxACLEntry[] { new SimpleMailboxACL.SimpleMailboxACLEntry(SimpleMailboxACL.OWNER_KEY, SimpleMailboxACL.FULL_RIGHTS.except(new Rfc4314Rights(Right.Administer))) });
} catch (UnsupportedRightException e) {
throw new RuntimeException(e);
}
}
+
+ private static Map<MailboxACLEntryKey, MailboxACLRights> toMap(Properties props) throws UnsupportedRightException {
+ ImmutableMap.Builder<MailboxACLEntryKey, MailboxACLRights> builder = ImmutableMap.builder();
+ for (Entry<Object, Object> prop : props.entrySet()) {
+ builder.put(SimpleMailboxACLEntryKey.deserialize((String) prop.getKey()), new Rfc4314Rights((String) prop.getValue()));
+ }
+ return builder.build();
+ }
private final Map<MailboxACLEntryKey, MailboxACLRights> entries;
@@ -885,7 +537,7 @@ public class SimpleMailboxACL implements MailboxACL {
*
*/
public SimpleMailboxACL() {
- this.entries = Collections.emptyMap();
+ this(ImmutableMap.of());
}
/**
@@ -894,47 +546,24 @@ public class SimpleMailboxACL implements MailboxACL {
*
* @param entries
*/
- public SimpleMailboxACL(Map.Entry<MailboxACLEntryKey, MailboxACLRights>[] entries) {
- if (entries != null) {
- Map<MailboxACLEntryKey, MailboxACLRights> m = new HashMap<>(entries.length + entries.length / 2 + 1);
- for (Entry<MailboxACLEntryKey, MailboxACLRights> en : entries) {
- m.put(en.getKey(), en.getValue());
- }
- this.entries = Collections.unmodifiableMap(m);
- } else {
- this.entries = Collections.emptyMap();
- }
+ public SimpleMailboxACL(Map.Entry<MailboxACLEntryKey, MailboxACLRights>... entries) {
+ this(ImmutableMap.copyOf(
+ Optional.ofNullable(entries)
+ .map(array -> Arrays.stream(array)
+ .collect(Guavate.toImmutableMap(Entry::getKey, Entry::getValue)))
+ .orElse(ImmutableMap.of())));
}
/**
* Creates a new instance of SimpleMailboxACL from the given {@link Map} of
* entries.
- *
+ *
* @param entries
*/
public SimpleMailboxACL(Map<MailboxACLEntryKey, MailboxACLRights> entries) {
- if (entries != null && entries.size() > 0) {
- Map<MailboxACLEntryKey, MailboxACLRights> m = new HashMap<>(entries.size() + entries.size() / 2 + 1);
- for (Entry<MailboxACLEntryKey, MailboxACLRights> en : entries.entrySet()) {
- m.put(en.getKey(), en.getValue());
- }
- this.entries = Collections.unmodifiableMap(m);
- } else {
- this.entries = Collections.emptyMap();
- }
- }
+ Preconditions.checkNotNull(entries);
- /**
- * Creates a new instance of SimpleMailboxACL.
- * <code>unmodifiableEntries</code> parameter is supposed to be umodifiable
- * already.
- *
- * @param unmodifiableEntries
- * @param dummy
- * just to be different from {@link #SimpleMailboxACL(Map)}.
- */
- private SimpleMailboxACL(Map<MailboxACLEntryKey, MailboxACLRights> unmodifiableEntries, boolean dummy) {
- this.entries = unmodifiableEntries;
+ this.entries = ImmutableMap.copyOf(entries);
}
/**
@@ -947,33 +576,24 @@ public class SimpleMailboxACL implements MailboxACL {
* @throws UnsupportedRightException
*/
public SimpleMailboxACL(Properties props) throws UnsupportedRightException {
- super();
-
- Map<MailboxACLEntryKey, MailboxACLRights> m = new HashMap<>(props.size() + props.size() / 2 + 1);
-
- if (props != null) {
- for (Map.Entry<Object, Object> prop : props.entrySet()) {
- m.put(new SimpleMailboxACLEntryKey((String) prop.getKey()), new Rfc4314Rights((String) prop.getValue()));
- }
- }
-
- entries = Collections.unmodifiableMap(m);
+ this(toMap(props));
}
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
@Override
public boolean equals(Object o) {
if (o instanceof MailboxACL) {
MailboxACL acl = (MailboxACL) o;
- Map<MailboxACLEntryKey, MailboxACLRights> ens = acl.getEntries();
- return entries == ens || (entries != null && entries.equals(ens));
+ return Objects.equals(this.getEntries(), acl.getEntries());
}
return false;
}
@Override
+ public int hashCode() {
+ return Objects.hash(entries);
+ }
+
+ @Override
public MailboxACL apply(MailboxACLCommand aclUpdate) throws UnsupportedRightException {
switch (aclUpdate.getEditMode()) {
case ADD:
@@ -986,144 +606,74 @@ public class SimpleMailboxACL implements MailboxACL {
throw new RuntimeException("Unknown edit mode");
}
- /**
- * @see org.apache.james.mailbox.MailboxACL#except(org.apache.james.mailbox.MailboxACL)
- */
@Override
public MailboxACL except(MailboxACL other) throws UnsupportedRightException {
- if (entries.size() == 0) {
- return this;
- } else {
- Map<MailboxACLEntryKey, MailboxACLRights> otherEntries = other.getEntries();
- Map<MailboxACLEntryKey, MailboxACLRights> resultEntries = new HashMap<>(this.entries);
- for (Entry<MailboxACLEntryKey, MailboxACLRights> otherEntry : otherEntries.entrySet()) {
- MailboxACLEntryKey key = otherEntry.getKey();
- MailboxACLRights thisRights = resultEntries.get(key);
- if (thisRights == null) {
- /* nothing to diff */
- } else {
- /* diff */
- MailboxACLRights resultRights = thisRights.except(otherEntry.getValue());
- if (!resultRights.isEmpty()) {
- resultEntries.put(key, resultRights);
- }
- else {
- resultEntries.remove(key);
- }
- }
- }
- return new SimpleMailboxACL(Collections.unmodifiableMap(resultEntries), true);
- }
+ return new SimpleMailboxACL(entries.entrySet()
+ .stream()
+ .map(entry -> Pair.of(entry.getKey(),
+ Optional.ofNullable(other.getEntries().get(entry.getKey()))
+ .map(Throwing.function(exceptValue -> entry.getValue().except(exceptValue)))
+ .orElse(entry.getValue())))
+ .filter(pair -> !pair.getValue().isEmpty())
+ .collect(Guavate.toImmutableMap(Entry::getKey, Entry::getValue)));
}
- /**
- * @see org.apache.james.mailbox.model.MailboxACL#except(org.apache.james.mailbox.model.MailboxACL.MailboxACLEntryKey, org.apache.james.mailbox.model.MailboxACL.MailboxACLRights)
- */
+ @Override
public MailboxACL except(MailboxACLEntryKey key, MailboxACLRights mailboxACLRights) throws UnsupportedRightException {
- Map<MailboxACLEntryKey, MailboxACLRights> resultEntries = new HashMap<>(this.entries);
- MailboxACLRights thisRights = resultEntries.get(key);
- if (thisRights == null) {
- /* nothing to diff */
- } else {
- /* diff */
- MailboxACLRights resultRights = thisRights.except(mailboxACLRights);
- if (!resultRights.isEmpty()) {
- resultEntries.put(key, resultRights);
- }
- else {
- resultEntries.remove(key);
- }
- }
- return new SimpleMailboxACL(Collections.unmodifiableMap(resultEntries), true);
+ return except(new SimpleMailboxACL(new SimpleMailboxACLEntry(key, mailboxACLRights)));
}
- /**
- * @see org.apache.james.mailbox.MailboxACL#getEntries()
- */
@Override
public Map<MailboxACLEntryKey, MailboxACLRights> getEntries() {
return entries;
}
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return entries == null ? 0 : entries.hashCode();
- }
-
- /**
- * @see org.apache.james.mailbox.model.MailboxACL#replace(org.apache.james.mailbox.model.MailboxACL.MailboxACLEntryKey, org.apache.james.mailbox.model.MailboxACL.MailboxACLRights)
- */
@Override
public MailboxACL replace(MailboxACLEntryKey key, MailboxACLRights replacement) throws UnsupportedRightException {
- Map<MailboxACLEntryKey, MailboxACLRights> resultEntries = new HashMap<>(this.entries);
- if (replacement == null || replacement.isEmpty()) {
- resultEntries.remove(key);
+ if (entries.containsKey(key)) {
+ return new SimpleMailboxACL(
+ entries.entrySet()
+ .stream()
+ .map(entry -> Pair.of(entry.getKey(),
+ entry.getKey().equals(key) ? replacement : entry.getValue()))
+ .filter(pair -> pair.getValue() != null && !pair.getValue().isEmpty())
+ .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)));
} else {
- resultEntries.put(key, replacement);
+ return new SimpleMailboxACL(
+ ImmutableMap.<MailboxACLEntryKey, MailboxACLRights>builder()
+ .putAll(entries)
+ .put(key, replacement)
+ .build());
}
- return new SimpleMailboxACL(Collections.unmodifiableMap(resultEntries), true);
}
- /**
- * @see java.lang.Object#toString()
- */
@Override
public String toString() {
return entries == null ? "" : entries.toString();
}
- /**
- * @see org.apache.james.mailbox.MailboxACL#union(org.apache.james.mailbox.MailboxACL)
- */
@Override
public MailboxACL union(MailboxACL other) throws UnsupportedRightException {
- Map<MailboxACLEntryKey, MailboxACLRights> otherEntries = other.getEntries();
- if (otherEntries.size() == 0) {
- return this;
- } else if (entries.size() == 0) {
- return other;
- } else {
- int cnt = otherEntries.size() + entries.size();
- Map<MailboxACLEntryKey, MailboxACLRights> resultEntries = new HashMap<>(cnt + cnt / 2 + 1);
- for (Entry<MailboxACLEntryKey, MailboxACLRights> otherEntry : otherEntries.entrySet()) {
- MailboxACLEntryKey key = otherEntry.getKey();
- MailboxACLRights thisRights = entries.get(key);
- if (thisRights == null) {
- /* nothing to union */
- resultEntries.put(key, otherEntry.getValue());
- } else {
- /* union */
- resultEntries.put(key, otherEntry.getValue().union(thisRights));
- }
- }
- /* let us check what we have missed in the previous loop */
- for (Entry<MailboxACLEntryKey, MailboxACLRights> thisEntry : entries.entrySet()) {
- MailboxACLEntryKey key = thisEntry.getKey();
- if (!resultEntries.containsKey(key)) {
- resultEntries.put(key, thisEntry.getValue());
- }
- }
- return new SimpleMailboxACL(Collections.unmodifiableMap(resultEntries), true);
- }
+ return new SimpleMailboxACL(
+ Stream.concat(
+ this.entries.entrySet().stream(),
+ other.getEntries().entrySet().stream())
+ .collect(Guavate.toImmutableListMultimap(Entry::getKey, Entry::getValue))
+ .asMap()
+ .entrySet()
+ .stream()
+ .map(entry -> Pair.of(entry.getKey(),
+ entry.getValue()
+ .stream()
+ .reduce(
+ new Rfc4314Rights(),
+ Throwing.binaryOperator(MailboxACLRights::union))))
+ .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)));
}
- /**
- * @see org.apache.james.mailbox.model.MailboxACL#union(org.apache.james.mailbox.model.MailboxACL.MailboxACLEntryKey, org.apache.james.mailbox.model.MailboxACL.MailboxACLRights)
- */
+ @Override
public MailboxACL union(MailboxACLEntryKey key, MailboxACLRights mailboxACLRights) throws UnsupportedRightException {
- Map<MailboxACLEntryKey, MailboxACLRights> resultEntries = new HashMap<>(this.entries);
- MailboxACLRights thisRights = resultEntries.get(key);
- if (thisRights == null) {
- /* nothing to union */
- resultEntries.put(key, mailboxACLRights);
- } else {
- /* union */
- resultEntries.put(key, thisRights.union(mailboxACLRights));
- }
- return new SimpleMailboxACL(Collections.unmodifiableMap(resultEntries), true);
+ return union(new SimpleMailboxACL(new SimpleMailboxACLEntry(key, mailboxACLRights)));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org