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 bt...@apache.org on 2018/12/04 08:48:59 UTC
[6/8] james-project git commit: MAILBOX-292 Make Maildir Mailbox Id
persistent
MAILBOX-292 Make Maildir Mailbox Id persistent
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7e32da51
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7e32da51
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7e32da51
Branch: refs/heads/master
Commit: 7e32da51a29bee1c732b2b13708bb4b986140119
Parents: d9bcebc
Author: Benoit Tellier <bt...@linagora.com>
Authored: Fri Nov 30 16:00:34 2018 +0700
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Tue Dec 4 15:47:46 2018 +0700
----------------------------------------------------------------------
.../james/mailbox/maildir/MaildirFolder.java | 54 +++++++++++++++-
.../apache/james/mailbox/maildir/MaildirId.java | 7 ++
.../james/mailbox/maildir/MaildirStore.java | 1 +
.../mailbox/maildir/mail/MailboxCache.java | 68 --------------------
.../maildir/mail/MaildirMailboxMapper.java | 63 ++++++++++--------
.../DomainUserMaildirMailboxManagerTest.java | 9 ---
.../FullUserMaildirMailboxManagerTest.java | 10 ---
.../maildir/src/test/resources/logback-test.xml | 28 ++++++++
8 files changed, 125 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
index 4982726..b31b522 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
@@ -58,6 +58,7 @@ public class MaildirFolder {
public static final String VALIDITY_FILE = "james-uidvalidity";
public static final String UIDLIST_FILE = "james-uidlist";
public static final String ACL_FILE = "james-acl";
+ public static final String MAILBOX_ID_FILE = "james-mailboxId";
public static final String CUR = "cur";
public static final String NEW = "new";
public static final String TMP = "tmp";
@@ -68,7 +69,8 @@ public class MaildirFolder {
private final File tmpFolder;
private final File uidFile;
private final File aclFile;
-
+ private final File mailboxIdFile;
+
private Optional<MessageUid> lastUid;
private int messageCount = 0;
private long uidValidity = -1;
@@ -91,6 +93,7 @@ public class MaildirFolder {
this.tmpFolder = new File(rootFolder, TMP);
this.uidFile = new File(rootFolder, UIDLIST_FILE);
this.aclFile = new File(rootFolder, ACL_FILE);
+ this.mailboxIdFile = new File(rootFolder, MAILBOX_ID_FILE);
this.locker = locker;
this.path = path;
this.lastUid = Optional.empty();
@@ -163,6 +166,10 @@ public class MaildirFolder {
public File getCurFolder() {
return curFolder;
}
+
+ public File getMailboxIdFile() {
+ return mailboxIdFile;
+ }
/**
* Returns the ./new folder of this Maildir folder.
@@ -294,6 +301,51 @@ public class MaildirFolder {
fos.write(String.valueOf(uidValidity).getBytes());
}
}
+
+ /**
+ * Sets the mailboxId for this mailbox and writes it to the file system
+ * @param mailboxId
+ * @throws IOException
+ */
+ public void setMailboxId(MaildirId mailboxId) throws IOException {
+ saveMailboxId(mailboxId);
+ }
+
+ /**
+ * Read the mailboxId of the given mailbox from the file system.
+ * If the respective file is not yet there, it gets created and
+ * filled with a brand new uidValidity.
+ * @return The uidValidity
+ * @throws IOException if there are problems with the validity file
+ */
+ public MaildirId readMailboxId() throws IOException {
+ if (!mailboxIdFile.exists()) {
+ MaildirId maildirId = MaildirId.random();
+ saveMailboxId(maildirId);
+ return maildirId;
+ }
+ try (FileInputStream fis = new FileInputStream(mailboxIdFile);
+ InputStreamReader isr = new InputStreamReader(fis)) {
+ char[] mailboxId = new char[20];
+ int len = isr.read(mailboxId);
+ int idAsInt = Integer.parseInt(String.valueOf(mailboxId, 0, len).trim());
+ return MaildirId.of(idAsInt);
+ }
+ }
+
+ /**
+ * Save the given MaildirId to the file system
+ * @param id
+ * @throws IOException
+ */
+ private void saveMailboxId(MaildirId id) throws IOException {
+ if (!mailboxIdFile.createNewFile()) {
+ throw new IOException("Could not create file " + mailboxIdFile);
+ }
+ try (FileOutputStream fos = new FileOutputStream(mailboxIdFile)) {
+ fos.write(String.valueOf(id.getRawId()).getBytes());
+ }
+ }
/**
* Sets and returns a new uidValidity for this folder.
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirId.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirId.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirId.java
index 69de83f..18df444 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirId.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirId.java
@@ -19,6 +19,7 @@
package org.apache.james.mailbox.maildir;
import java.io.Serializable;
+import java.security.SecureRandom;
import org.apache.james.mailbox.model.MailboxId;
@@ -31,6 +32,12 @@ public class MaildirId implements MailboxId, Serializable {
}
}
+ private static final SecureRandom RANDOM = new SecureRandom();
+
+ public static MaildirId random() {
+ return MaildirId.of(Math.abs(RANDOM.nextInt()));
+ }
+
public static MaildirId of(int id) {
return new MaildirId(id);
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java
index f7a2d8d..b0a3192 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java
@@ -132,6 +132,7 @@ public class MaildirStore implements UidProvider, ModSeqProvider {
folder.setMessageNameStrictParse(isMessageNameStrictParse());
try {
Mailbox loadedMailbox = new SimpleMailbox(mailboxPath, folder.getUidValidity());
+ loadedMailbox.setMailboxId(folder.readMailboxId());
loadedMailbox.setACL(folder.getACL(session));
return loadedMailbox;
} catch (IOException e) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MailboxCache.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MailboxCache.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MailboxCache.java
deleted file mode 100644
index cf04c1e..0000000
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MailboxCache.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- ****************************************************************/
-
-package org.apache.james.mailbox.maildir.mail;
-
-import java.util.ArrayList;
-
-import org.apache.james.mailbox.exception.MailboxNotFoundException;
-import org.apache.james.mailbox.maildir.MaildirId;
-import org.apache.james.mailbox.store.mail.model.Mailbox;
-import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
-
-public class MailboxCache {
- /**
- * A request-scoped list of mailboxes in order to refer to them via id
- */
- private final ArrayList<Mailbox> mailboxCache = new ArrayList<>();
-
- /**
- * Stores a copy of a mailbox in a cache valid for one request. This is to enable
- * referring to renamed mailboxes via id.
- * @param mailbox The mailbox to cache
- * @return the cached mailbox
- */
- public synchronized Mailbox cacheMailbox(Mailbox mailbox) {
- mailboxCache.add(new SimpleMailbox(mailbox));
- int id = mailboxCache.size() - 1;
- mailbox.setMailboxId(MaildirId.of(id));
- return mailbox;
- }
-
- /**
- * Retrieves a mailbox from the cache
- * @param mailboxId The id of the mailbox to retrieve
- * @return The mailbox
- * @throws MailboxNotFoundException If the mailboxId is not in the cache
- */
- public synchronized Mailbox getCachedMailbox(MaildirId mailboxId) throws MailboxNotFoundException {
- if (mailboxId == null) {
- throw new MailboxNotFoundException("null");
- }
- try {
- return mailboxCache.get(mailboxId.getRawId());
- } catch (IndexOutOfBoundsException e) {
- throw new MailboxNotFoundException(mailboxId);
- }
- }
-
- public synchronized void clear() {
- mailboxCache.clear();
- }
-}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
index b1b83f9..454d857 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMailboxMapper.java
@@ -23,6 +23,8 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
+import java.util.Random;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
@@ -55,18 +57,12 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
* The {@link MaildirStore} the mailboxes reside in
*/
private final MaildirStore maildirStore;
-
- /**
- * A request-scoped list of mailboxes in order to refer to them via id
- */
- private final MailboxCache mailboxCache;
private final MailboxSession session;
public MaildirMailboxMapper(MaildirStore maildirStore, MailboxSession session) {
this.maildirStore = maildirStore;
this.session = session;
- this.mailboxCache = new MailboxCache();
}
@Override
@@ -109,14 +105,18 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
@Override
public Mailbox findMailboxByPath(MailboxPath mailboxPath)
throws MailboxException, MailboxNotFoundException {
- Mailbox mailbox = maildirStore.loadMailbox(session, mailboxPath);
- return mailboxCache.cacheMailbox(mailbox);
+ return maildirStore.loadMailbox(session, mailboxPath);
}
@Override
public Mailbox findMailboxById(MailboxId id) throws MailboxException, MailboxNotFoundException {
- MaildirId mailboxId = (MaildirId)id;
- return mailboxCache.getCachedMailbox(mailboxId);
+ if (id == null) {
+ throw new MailboxNotFoundException("null");
+ }
+ return list().stream()
+ .filter(mailbox -> mailbox.getMailboxId().equals(id))
+ .findAny()
+ .orElseThrow(() -> new MailboxNotFoundException(id));
}
@Override
@@ -131,13 +131,13 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
for (File folder : folders) {
if (folder.isDirectory()) {
Mailbox mailbox = maildirStore.loadMailbox(session, root, mailboxPath.getNamespace(), mailboxPath.getUser(), folder.getName());
- mailboxList.add(mailboxCache.cacheMailbox(mailbox));
+ mailboxList.add(mailbox);
}
}
// INBOX is in the root of the folder
if (Pattern.matches(mailboxPath.getName().replace(MaildirStore.WILDCARD, ".*"), MailboxConstants.INBOX)) {
Mailbox mailbox = maildirStore.loadMailbox(session, root, mailboxPath.getNamespace(), mailboxPath.getUser(), "");
- mailboxList.add(0, mailboxCache.cacheMailbox(mailbox));
+ mailboxList.add(0, mailbox);
}
return mailboxList;
}
@@ -152,8 +152,11 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
@Override
public MailboxId save(Mailbox mailbox) throws MailboxException {
+ MaildirId maildirId = Optional.ofNullable(mailbox.getMailboxId())
+ .map(mailboxId -> (MaildirId) mailboxId)
+ .orElseGet(MaildirId::random);
try {
- Mailbox originalMailbox = mailboxCache.getCachedMailbox((MaildirId) mailbox.getMailboxId());
+ Mailbox originalMailbox = findMailboxById(mailbox.getMailboxId());
MaildirFolder folder = maildirStore.createMaildirFolder(mailbox);
// equals with null check
if (originalMailbox.getName() == null ? mailbox.getName() != null : !originalMailbox.getName().equals(mailbox.getName())) {
@@ -171,6 +174,9 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
if (!originalFolder.getCurFolder().renameTo(folder.getCurFolder())) {
throw new IOException("Could not rename folder " + originalFolder.getCurFolder() + " to " + folder.getCurFolder());
}
+ if (!originalFolder.getMailboxIdFile().renameTo(folder.getMailboxIdFile())) {
+ throw new IOException("Could not rename folder " + originalFolder.getCurFolder() + " to " + folder.getCurFolder());
+ }
if (!originalFolder.getNewFolder().renameTo(folder.getNewFolder())) {
throw new IOException("Could not rename folder " + originalFolder.getNewFolder() + " to " + folder.getNewFolder());
}
@@ -192,6 +198,7 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
FileUtils.forceMkdir(originalFolder.getCurFolder());
FileUtils.forceMkdir(originalFolder.getNewFolder());
FileUtils.forceMkdir(originalFolder.getTmpFolder());
+ originalFolder.setMailboxId(MaildirId.of(Math.abs(new Random().nextInt())));
} catch (IOException e) {
throw new MailboxException("Failed to save Mailbox " + mailbox, e);
}
@@ -224,14 +231,14 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
}
try {
folder.setUidValidity(mailbox.getUidValidity());
+ folder.setMailboxId(maildirId);
} catch (IOException ioe) {
throw new MailboxException("Failed to save Mailbox " + mailbox, ioe);
}
folder.setACL(session, mailbox.getACL());
}
- mailboxCache.cacheMailbox(mailbox);
- return mailbox.getMailboxId();
+ return maildirId;
}
@Override
@@ -240,26 +247,28 @@ public class MaildirMailboxMapper extends NonTransactionalMapper implements Mail
File maildirRoot = maildirStore.getMaildirRoot();
List<Mailbox> mailboxList = new ArrayList<>();
- if (maildirStore.getMaildirLocation().endsWith("/" + MaildirStore.PATH_FULLUSER)) {
- File[] users = maildirRoot.listFiles();
- visitUsersForMailboxList(null, users, mailboxList);
+
+
+ if (maildirStore.getMaildirLocation().endsWith("/" + MaildirStore.PATH_DOMAIN + "/" + MaildirStore.PATH_USER)) {
+ File[] domains = maildirRoot.listFiles();
+ for (File domain : domains) {
+ File[] users = domain.listFiles();
+ visitUsersForMailboxList(domain, users, mailboxList);
+ }
return mailboxList;
}
-
- File[] domains = maildirRoot.listFiles();
- for (File domain: domains) {
- File[] users = domain.listFiles();
- visitUsersForMailboxList(domain, users, mailboxList);
- }
- return mailboxList;
+
+ File[] users = maildirRoot.listFiles();
+ visitUsersForMailboxList(null, users, mailboxList);
+ return mailboxList;
}
@Override
public void endRequest() {
- mailboxCache.clear();
+
}
-
+
private void visitUsersForMailboxList(File domain, File[] users, List<Mailbox> mailboxList) throws MailboxException {
String userName = null;
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java
index 508fc54..cc494f1 100644
--- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java
+++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java
@@ -18,13 +18,9 @@
****************************************************************/
package org.apache.james.mailbox.maildir;
-import java.io.UnsupportedEncodingException;
-
import org.apache.james.junit.TemporaryFolderExtension;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxManagerTest;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.extension.RegisterExtension;
public class DomainUserMaildirMailboxManagerTest extends MailboxManagerTest {
@@ -41,9 +37,4 @@ public class DomainUserMaildirMailboxManagerTest extends MailboxManagerTest {
}
}
- @Disabled("https://issues.apache.org/jira/browse/MAILBOX-292")
- @Override
- public void createMailboxShouldReturnRightId() throws MailboxException, UnsupportedEncodingException {
-
- }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java
----------------------------------------------------------------------
diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java
index b69f30f..e08097f 100644
--- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java
+++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java
@@ -18,13 +18,9 @@
****************************************************************/
package org.apache.james.mailbox.maildir;
-import java.io.UnsupportedEncodingException;
-
import org.apache.james.junit.TemporaryFolderExtension;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxManagerTest;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.junit.Ignore;
import org.junit.jupiter.api.extension.RegisterExtension;
public class FullUserMaildirMailboxManagerTest extends MailboxManagerTest {
@@ -39,10 +35,4 @@ public class FullUserMaildirMailboxManagerTest extends MailboxManagerTest {
throw new RuntimeException(e);
}
}
-
- @Ignore("https://issues.apache.org/jira/browse/MAILBOX-292")
- @Override
- public void createMailboxShouldReturnRightId() throws MailboxException, UnsupportedEncodingException {
-
- }
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/7e32da51/mpt/impl/imap-mailbox/maildir/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/mpt/impl/imap-mailbox/maildir/src/test/resources/logback-test.xml b/mpt/impl/imap-mailbox/maildir/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..b02f0d8
--- /dev/null
+++ b/mpt/impl/imap-mailbox/maildir/src/test/resources/logback-test.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
+ <resetJUL>true</resetJUL>
+ </contextListener>
+
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
+ <immediateFlush>false</immediateFlush>
+ </encoder>
+ </appender>
+
+ <root level="WARN">
+ <appender-ref ref="CONSOLE" />
+ </root>
+
+
+ <logger name="org.apache.james" level="WARN" >
+ <appender-ref ref="CONSOLE" />
+ </logger>
+
+ <logger name="org.apache.james.backends.cassandra.DockerCassandraRule" level="WARN" >
+ <appender-ref ref="CONSOLE" />
+ </logger>
+
+</configuration>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org