Author: eric
Date: Mon Feb 13 09:50:23 2012
New Revision: 1243457
URL: http://svn.apache.org/viewvc?rev=1243457&view=rev
Log:
Mapping of ACL to to READ-WRITE and READ-ONLY response codes, contributed by
Jochen Gazda (MAILBOX-160)
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
(original)
+++
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
Mon Feb 13 09:50:23 2012
@@ -61,11 +61,12 @@ public interface MessageManager {
*
* @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
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java
(original)
+++
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/MailboxACLResolver.java
Mon Feb 13 09:50:23 2012
@@ -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 interface MailboxACLResolver {
*/
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;
+
}
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
(original)
+++
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/acl/UnionMailboxACLResolver.java
Mon Feb 13 09:50:23 2012
@@ -24,6 +24,9 @@ import java.util.Iterator;
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.Ma
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 @@ import com.sun.mail.mbox.Mailbox;
* the result is computed afterwards with
* <code>nonNegativeUnion.except(negativeUnion)</code>.
*
- * 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 @@ public class UnionMailboxACLResolver imp
return false;
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.MailboxACLResolver#applyGlobalACL(org.apache
* .james.mailbox.MailboxACL, boolean)
@@ -152,9 +154,7 @@ public class UnionMailboxACLResolver imp
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 @@ public class UnionMailboxACLResolver imp
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.
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
(original)
+++
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java
Mon Feb 13 09:50:23 2012
@@ -133,7 +133,7 @@ public interface MailboxACL {
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 @@ public interface MailboxACL {
* 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.
Modified:
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
(original)
+++
james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/model/SimpleMailboxACL.java
Mon Feb 13 09:50:23 2012
@@ -354,9 +354,7 @@ public class SimpleMailboxACL implements
}
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
* org.apache.james.mailbox.MailboxACL.MailboxACLRights#contains(org
* .apache.james.mailbox.MailboxACL.MailboxACLRight)
@@ -381,9 +379,7 @@ public class SimpleMailboxACL implements
}
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see
*
org.apache.james.mailbox.MailboxACL.MailboxACLRights#except(org.apache
* .james.mailbox.MailboxACL.MailboxACLRights)
Modified:
james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
URL:
http://svn.apache.org/viewvc/james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java?rev=1243457&r1=1243456&r2=1243457&view=diff
==============================================================================
---
james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
(original)
+++
james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
Mon Feb 13 09:50:23 2012
@@ -45,17 +45,20 @@ import org.apache.james.mailbox.MailboxS
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.Mi
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<Id> implements
org.apache.james.mailbox.MessageManager{
+public class StoreMessageManager<Id> implements
org.apache.james.mailbox.MessageManager {
/**
* The minimal Permanent flags the {@link MessageManager} must support.
<br>
*
- * <strong>Be sure this static instance will never get modifed
later!</strong>
+ * <strong>Be sure this static instance will never get modifed
+ * later!</strong>
*/
protected final static Flags MINIMAL_PERMANET_FLAGS;
static {
@@ -103,22 +109,23 @@ public class StoreMessageManager<Id> imp
}
private final Mailbox<Id> mailbox;
-
- private final MailboxEventDispatcher<Id> dispatcher;
-
+
+ private final MailboxEventDispatcher<Id> dispatcher;
+
private final MessageMapperFactory<Id> mapperFactory;
private final MessageSearchIndex<Id> index;
-
+
private final MailboxACLResolver aclResolver;
-
+
private final GroupMembershipResolver groupMembershipResolver;
- private MailboxPathLocker locker;
+ private MailboxPathLocker locker;
private int fetchBatchSize;
-
- public StoreMessageManager(final MessageMapperFactory<Id> mapperFactory,
final MessageSearchIndex<Id> index, final MailboxEventDispatcher<Id>
dispatcher, final MailboxPathLocker locker, final Mailbox<Id> mailbox, final
MailboxACLResolver aclResolver, final GroupMembershipResolver
groupMembershipResolver) throws MailboxException {
+
+ public StoreMessageManager(final MessageMapperFactory<Id> mapperFactory,
final MessageSearchIndex<Id> index, final MailboxEventDispatcher<Id>
dispatcher, final MailboxPathLocker locker, final Mailbox<Id> mailbox, final
MailboxACLResolver aclResolver,
+ final GroupMembershipResolver groupMembershipResolver) throws
MailboxException {
this.mailbox = mailbox;
this.dispatcher = dispatcher;
this.mapperFactory = mapperFactory;
@@ -127,12 +134,11 @@ public class StoreMessageManager<Id> imp
this.aclResolver = aclResolver;
this.groupMembershipResolver = groupMembershipResolver;
}
-
+
public void setFetchBatchSize(int fetchBatchSize) {
this.fetchBatchSize = fetchBatchSize;
}
-
-
+
/**
* Return the {@link MailboxPathLocker}
*
@@ -141,7 +147,7 @@ public class StoreMessageManager<Id> imp
protected MailboxPathLocker getLocker() {
return locker;
}
-
+
/**
* Return the {@link MailboxEventDispatcher} for this Mailbox
*
@@ -150,18 +156,17 @@ public class StoreMessageManager<Id> imp
protected MailboxEventDispatcher<Id> getDispatcher() {
return dispatcher;
}
-
+
/**
* Return the underlying {@link Mailbox}
*
* @return mailbox
* @throws MailboxException
*/
-
+
public Mailbox<Id> getMailboxEntity() throws MailboxException {
return mailbox;
}
-
/**
* Return {@link Flags} which are permanent stored by the mailbox. By
@@ -188,12 +193,26 @@ public class StoreMessageManager<Id> imp
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 @@ public class StoreMessageManager<Id> imp
}
/**
- * @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<Long> expunge(final MessageRange set, MailboxSession
mailboxSession) throws MailboxException {
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new
StoreMailboxPath<Id>(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new
StoreMailboxPath<Id>(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
Map<Long, MessageMetaData> 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<Id>(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new
StoreMailboxPath<Id>(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 @@ public class StoreMessageManager<Id> imp
} 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 @@ public class StoreMessageManager<Id> imp
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 @@ public class StoreMessageManager<Id> imp
@Override
public Long execute() throws MailboxException {
MessageMetaData data = appendMessageToStore(message,
mailboxSession);
-
+
SortedMap<Long, MessageMetaData> uids = new TreeMap<Long,
MessageMetaData>();
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 @@ public class StoreMessageManager<Id> imp
// 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 @@ public class StoreMessageManager<Id> imp
}
-
/**
* Create a new {@link Message} for the given data
*
@@ -387,76 +408,78 @@ public class StoreMessageManager<Id> imp
* @param content
* @param flags
* @return membership
- * @throws MailboxException
+ * @throws MailboxException
*/
- protected Message<Id> createMessage(Date internalDate, final int size, int
bodyStartOctet,
- final SharedInputStream content, final Flags flags, final
PropertyBuilder propertyBuilder) throws MailboxException {
+ protected Message<Id> createMessage(Date internalDate, final int size, int
bodyStartOctet, final SharedInputStream content, final Flags flags, final
PropertyBuilder propertyBuilder) throws MailboxException {
return new SimpleMessage<Id>(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<Long> 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);
-
- 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;
- 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<Long>();
- 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 );
+ 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 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<Long>();
+ break;
+ }
+ 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 @@ public class StoreMessageManager<Id> imp
* @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 <uFlags.length; i++) {
+ for (int i = 0; i < uFlags.length; i++) {
String uFlag = uFlags[i];
if (permFlags.contains(uFlag) == false) {
flags.remove(uFlag);
}
}
}
-
+
}
-
+
/**
- * @see org.apache.james.mailbox.MessageManager#setFlags(javax.mail.Flags,
boolean, boolean, org.apache.james.mailbox.model.MessageRange,
org.apache.james.mailbox.MailboxSession)
+ * @see org.apache.james.mailbox.MessageManager#setFlags(javax.mail.Flags,
+ * boolean, boolean, org.apache.james.mailbox.model.MessageRange,
+ * org.apache.james.mailbox.MailboxSession)
*/
- public Map<Long, Flags> setFlags(final Flags flags, final boolean value,
final boolean replace,
- final MessageRange set, MailboxSession mailboxSession) throws
MailboxException {
-
+ public Map<Long, Flags> 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<Id>(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new
StoreMailboxPath<Id>(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
final SortedMap<Long, Flags> newFlagsByUid = new TreeMap<Long,
Flags>();
trimFlags(flags, mailboxSession);
-
+
final MessageMapper<Id> messageMapper =
mapperFactory.getMessageMapper(mailboxSession);
-
+
Iterator<UpdatedFlags> it = messageMapper.execute(new
Mapper.Transaction<Iterator<UpdatedFlags>>() {
public Iterator<UpdatedFlags> run() throws MailboxException {
- return messageMapper.updateFlags(getMailboxEntity(),flags,
value, replace, set);
+ return messageMapper.updateFlags(getMailboxEntity(), flags,
value, replace, set);
}
});
-
+
final SortedMap<Long, UpdatedFlags> uFlags = new TreeMap<Long,
UpdatedFlags>();
while (it.hasNext()) {
@@ -517,14 +542,12 @@ public class StoreMessageManager<Id> imp
newFlagsByUid.put(flag.getUid(), flag.getNewFlags());
uFlags.put(flag.getUid(), flag);
}
-
+
dispatcher.flagsUpdated(mailboxSession, new
ArrayList<Long>(uFlags.keySet()), getMailboxEntity(), new
ArrayList<UpdatedFlags>(uFlags.values()));
return newFlagsByUid;
}
-
-
/**
* Copy the {@link MessageRange} to the {@link StoreMessageManager}
*
@@ -535,9 +558,9 @@ public class StoreMessageManager<Id> imp
*/
public List<MessageRange> copyTo(final MessageRange set, final
StoreMessageManager<Id> toMailbox, final MailboxSession session) throws
MailboxException {
if (!toMailbox.isWriteable(session)) {
- throw new ReadOnlyException(new
StoreMailboxPath<Id>(toMailbox.getMailboxEntity()),session.getPathDelimiter());
+ throw new ReadOnlyException(new
StoreMailboxPath<Id>(toMailbox.getMailboxEntity()), session.getPathDelimiter());
}
-
+
return locker.executeWithLock(session, new
StoreMailboxPath<Id>(toMailbox.getMailboxEntity()), new
MailboxPathLocker.LockAwareExecution<List<MessageRange>>() {
@Override
@@ -548,7 +571,7 @@ public class StoreMessageManager<Id> imp
}
}, true);
}
-
+
protected MessageMetaData appendMessageToStore(final Message<Id> message,
MailboxSession session) throws MailboxException {
final MessageMapper<Id> mapper =
mapperFactory.getMessageMapper(session);
return mapperFactory.getMessageMapper(session).execute(new
Mapper.Transaction<MessageMetaData>() {
@@ -556,7 +579,7 @@ public class StoreMessageManager<Id> imp
public MessageMetaData run() throws MailboxException {
return mapper.add(getMailboxEntity(), message);
}
-
+
});
}
@@ -568,7 +591,9 @@ public class StoreMessageManager<Id> imp
}
/**
- * @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<Id> messageMapper =
mapperFactory.getMessageMapper(mailboxSession);
@@ -587,19 +612,20 @@ public class StoreMessageManager<Id> imp
protected List<Long> recent(final boolean reset, MailboxSession
mailboxSession) throws MailboxException {
if (reset) {
if (!isWriteable(mailboxSession)) {
- throw new ReadOnlyException(new
StoreMailboxPath<Id>(getMailboxEntity()),mailboxSession.getPathDelimiter());
+ throw new ReadOnlyException(new
StoreMailboxPath<Id>(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
}
final MessageMapper<Id> messageMapper =
mapperFactory.getMessageMapper(mailboxSession);
-
+
return messageMapper.execute(new Mapper.Transaction<List<Long>>() {
public List<Long> run() throws MailboxException {
final List<Long> 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<MessageRange> 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 @@ public class StoreMessageManager<Id> imp
}
return members;
}
-
+
});
-
+
}
-
+
protected Map<Long, MessageMetaData> deleteMarkedInMailbox(final
MessageRange range, final MailboxSession session) throws MailboxException {
final MessageMapper<Id> messageMapper =
mapperFactory.getMessageMapper(session);
@@ -621,12 +647,13 @@ public class StoreMessageManager<Id> imp
public Map<Long, MessageMetaData> 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<Long> search(SearchQuery query, MailboxSession
mailboxSession) throws MailboxException {
return index.search(mailboxSession, getMailboxEntity(), query);
@@ -651,7 +678,9 @@ public class StoreMessageManager<Id> imp
}
/**
- * @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<Long, MessageMetaData> copy(MessageRange set, final
StoreMessageManager<Id> to, final MailboxSession session) throws
MailboxException {
MessageMapper<Id> messageMapper =
mapperFactory.getMessageMapper(session);
@@ -686,30 +715,75 @@ public class StoreMessageManager<Id> imp
* @return uid
* @throws MailboxException
*/
- protected Long findFirstUnseenMessageUid(MailboxSession session) throws
MailboxException{
+ protected Long findFirstUnseenMessageUid(MailboxSession session) throws
MailboxException {
MessageMapper<Id> 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()));
}
-
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]