Index: mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java
===================================================================
--- mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java (revision 1242500)
+++ mailbox/api/src/main/java/org/apache/james/mailbox/MessageManager.java (working copy)
@@ -61,11 +61,12 @@
*
* @param session
* @return writable
+ * @throws MailboxException
* @deprecated use
* {@link #getMetaData(boolean, MailboxSession, org.apache.james.mailbox.MessageManager.MetaData.FetchGroup)}
*/
@Deprecated
- boolean isWriteable(MailboxSession session);
+ boolean isWriteable(MailboxSession session) throws MailboxException;
/**
* Return true if {@link MessageResult#getModSeq()} is stored in a permanent
Index: mailbox/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java
===================================================================
--- mailbox/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java (revision 1242500)
+++ mailbox/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java (working copy)
@@ -20,6 +20,8 @@
package org.apache.james.mailbox.acl;
+import javax.mail.Flags;
+
import org.apache.james.mailbox.exception.UnsupportedRightException;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxACL.MailboxACLRight;
@@ -110,4 +112,43 @@
*/
public abstract MailboxACLRights listRights(String requestUser, GroupMembershipResolver groupMembershipResolver, MailboxACL resourceACL, String resourceOwner, boolean resourceOwnerIsGroup) throws UnsupportedRightException;
+ /**
+ * Maps the given {@code mailboxACLRights} to READ-WRITE and READ-ONLY
+ * response codes.
+ *
+ * From RFC 4314 section 5.2:
+ *
+ * The server SHOULD include a READ-WRITE response code in the tagged OK
+ * response if at least one of the "i", "e", or "shared flag rights"(***) is
+ * granted to the current user.
+ *
+ * The server MUST include a READ-ONLY response code in the tagged OK
+ * response to a SELECT command if none of the following rights is granted
+ * to the current user: "i", "e", and "shared flag rights"(***).
+ *
+ * @param mailboxACLRights
+ * the rights applicable to the user and resource in question.
+ * This method supposes that any global ACLs were already applied
+ * to the {@code mailboxACLRights} parameter before this method
+ * is called.
+ * @param sharedFlags
+ * From RFC 4314 section 5.2: If the ACL server implements some
+ * flags as shared for a mailbox (i.e., the ACL for the mailbox
+ * MAY be set up so that changes to those flags are visible to
+ * another user), let’s call the set of rights associated with
+ * these flags (as described in Section 4) for that mailbox
+ * collectively as "shared flag rights". Note that the
+ * "shared flag rights" set MAY be different for different
+ * mailboxes.
+ *
+ * If the server doesn’t support "shared multiuser write access"
+ * to a mailbox or doesn’t implement shared flags on the mailbox,
+ * "shared flag rights" for the mailbox is defined to be the
+ * empty set.
+ *
+ * @return
+ * @throws UnsupportedRightException
+ */
+ public abstract boolean isReadWrite(MailboxACLRights mailboxACLRights, Flags sharedFlags) throws UnsupportedRightException;
+
}
Index: mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
===================================================================
--- mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java (revision 1242500)
+++ mailbox/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java (working copy)
@@ -24,6 +24,9 @@
import java.util.Map;
import java.util.Map.Entry;
+import javax.mail.Flags;
+import javax.mail.Flags.Flag;
+
import org.apache.james.mailbox.exception.UnsupportedRightException;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.SimpleMailboxACL;
@@ -31,6 +34,7 @@
import org.apache.james.mailbox.model.MailboxACL.MailboxACLRight;
import org.apache.james.mailbox.model.MailboxACL.MailboxACLRights;
import org.apache.james.mailbox.model.MailboxACL.NameType;
+import org.apache.james.mailbox.model.SimpleMailboxACL.Rfc4314Rights;
import com.sun.mail.mbox.Mailbox;
@@ -44,7 +48,7 @@
* the result is computed afterwards with
* nonNegativeUnion.except(negativeUnion).
*
- * Allows for setting dictinct global ACL for users' mailboxes on one hand and
+ * Allows for setting distinct global ACL for users' mailboxes on one hand and
* group (a.k.a shared) mailboxes on the other hand. E.g. the zero parameter
* constructor uses full rights for user mailboxes and
* full-except-administration rights for group mailboxes.
@@ -140,9 +144,7 @@
return false;
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.MailboxACLResolver#applyGlobalACL(org.apache
* .james.mailbox.MailboxACL, boolean)
@@ -152,9 +154,7 @@
return resourceOwnerIsGroup ? resourceACL.union(groupGlobalACL) : resourceACL.union(userGlobalACL);
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.store.mail.MailboxACLResolver#hasRight(java.
* lang.String, org.apache.james.mailbox.store.mail.MailboxACLResolver.
@@ -200,9 +200,41 @@
return result;
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * @see org.apache.james.mailbox.acl.MailboxACLResolver#isReadWrite(org.apache.james.mailbox.model.MailboxACL.MailboxACLRights, javax.mail.Flags)
+ */
+ @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)) {
+ return true;
+ }
+ /*
+ * then go through shared flags. RFC 4314 section 4:
+ *
+ * Changing flags: STORE
+ *
+ * - the server MUST check if the user has "t" right
+ *
+ * - when the user modifies \Deleted flag "s" right
+ *
+ * - when the user modifies \Seen flag "w" right - for all other message flags.
+ *
+ */
+ else if (sharedFlags != null) {
+ if (sharedFlags.contains(Flag.DELETED) && mailboxACLRights.contains(Rfc4314Rights.t_DeleteMessages_RIGHT)) {
+ return true;
+ } else if (sharedFlags.contains(Flag.SEEN) && mailboxACLRights.contains(Rfc4314Rights.s_WriteSeenFlag_RIGHT)) {
+ return true;
+ } else {
+ boolean hasWriteRight = mailboxACLRights.contains(Rfc4314Rights.w_Write_RIGHT);
+ return hasWriteRight && (sharedFlags.contains(Flag.ANSWERED) || sharedFlags.contains(Flag.DRAFT) || sharedFlags.contains(Flag.FLAGGED) || sharedFlags.contains(Flag.RECENT) || sharedFlags.contains(Flag.USER));
+ }
+ }
+ return false;
+ }
+
+ /**
* @see
* org.apache.james.mailbox.store.mail.MailboxACLResolver#rightsOf(java.
* lang.String, org.apache.james.mailbox.store.mail.MailboxACLResolver.
Index: mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
===================================================================
--- mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java (revision 1242500)
+++ mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java (working copy)
@@ -133,7 +133,7 @@
boolean isSupported(MailboxACLRight right);
/**
- * Tells whether this conatins the given right.
+ * Tells whether this contains the given right.
*
* @param right
* @return
@@ -141,7 +141,7 @@
* iff the given right is not supported.
*/
boolean contains(MailboxACLRight right) throws UnsupportedRightException;
-
+
/**
* Performs the set theoretic operation of relative complement of
* toRemove MailboxACLRights in this MailboxACLRights.
Index: mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
===================================================================
--- mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java (revision 1242500)
+++ mailbox/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java (working copy)
@@ -354,9 +354,7 @@
}
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.MailboxACL.MailboxACLRights#contains(org
* .apache.james.mailbox.MailboxACL.MailboxACLRight)
@@ -381,9 +379,7 @@
}
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.MailboxACL.MailboxACLRights#except(org.apache
* .james.mailbox.MailboxACL.MailboxACLRights)
Index: mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
===================================================================
--- mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java (revision 1242500)
+++ mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java (working copy)
@@ -45,17 +45,20 @@
import org.apache.james.mailbox.MessageManager;
import org.apache.james.mailbox.acl.GroupMembershipResolver;
import org.apache.james.mailbox.acl.MailboxACLResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.exception.ReadOnlyException;
import org.apache.james.mailbox.exception.UnsupportedRightException;
import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxACL.MailboxACLRight;
+import org.apache.james.mailbox.model.MailboxACL.MailboxACLRights;
import org.apache.james.mailbox.model.MessageMetaData;
import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.MessageResult.FetchGroup;
import org.apache.james.mailbox.model.MessageResultIterator;
import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.SimpleMailboxACL;
import org.apache.james.mailbox.model.UpdatedFlags;
-import org.apache.james.mailbox.model.MailboxACL.MailboxACLRight;
-import org.apache.james.mailbox.model.MessageResult.FetchGroup;
import org.apache.james.mailbox.store.mail.MessageMapper;
import org.apache.james.mailbox.store.mail.MessageMapper.FetchType;
import org.apache.james.mailbox.store.mail.MessageMapperFactory;
@@ -77,20 +80,23 @@
import org.apache.james.mime4j.stream.RecursionMode;
/**
- * Base class for {@link org.apache.james.mailbox.MessageManager} implementations.
+ * Base class for {@link org.apache.james.mailbox.MessageManager}
+ * implementations.
*
- * This base class take care of dispatching events to the registered {@link MailboxListener} and so help
- * with handling concurrent {@link MailboxSession}'s.
+ * This base class take care of dispatching events to the registered
+ * {@link MailboxListener} and so help with handling concurrent
+ * {@link MailboxSession}'s.
*
*
- *
+ *
*/
-public class StoreMessageManager implements org.apache.james.mailbox.MessageManager{
+public class StoreMessageManager implements org.apache.james.mailbox.MessageManager {
/**
* The minimal Permanent flags the {@link MessageManager} must support.
*
- * Be sure this static instance will never get modifed later!
+ * Be sure this static instance will never get modifed
+ * later!
*/
protected final static Flags MINIMAL_PERMANET_FLAGS;
static {
@@ -103,22 +109,23 @@
}
private final Mailbox mailbox;
-
- private final MailboxEventDispatcher dispatcher;
-
+
+ private final MailboxEventDispatcher dispatcher;
+
private final MessageMapperFactory mapperFactory;
private final MessageSearchIndex index;
-
+
private final MailboxACLResolver aclResolver;
-
+
private final GroupMembershipResolver groupMembershipResolver;
- private MailboxPathLocker locker;
+ private MailboxPathLocker locker;
private int fetchBatchSize;
-
- public StoreMessageManager(final MessageMapperFactory mapperFactory, final MessageSearchIndex index, final MailboxEventDispatcher dispatcher, final MailboxPathLocker locker, final Mailbox mailbox, final MailboxACLResolver aclResolver, final GroupMembershipResolver groupMembershipResolver) throws MailboxException {
+
+ public StoreMessageManager(final MessageMapperFactory mapperFactory, final MessageSearchIndex index, final MailboxEventDispatcher dispatcher, final MailboxPathLocker locker, final Mailbox mailbox, final MailboxACLResolver aclResolver,
+ final GroupMembershipResolver groupMembershipResolver) throws MailboxException {
this.mailbox = mailbox;
this.dispatcher = dispatcher;
this.mapperFactory = mapperFactory;
@@ -127,12 +134,11 @@
this.aclResolver = aclResolver;
this.groupMembershipResolver = groupMembershipResolver;
}
-
+
public void setFetchBatchSize(int fetchBatchSize) {
this.fetchBatchSize = fetchBatchSize;
}
-
-
+
/**
* Return the {@link MailboxPathLocker}
*
@@ -141,7 +147,7 @@
protected MailboxPathLocker getLocker() {
return locker;
}
-
+
/**
* Return the {@link MailboxEventDispatcher} for this Mailbox
*
@@ -150,18 +156,17 @@
protected MailboxEventDispatcher getDispatcher() {
return dispatcher;
}
-
+
/**
* Return the underlying {@link Mailbox}
*
* @return mailbox
* @throws MailboxException
*/
-
+
public Mailbox getMailboxEntity() throws MailboxException {
return mailbox;
}
-
/**
* Return {@link Flags} which are permanent stored by the mailbox. By
@@ -188,12 +193,26 @@
return new Flags(MINIMAL_PERMANET_FLAGS);
}
-
-
+ /**
+ * Returns the flags which are shared for the current mailbox, i.e. the
+ * flags set up so that changes to those flags are visible to another user.
+ * See RFC 4314 section 5.2.
+ *
+ * In this implementation, all permanent flags are shared, ergo we simply
+ * return {@link #getPermanentFlags(MailboxSession)}
+ *
+ * @see UnionMailboxACLResolver#isReadWrite(MailboxACLRights, Flags)
+ *
+ * @param session
+ * @return
+ */
+ protected Flags getSharedPermanentFlags(MailboxSession session) {
+ return getPermanentFlags(session);
+ }
/**
- * Return true. If an subclass don't want to store mod-sequences in a permanent way just override this
- * and return false
+ * Return true. If an subclass don't want to store mod-sequences in a
+ * permanent way just override this and return false
*
* @return true
*/
@@ -202,60 +221,61 @@
}
/**
- * @see org.apache.james.mailbox.MessageManager#expunge(org.apache.james.mailbox.model.MessageRange, org.apache.james.mailbox.MailboxSession)
+ * @see org.apache.james.mailbox.MessageManager#expunge(org.apache.james.mailbox.model.MessageRange,
+ * org.apache.james.mailbox.MailboxSession)
*/
public Iterator expunge(final MessageRange set, MailboxSession mailboxSession) throws MailboxException {
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
Map uids = deleteMarkedInMailbox(set, mailboxSession);
-
+
dispatcher.expunged(mailboxSession, uids, getMailboxEntity());
- return uids.keySet().iterator();
+ return uids.keySet().iterator();
}
/**
- * @see org.apache.james.mailbox.MessageManager#appendMessage(java.io.InputStream, java.util.Date, org.apache.james.mailbox.MailboxSession, boolean, javax.mail.Flags)
+ * @see org.apache.james.mailbox.MessageManager#appendMessage(java.io.InputStream,
+ * java.util.Date, org.apache.james.mailbox.MailboxSession, boolean,
+ * javax.mail.Flags)
*/
- public long appendMessage(final InputStream msgIn, Date internalDate,
- final MailboxSession mailboxSession, final boolean isRecent, final Flags flagsToBeSet)
- throws MailboxException {
-
+ public long appendMessage(final InputStream msgIn, Date internalDate, final MailboxSession mailboxSession, final boolean isRecent, final Flags flagsToBeSet) throws MailboxException {
+
File file = null;
TeeInputStream tmpMsgIn = null;
BodyOffsetInputStream bIn = null;
FileOutputStream out = null;
SharedFileInputStream contentIn = null;
-
+
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
-
+
try {
- // Create a temporary file and copy the message to it. We will work with the file as
+ // Create a temporary file and copy the message to it. We will work
+ // with the file as
// source for the InputStream
file = File.createTempFile("imap", ".msg");
out = new FileOutputStream(file);
-
+
tmpMsgIn = new TeeInputStream(msgIn, out);
-
+
bIn = new BodyOffsetInputStream(tmpMsgIn);
- // Disable line length... This should be handled by the smtp server component and not the parser itself
+ // Disable line length... This should be handled by the smtp server
+ // component and not the parser itself
// https://issues.apache.org/jira/browse/IMAP-122
MimeConfig config = new MimeConfig();
config.setMaxLineLen(-1);
config.setMaxHeaderLen(-1);
final MimeTokenStream parser = new MimeTokenStream(config, new DefaultBodyDescriptorBuilder());
-
+
parser.setRecursionMode(RecursionMode.M_NO_RECURSE);
parser.parse(bIn);
final HeaderImpl header = new HeaderImpl();
-
+
EntityState next = parser.next();
- while (next != EntityState.T_BODY
- && next != EntityState.T_END_OF_STREAM
- && next != EntityState.T_START_MULTIPART) {
+ while (next != EntityState.T_BODY && next != EntityState.T_END_OF_STREAM && next != EntityState.T_START_MULTIPART) {
if (next == EntityState.T_FIELD) {
header.addField(parser.getField());
}
@@ -293,27 +313,27 @@
} else {
propertyBuilder.setCharset(codeset);
}
-
+
final String boundary = descriptor.getBoundary();
if (boundary != null) {
propertyBuilder.setBoundary(boundary);
- }
+ }
if ("text".equalsIgnoreCase(mediaType)) {
final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream());
bodyStream.readAll();
long lines = bodyStream.getLineCount();
bodyStream.close();
next = parser.next();
- if (next == EntityState.T_EPILOGUE) {
+ if (next == EntityState.T_EPILOGUE) {
final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream());
epilogueStream.readAll();
- lines+=epilogueStream.getLineCount();
+ lines += epilogueStream.getLineCount();
epilogueStream.close();
}
propertyBuilder.setTextualLineCount(lines);
}
-
+
final Flags flags;
if (flagsToBeSet == null) {
flags = new Flags();
@@ -331,8 +351,9 @@
internalDate = new Date();
}
byte[] discard = new byte[4096];
- while(tmpMsgIn.read(discard) != -1) {
- // consume the rest of the stream so everything get copied to the file now
+ while (tmpMsgIn.read(discard) != -1) {
+ // consume the rest of the stream so everything get copied to
+ // the file now
// via the TeeInputStream
}
int bodyStartOctet = (int) bIn.getBodyStartOffset();
@@ -348,14 +369,14 @@
@Override
public Long execute() throws MailboxException {
MessageMetaData data = appendMessageToStore(message, mailboxSession);
-
+
SortedMap uids = new TreeMap();
uids.put(data.getUid(), data);
dispatcher.added(mailboxSession, uids, getMailboxEntity());
return data.getUid();
}
}, true);
-
+
} catch (IOException e) {
throw new MailboxException("Unable to parse message", e);
} catch (MimeException e) {
@@ -369,7 +390,8 @@
// delete the temporary file if one was specified
if (file != null) {
if (!file.delete()) {
- // Don't throw an IOException. The message could be appended and the temporary file
+ // Don't throw an IOException. The message could be appended
+ // and the temporary file
// will be deleted hopefully some day
}
}
@@ -377,7 +399,6 @@
}
-
/**
* Create a new {@link Message} for the given data
*
@@ -387,76 +408,78 @@
* @param content
* @param flags
* @return membership
- * @throws MailboxException
+ * @throws MailboxException
*/
- protected Message createMessage(Date internalDate, final int size, int bodyStartOctet,
- final SharedInputStream content, final Flags flags, final PropertyBuilder propertyBuilder) throws MailboxException {
+ protected Message createMessage(Date internalDate, final int size, int bodyStartOctet, final SharedInputStream content, final Flags flags, final PropertyBuilder propertyBuilder) throws MailboxException {
return new SimpleMessage(internalDate, size, bodyStartOctet, content, flags, propertyBuilder, getMailboxEntity().getMailboxId());
}
-
+
/**
* This mailbox is writable
+ *
+ * @throws MailboxException
*/
- public boolean isWriteable(MailboxSession session) {
- return true;
+ public boolean isWriteable(MailboxSession session) throws MailboxException {
+ return aclResolver.isReadWrite(myRights(session), getSharedPermanentFlags(session));
}
-
-
+
/**
- * @see MessageManager#getMetaData(boolean, MailboxSession, org.apache.james.mailbox.MessageManager.MetaData.FetchGroup)
+ * @see MessageManager#getMetaData(boolean, MailboxSession,
+ * org.apache.james.mailbox.MessageManager.MetaData.FetchGroup)
*/
- public MetaData getMetaData(boolean resetRecent, MailboxSession mailboxSession,
- org.apache.james.mailbox.MessageManager.MetaData.FetchGroup fetchGroup) throws MailboxException {
-
+ public MetaData getMetaData(boolean resetRecent, MailboxSession mailboxSession, org.apache.james.mailbox.MessageManager.MetaData.FetchGroup fetchGroup) throws MailboxException {
+
final List recent;
final Flags permanentFlags = getPermanentFlags(mailboxSession);
final long uidValidity = getMailboxEntity().getUidValidity();
- final long uidNext = mapperFactory.getMessageMapper(mailboxSession).getLastUid(mailbox) +1;
- final long highestModSeq = mapperFactory.getMessageMapper(mailboxSession).getHighestModSeq(mailbox);
- final long messageCount;
+ final long uidNext = mapperFactory.getMessageMapper(mailboxSession).getLastUid(mailbox) + 1;
+ final long highestModSeq = mapperFactory.getMessageMapper(mailboxSession).getHighestModSeq(mailbox);
+ final long messageCount;
final long unseenCount;
final Long firstUnseen;
switch (fetchGroup) {
- case UNSEEN_COUNT:
- unseenCount = countUnseenMessagesInMailbox(mailboxSession);
- messageCount = getMessageCount(mailboxSession);
- firstUnseen = null;
- recent = recent(resetRecent, mailboxSession);
+ case UNSEEN_COUNT:
+ unseenCount = countUnseenMessagesInMailbox(mailboxSession);
+ messageCount = getMessageCount(mailboxSession);
+ firstUnseen = null;
+ recent = recent(resetRecent, mailboxSession);
- break;
- case FIRST_UNSEEN:
- firstUnseen = findFirstUnseenMessageUid(mailboxSession);
- messageCount = getMessageCount(mailboxSession);
- unseenCount = 0;
- recent = recent(resetRecent, mailboxSession);
+ break;
+ case FIRST_UNSEEN:
+ firstUnseen = findFirstUnseenMessageUid(mailboxSession);
+ messageCount = getMessageCount(mailboxSession);
+ unseenCount = 0;
+ recent = recent(resetRecent, mailboxSession);
- break;
- case NO_UNSEEN:
- firstUnseen = null;
- unseenCount = 0;
- messageCount = getMessageCount(mailboxSession);
- recent = recent(resetRecent, mailboxSession);
+ break;
+ case NO_UNSEEN:
+ firstUnseen = null;
+ unseenCount = 0;
+ messageCount = getMessageCount(mailboxSession);
+ recent = recent(resetRecent, mailboxSession);
- break;
- default:
- firstUnseen = null;
- unseenCount = 0;
- messageCount = -1;
- // just reset the recent but not include them in the metadata
- if (resetRecent) {
- recent(resetRecent, mailboxSession);
- }
- recent = new ArrayList();
- break;
+ break;
+ default:
+ firstUnseen = null;
+ unseenCount = 0;
+ messageCount = -1;
+ // just reset the recent but not include them in the metadata
+ if (resetRecent) {
+ recent(resetRecent, mailboxSession);
+ }
+ recent = new ArrayList();
+ break;
}
- MailboxACL resolvedAcl = aclResolver.applyGlobalACL(mailbox.getACL(), isGroupFolder(mailboxSession) );
- return new MailboxMetaData(recent, permanentFlags, uidValidity, uidNext,highestModSeq, messageCount, unseenCount, firstUnseen, isWriteable(mailboxSession), isModSeqPermanent(mailboxSession), resolvedAcl );
+ MailboxACL resolvedAcl = getResolvedMailboxACL(mailboxSession);
+ return new MailboxMetaData(recent, permanentFlags, uidValidity, uidNext, highestModSeq, messageCount, unseenCount, firstUnseen, isWriteable(mailboxSession), isModSeqPermanent(mailboxSession), resolvedAcl);
}
-
/**
- * Check if the given {@link Flags} contains {@link Flags} which are not included in the returned {@link Flags} of {@link #getPermanentFlags(MailboxSession)}.
- * If any are found, these are removed from the given {@link Flags} instance. The only exception is the {@link Flag#RECENT} flag.
+ * Check if the given {@link Flags} contains {@link Flags} which are not
+ * included in the returned {@link Flags} of
+ * {@link #getPermanentFlags(MailboxSession)}. If any are found, these are
+ * removed from the given {@link Flags} instance. The only exception is the
+ * {@link Flag#RECENT} flag.
*
* This flag is never removed!
*
@@ -464,52 +487,54 @@
* @param session
*/
private void trimFlags(Flags flags, MailboxSession session) {
-
+
Flags permFlags = getPermanentFlags(session);
-
+
Flag[] systemFlags = flags.getSystemFlags();
- for (int i = 0; i < systemFlags.length; i++) {
+ for (int i = 0; i < systemFlags.length; i++) {
Flag f = systemFlags[i];
-
+
if (f != Flag.RECENT && permFlags.contains(f) == false) {
flags.remove(f);
}
}
- // if the permFlags contains the special USER flag we can skip this as all user flags are allowed
+ // if the permFlags contains the special USER flag we can skip this as
+ // all user flags are allowed
if (permFlags.contains(Flags.Flag.USER) == false) {
String[] uFlags = flags.getUserFlags();
- for (int i = 0; i setFlags(final Flags flags, final boolean value, final boolean replace,
- final MessageRange set, MailboxSession mailboxSession) throws MailboxException {
-
+ public Map setFlags(final Flags flags, final boolean value, final boolean replace, final MessageRange set, MailboxSession mailboxSession) throws MailboxException {
+
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
final SortedMap newFlagsByUid = new TreeMap();
trimFlags(flags, mailboxSession);
-
+
final MessageMapper messageMapper = mapperFactory.getMessageMapper(mailboxSession);
-
+
Iterator it = messageMapper.execute(new Mapper.Transaction>() {
public Iterator run() throws MailboxException {
- return messageMapper.updateFlags(getMailboxEntity(),flags, value, replace, set);
+ return messageMapper.updateFlags(getMailboxEntity(), flags, value, replace, set);
}
});
-
+
final SortedMap uFlags = new TreeMap();
while (it.hasNext()) {
@@ -517,14 +542,12 @@
newFlagsByUid.put(flag.getUid(), flag.getNewFlags());
uFlags.put(flag.getUid(), flag);
}
-
+
dispatcher.flagsUpdated(mailboxSession, new ArrayList(uFlags.keySet()), getMailboxEntity(), new ArrayList(uFlags.values()));
return newFlagsByUid;
}
-
-
/**
* Copy the {@link MessageRange} to the {@link StoreMessageManager}
*
@@ -535,9 +558,9 @@
*/
public List copyTo(final MessageRange set, final StoreMessageManager toMailbox, final MailboxSession session) throws MailboxException {
if (!toMailbox.isWriteable(session)) {
- throw new ReadOnlyException(new StoreMailboxPath(toMailbox.getMailboxEntity()),session.getPathDelimiter());
+ throw new ReadOnlyException(new StoreMailboxPath(toMailbox.getMailboxEntity()), session.getPathDelimiter());
}
-
+
return locker.executeWithLock(session, new StoreMailboxPath(toMailbox.getMailboxEntity()), new MailboxPathLocker.LockAwareExecution>() {
@Override
@@ -548,7 +571,7 @@
}
}, true);
}
-
+
protected MessageMetaData appendMessageToStore(final Message message, MailboxSession session) throws MailboxException {
final MessageMapper mapper = mapperFactory.getMessageMapper(session);
return mapperFactory.getMessageMapper(session).execute(new Mapper.Transaction() {
@@ -556,7 +579,7 @@
public MessageMetaData run() throws MailboxException {
return mapper.add(getMailboxEntity(), message);
}
-
+
});
}
@@ -568,7 +591,9 @@
}
/**
- * @see org.apache.james.mailbox.MessageManager#getMessages(org.apache.james.mailbox.model.MessageRange, org.apache.james.mailbox.model.MessageResult.FetchGroup, org.apache.james.mailbox.MailboxSession)
+ * @see org.apache.james.mailbox.MessageManager#getMessages(org.apache.james.mailbox.model.MessageRange,
+ * org.apache.james.mailbox.model.MessageResult.FetchGroup,
+ * org.apache.james.mailbox.MailboxSession)
*/
public MessageResultIterator getMessages(final MessageRange set, FetchGroup fetchGroup, MailboxSession mailboxSession) throws MailboxException {
final MessageMapper messageMapper = mapperFactory.getMessageMapper(mailboxSession);
@@ -587,19 +612,20 @@
protected List recent(final boolean reset, MailboxSession mailboxSession) throws MailboxException {
if (reset) {
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new StoreMailboxPath(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
}
final MessageMapper messageMapper = mapperFactory.getMessageMapper(mailboxSession);
-
+
return messageMapper.execute(new Mapper.Transaction>() {
public List run() throws MailboxException {
final List members = messageMapper.findRecentMessageUidsInMailbox(getMailboxEntity());
- // Convert to MessageRanges so we may be able to optimize the flag update
+ // Convert to MessageRanges so we may be able to optimize the
+ // flag update
List ranges = MessageRange.toRanges(members);
- for (MessageRange range:ranges) {
+ for (MessageRange range : ranges) {
if (reset) {
// only call save if we need to
messageMapper.updateFlags(getMailboxEntity(), new Flags(Flag.RECENT), false, false, range);
@@ -607,11 +633,11 @@
}
return members;
}
-
+
});
-
+
}
-
+
protected Map deleteMarkedInMailbox(final MessageRange range, final MailboxSession session) throws MailboxException {
final MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
@@ -621,12 +647,13 @@
public Map run() throws MailboxException {
return messageMapper.expungeMarkedForDeletionInMailbox(getMailboxEntity(), range);
}
-
- });
+
+ });
}
/**
- * @see org.apache.james.mailbox.MessageManager#search(org.apache.james.mailbox.model.SearchQuery, org.apache.james.mailbox.MailboxSession)
+ * @see org.apache.james.mailbox.MessageManager#search(org.apache.james.mailbox.model.SearchQuery,
+ * org.apache.james.mailbox.MailboxSession)
*/
public Iterator search(SearchQuery query, MailboxSession mailboxSession) throws MailboxException {
return index.search(mailboxSession, getMailboxEntity(), query);
@@ -651,7 +678,9 @@
}
/**
- * @see org.apache.james.mailbox.store.AbstractStoreMessageManager#copy(org.apache.james.mailbox.model.MessageRange, org.apache.james.mailbox.store.AbstractStoreMessageManager, org.apache.james.mailbox.MailboxSession)
+ * @see org.apache.james.mailbox.store.AbstractStoreMessageManager#copy(org.apache.james.mailbox.model.MessageRange,
+ * org.apache.james.mailbox.store.AbstractStoreMessageManager,
+ * org.apache.james.mailbox.MailboxSession)
*/
private SortedMap copy(MessageRange set, final StoreMessageManager to, final MailboxSession session) throws MailboxException {
MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
@@ -686,30 +715,75 @@
* @return uid
* @throws MailboxException
*/
- protected Long findFirstUnseenMessageUid(MailboxSession session) throws MailboxException{
+ protected Long findFirstUnseenMessageUid(MailboxSession session) throws MailboxException {
MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
return messageMapper.findFirstUnseenMessageUid(getMailboxEntity());
}
-
+
+ /**
+ * @see org.apache.james.mailbox.MessageManager#hasRight(org.apache.james.mailbox.MailboxACL.MailboxACLRight,
+ * org.apache.james.mailbox.MailboxSession)
+ */
public boolean hasRight(MailboxACLRight right, MailboxSession session) throws UnsupportedRightException {
User user = session.getUser();
String userName = user != null ? user.getUserName() : null;
-
+
return aclResolver.hasRight(userName, groupMembershipResolver, right, mailbox.getACL(), mailbox.getUser(), isGroupFolder(session));
}
-
+
/**
- * Returns true if the current mailbox does not reside neither in private nor other users' namespace.
- *
+ * Returns the rights applicable to the user who has sent the current
+ * request.
+ *
* @param session
+ * @return the rights applicable to the user who has sent the request,
+ * returns {@link SimpleMailboxACL#NO_RIGHTS} if
+ * {@code session.getUser()} is null.
+ * @throws UnsupportedRightException
+ */
+ public MailboxACLRights myRights(MailboxSession session) throws MailboxException {
+ User user = session.getUser();
+ if (user != null) {
+ return listRigths(user.getUserName(), session);
+ } else {
+ return SimpleMailboxACL.NO_RIGHTS;
+ }
+ }
+
+ /**
+ * Returns the rights applicable to the given user.
+ *
+ * @param user
+ * @param session
* @return
+ * @throws UnsupportedRightException
*/
+ public MailboxACLRights listRigths(String user, MailboxSession session) throws UnsupportedRightException {
+ return aclResolver.listRights(user, groupMembershipResolver, mailbox.getACL(), mailbox.getUser(), isGroupFolder(session));
+ }
+
+ /**
+ * Applies the global ACL (if there are any) to the mailbox ACL.
+ *
+ * @param mailboxSession
+ * @return the ACL of the present mailbox merged with the global ACL (if
+ * there are any).
+ * @throws UnsupportedRightException
+ */
+ protected MailboxACL getResolvedMailboxACL(MailboxSession mailboxSession) throws UnsupportedRightException {
+ return aclResolver.applyGlobalACL(mailbox.getACL(), isGroupFolder(mailboxSession));
+ }
+
+ /**
+ * Returns true if the current mailbox does not reside neither in private
+ * nor other users' namespace.
+ *
+ * @param session
+ * @return
+ */
protected boolean isGroupFolder(MailboxSession session) {
final String ns = mailbox.getNamespace();
- return ns == null || (
- !ns.equals(session.getPersonalSpace())
- && !ns.equals(session.getOtherUsersSpace())
- );
+ return ns == null || (!ns.equals(session.getPersonalSpace()) && !ns.equals(session.getOtherUsersSpace()));
}
-
+
}