This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 61b367fb621a8c9a7a0ae42e43f7bd7d371155c1 Author: Jan-Eric Hellenberg <janeric.hellenb...@gmail.com> AuthorDate: Fri Jan 3 10:25:28 2025 +0100 James-4099 Make mailbox path delimiter configurable --- docs/modules/servers/partials/configure/jvm.adoc | 15 ++ .../james/mailbox/model/MailboxConstants.java | 39 +++- .../apache/james/mailbox/MailboxSessionUtil.java | 11 +- .../james/mailbox/store/SessionProviderImpl.java | 2 +- .../org/apache/james/imap/main/PathConverter.java | 2 +- .../james/imap/message/response/ListResponse.java | 2 +- .../james/imap/main/DefaultPathConverterTest.java | 47 ++--- .../imap/main/PathConverterBasicContract.java | 210 ++++++++++++--------- .../docker-configuration/jvm.properties | 6 + .../sample-configuration/jvm.properties | 6 + .../docker-configuration/jvm.properties | 12 +- .../sample-configuration/jvm.properties | 10 +- .../docker-configuration/jvm.properties | 6 + .../sample-configuration/jvm.properties | 6 + .../jpa-app/sample-configuration/jvm.properties | 6 + .../sample-configuration/jvm.properties | 6 + .../memory-app/sample-configuration/jvm.properties | 6 + .../sample-configuration/jvm.properties | 6 + 18 files changed, 266 insertions(+), 132 deletions(-) diff --git a/docs/modules/servers/partials/configure/jvm.adoc b/docs/modules/servers/partials/configure/jvm.adoc index fdc71ef205..11f22bc5a3 100644 --- a/docs/modules/servers/partials/configure/jvm.adoc +++ b/docs/modules/servers/partials/configure/jvm.adoc @@ -5,6 +5,21 @@ when a property affects very early JVM start behaviour. For testing purposes, you may specify a different file path via the command line option `-Dextra.props=/some/other/jvm.properties`. +== Adjusting the Mailbox folder delimiter + +The delimiter used to separate parent/child folders. + +WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments will likely lead to failure of some system components, as occurrences of old the delimiter will still be present in the database/data store. + +Optional. String. Defaults to 'dot' + +Ex in `jvm.properties` +---- +james.mailbox.folder.delimiter=dot +---- + +Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). + == Control the threshold memory This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxConstants.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxConstants.java index 69bff299de..3afd9f21c7 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxConstants.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxConstants.java @@ -19,28 +19,51 @@ package org.apache.james.mailbox.model; +import java.util.Optional; + /** * Constants which are used within the mailbox api and implementations */ -public interface MailboxConstants { +public class MailboxConstants { /** * The char which is used to prefix a namespace */ - char NAMESPACE_PREFIX_CHAR = '#'; + public static final char NAMESPACE_PREFIX_CHAR = '#'; /** The namespace used for store user inboxes */ - String USER_NAMESPACE = NAMESPACE_PREFIX_CHAR + "private"; + public static final String USER_NAMESPACE = NAMESPACE_PREFIX_CHAR + "private"; + + /** The delimiter used to seperated parent/child folders */ + public static char FOLDER_DELIMITER = Optional.ofNullable(System.getProperty("james.mailbox.folder.delimiter")) + .map(MailboxFolderDelimiter::parse).orElse(MailboxFolderDelimiter.DOT).value; + + enum MailboxFolderDelimiter { + DOT('.'), + SLASH('/'); + + public final char value; + + MailboxFolderDelimiter(char value) { + this.value = value; + } - /** The default delimiter used to seperated parent/child folders */ - char DEFAULT_DELIMITER = '.'; + static MailboxFolderDelimiter parse(String input) { + for (MailboxFolderDelimiter delimiter: values()) { + if (delimiter.name().equalsIgnoreCase(input)) { + return delimiter; + } + } + throw new IllegalArgumentException(String.format("Invalid mailbox delimiter `%s`", input)); + } + } /** The name of the INBOX */ - String INBOX = "INBOX"; + public static final String INBOX = "INBOX"; /** The limitation of annotation data */ - int DEFAULT_LIMIT_ANNOTATION_SIZE = 1024; + public static final int DEFAULT_LIMIT_ANNOTATION_SIZE = 1024; /** The maximum number of annotations on a mailbox */ - int DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX = 10; + public static final int DEFAULT_LIMIT_ANNOTATIONS_ON_MAILBOX = 10; } diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxSessionUtil.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxSessionUtil.java index e2aa013008..2d4ac34f7d 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxSessionUtil.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxSessionUtil.java @@ -31,11 +31,16 @@ import com.google.common.annotations.VisibleForTesting; public class MailboxSessionUtil { public static MailboxSession create(Username username) { - return create(username, MailboxSession.SessionId.of(ThreadLocalRandom.current().nextLong())); + return create(username, MailboxConstants.FOLDER_DELIMITER); + } + + public static MailboxSession create(Username username, char folderDelimiter) { + return create(username, MailboxSession.SessionId.of(ThreadLocalRandom.current().nextLong()), folderDelimiter); } @VisibleForTesting - public static MailboxSession create(Username username, MailboxSession.SessionId sessionId) { + public static MailboxSession create(Username username, MailboxSession.SessionId sessionId, + char folderDelimiter) { ArrayList<Locale> locales = new ArrayList<>(); return new MailboxSession( @@ -43,7 +48,7 @@ public class MailboxSessionUtil { username, Optional.of(username), locales, - MailboxConstants.DEFAULT_DELIMITER, + folderDelimiter, MailboxSession.SessionType.User); } } diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java index 5651c699c8..b0eea7c0a3 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/SessionProviderImpl.java @@ -127,7 +127,7 @@ public class SessionProviderImpl implements SessionProvider { } private MailboxSession createSession(Username userName, Optional<Username> loggedInUser, MailboxSession.SessionType type) { - return new MailboxSession(newSessionId(), userName, loggedInUser, new ArrayList<>(), MailboxConstants.DEFAULT_DELIMITER, type); + return new MailboxSession(newSessionId(), userName, loggedInUser, new ArrayList<>(), MailboxConstants.FOLDER_DELIMITER, type); } private MailboxSession.SessionId newSessionId() { diff --git a/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java b/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java index 7d2d53281a..f57cc3e3c1 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/main/PathConverter.java @@ -112,7 +112,7 @@ public interface PathConverter { return new MailboxPath(MailboxConstants.USER_NAMESPACE, null, sanitizeMailboxName(mailboxName)); } String username = mailboxPathParts.get(USER); - String unescapedUsername = username.replace("__", ".") + String unescapedUsername = username.replace("__", String.valueOf(MailboxConstants.FOLDER_DELIMITER)) .replace("_-", "_"); Username user = Username.from(unescapedUsername, session.getUser().getDomainPart().map(Domain::asString)); String mailboxName = Joiner.on(session.getPathDelimiter()).join(Iterables.skip(mailboxPathParts, 2)); diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ListResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ListResponse.java index ba8c6f785f..77c13f095a 100644 --- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/ListResponse.java +++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/ListResponse.java @@ -106,7 +106,7 @@ public final class ListResponse extends AbstractListingResponse implements ImapR return name(subscribedPath.getName()) .children(MailboxMetaData.Children.CHILDREN_ALLOWED_BUT_UNKNOWN) .selectability(MailboxMetaData.Selectability.NONE) - .hierarchyDelimiter(MailboxConstants.DEFAULT_DELIMITER) + .hierarchyDelimiter(MailboxConstants.FOLDER_DELIMITER) .returnSubscribed(RETURN_SUBSCRIBED) .returnNonExistent(RETURN_NON_EXISTENT) .mailboxType(MailboxType.OTHER); diff --git a/protocols/imap/src/test/java/org/apache/james/imap/main/DefaultPathConverterTest.java b/protocols/imap/src/test/java/org/apache/james/imap/main/DefaultPathConverterTest.java index 8a47746da4..95172d8928 100644 --- a/protocols/imap/src/test/java/org/apache/james/imap/main/DefaultPathConverterTest.java +++ b/protocols/imap/src/test/java/org/apache/james/imap/main/DefaultPathConverterTest.java @@ -19,36 +19,41 @@ package org.apache.james.imap.main; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; -public class DefaultPathConverterTest implements PathConverterBasicContract { - - private PathConverter pathConverter; - - @BeforeEach - void setup() { - pathConverter = PathConverter.Factory.DEFAULT.forSession(mailboxSession); - } - - @Override - public PathConverter pathConverter() { - return pathConverter; +public class DefaultPathConverterTest { + @Nested + public class DotDelimiter extends TestBase { + @Override + public char pathDelimiter() { + return '.'; + } } @Nested - class WithEmailTest implements PathConverterBasicContract.WithEmail { - - private PathConverter pathConverter; - - @BeforeEach - void setup() { - pathConverter = PathConverter.Factory.DEFAULT.forSession(mailboxSession); + public class SlashDelimiter extends TestBase { + @Override + public char pathDelimiter() { + return '/'; } + } + + public abstract static class TestBase extends PathConverterBasicContract { + private final PathConverter pathConverter = PathConverter.Factory.DEFAULT.forSession(mailboxSession); @Override public PathConverter pathConverter() { return pathConverter; } + + @Nested + public class WithEmail extends PathConverterBasicContract.WithEmail { + private final PathConverter pathConverter = PathConverter.Factory.DEFAULT.forSession(mailboxWithEmailSession); + + @Override + public PathConverter pathConverter() { + return pathConverter; + } + } } -} \ No newline at end of file +} diff --git a/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterBasicContract.java b/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterBasicContract.java index 76ab0a6d36..a627462750 100644 --- a/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterBasicContract.java +++ b/protocols/imap/src/test/java/org/apache/james/imap/main/PathConverterBasicContract.java @@ -27,259 +27,285 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MailboxSessionUtil; import org.apache.james.mailbox.model.MailboxConstants; import org.apache.james.mailbox.model.MailboxPath; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -public interface PathConverterBasicContract { +public abstract class PathConverterBasicContract { + public static final Username USERNAME = Username.of("username"); + public static final Username USERNAME_WITH_DELIMITER = Username.of("username.with.delimiter"); + public static final Username USERNAME_WITH_UNDERSCORE = Username.of("username_with_underscore"); + public static final Username USERNAME2 = Username.of("username2"); - Username USERNAME = Username.of("username"); - Username USERNAME_WITH_DOT = Username.of("username.with.dot"); - Username USERNAME_WITH_UNDERSCORE = Username.of("username_with_underscore"); - Username USERNAME2 = Username.of("username2"); + public static final Username USERNAME_WITH_MAIL = Username.of("usern...@apache.org"); + public static final Username USERNAME2_WITH_MAIL = Username.of("userna...@apache.org"); + public static final boolean RELATIVE = true; - Username USERNAME_WITH_MAIL = Username.of("usern...@apache.org"); - Username USERNAME2_WITH_MAIL = Username.of("userna...@apache.org"); - char PATH_DELIMITER = '.'; - boolean RELATIVE = true; + public final MailboxSession mailboxSession = MailboxSessionUtil.create(USERNAME, pathDelimiter()); - MailboxSession mailboxSession = MailboxSessionUtil.create(USERNAME); + abstract PathConverter pathConverter(); - PathConverter pathConverter(); + abstract char pathDelimiter(); + + static char initialPathDelimiter; + + @BeforeEach + public void setUp() { + initialPathDelimiter = MailboxConstants.FOLDER_DELIMITER; + MailboxConstants.FOLDER_DELIMITER = pathDelimiter(); + } + + @AfterEach + public void tearDown() { + MailboxConstants.FOLDER_DELIMITER = initialPathDelimiter; + } + + static String adjustToTestDelimiter(String valueWithDots) { + // Because the test setup will configure the desired delimiter to be used, + // we do not need to pass it in manually here. + return valueWithDots.replace('.', MailboxConstants.FOLDER_DELIMITER); + } + + static Username adjustToTestDelimiter(Username username) { + return Username.of(adjustToTestDelimiter(username.asString())); + } @Test - default void buildFullPathShouldAcceptNull() { + public void buildFullPathShouldAcceptNull() { assertThat(pathConverter().buildFullPath(null)) .isEqualTo(new MailboxPath("", USERNAME, "")); } @Test - default void buildPathShouldAcceptEmpty() { + public void buildPathShouldAcceptEmpty() { assertThat(pathConverter().buildFullPath("")) .isEqualTo(new MailboxPath("", USERNAME, "")); } @Test - default void buildPathShouldAcceptRelativeMailboxName() { + public void buildPathShouldAcceptRelativeMailboxName() { String mailboxName = "mailboxName"; assertThat(pathConverter().buildFullPath(mailboxName)) .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); } @Test - default void buildFullPathShouldAcceptUserNamespace() { + public void buildFullPathShouldAcceptUserNamespace() { assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE)) .isEqualTo(MailboxPath.forUser(USERNAME, "")); } @Test - default void buildFullPathShouldAcceptUserNamespaceAndDelimiter() { - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER)) + public void buildFullPathShouldAcceptUserNamespaceAndDelimiter() { + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter())) .isEqualTo(MailboxPath.forUser(USERNAME, "")); } @Test - default void buildFullPathShouldAcceptFullAbsoluteUserPath() { + public void buildFullPathShouldAcceptFullAbsoluteUserPath() { String mailboxName = "mailboxName"; - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER + mailboxName)) - .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter() + mailboxName)) + .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); } @Test - default void buildFullPathShouldAcceptRelativePathWithSubFolder() { - String mailboxName = "mailboxName" + PATH_DELIMITER + "subFolder"; + public void buildFullPathShouldAcceptRelativePathWithSubFolder() { + String mailboxName = adjustToTestDelimiter("mailboxName.subFolder"); assertThat(pathConverter().buildFullPath(mailboxName)) - .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); + .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); } @Test - default void buildFullPathShouldAcceptAbsoluteUserPathWithSubFolder() { - String mailboxName = "mailboxName.subFolder"; - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER + mailboxName)) - .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); + public void buildFullPathShouldAcceptAbsoluteUserPathWithSubFolder() { + String mailboxName = adjustToTestDelimiter("mailboxName.subFolder"); + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter() + mailboxName)) + .isEqualTo(MailboxPath.forUser(USERNAME, mailboxName)); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPath() { - assertThat(pathConverter().buildFullPath("#user.username2.abc")) + public void buildFullPathShouldAcceptAbsoluteOtherUserPath() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username2.abc"))) .isEqualTo(MailboxPath.forUser(USERNAME2, "abc")); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPathWithDot() { - assertThat(pathConverter().buildFullPath("#user.username__with__dot.abc")) - .isEqualTo(MailboxPath.forUser(USERNAME_WITH_DOT, "abc")); + public void buildFullPathShouldAcceptAbsoluteOtherUserPathWithDelimiter() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username__with__delimiter.abc"))) + .isEqualTo(MailboxPath.forUser(adjustToTestDelimiter(USERNAME_WITH_DELIMITER), "abc")); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPathWithUnderscore() { - assertThat(pathConverter().buildFullPath("#user.username_-with_-underscore.abc")) + public void buildFullPathShouldAcceptAbsoluteOtherUserPathWithUnderscore() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username_-with_-underscore.abc"))) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_UNDERSCORE, "abc")); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPathWithSubfolder() { - assertThat(pathConverter().buildFullPath("#user.username2.abc.def")) - .isEqualTo(MailboxPath.forUser(USERNAME2, "abc.def")); + public void buildFullPathShouldAcceptAbsoluteOtherUserPathWithSubfolder() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username2.abc.def"))) + .isEqualTo(MailboxPath.forUser(USERNAME2, adjustToTestDelimiter("abc.def"))); } @Test - default void buildFullPathShouldDenyMailboxPathNotBelongingToTheUser() { + public void buildFullPathShouldDenyMailboxPathNotBelongingToTheUser() { assertThatThrownBy(() -> pathConverter().buildFullPath("#any")) .isInstanceOf(DeniedAccessOnSharedMailboxException.class); } @Test - default void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() { + public void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() { assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME, "abc"), mailboxSession)) .contains("abc"); } @Test - default void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() { + public void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() { assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME2, "abc"), mailboxSession)) - .contains("#user.username2.abc"); + .contains(adjustToTestDelimiter("#user.username2.abc")); } @Test - default void mailboxNameShouldEscapeDotInUsername() { - assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME_WITH_DOT, "abc"), mailboxSession)) - .contains("#user.username__with__dot.abc"); + public void mailboxNameShouldEscapeDelimiterInUsername() { + assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(adjustToTestDelimiter(USERNAME_WITH_DELIMITER), "abc"), mailboxSession)) + .contains(adjustToTestDelimiter("#user.username__with__delimiter.abc")); } @Test - default void mailboxNameShouldEscapeUnderscoreInUsername() { + public void mailboxNameShouldEscapeUnderscoreInUsername() { assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME_WITH_UNDERSCORE, "abc"), mailboxSession)) - .contains("#user.username_-with_-underscore.abc"); + .contains(adjustToTestDelimiter("#user.username_-with_-underscore.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() { + public void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() { assertThat(pathConverter().mailboxName(RELATIVE, new MailboxPath("#Shared", Username.of("marketing"), "abc"), mailboxSession)) - .contains("#Shared.marketing.abc"); + .contains(adjustToTestDelimiter("#Shared.marketing.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() { + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() { + String mailboxName = adjustToTestDelimiter("#private.abc"); assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME, "abc"), mailboxSession)) - .contains("#private.abc"); + .contains(mailboxName); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() { + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() { assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME2, "abc"), mailboxSession)) - .contains("#user.username2.abc"); + .contains(adjustToTestDelimiter("#user.username2.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() { + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() { assertThat(pathConverter().mailboxName(!RELATIVE, new MailboxPath("#Shared", Username.of("marketing"), "abc"), mailboxSession)) - .contains("#Shared.marketing.abc"); + .contains(adjustToTestDelimiter("#Shared.marketing.abc")); } @Nested - interface WithEmail { - MailboxSession mailboxSession = MailboxSessionUtil.create(USERNAME_WITH_MAIL); + public abstract class WithEmail { + public final MailboxSession mailboxWithEmailSession = MailboxSessionUtil.create(USERNAME_WITH_MAIL, pathDelimiter()); - PathConverter pathConverter(); + public abstract PathConverter pathConverter(); @Test - default void buildFullPathShouldAcceptNull() { + public void buildFullPathShouldAcceptNull() { assertThat(pathConverter().buildFullPath(null)) .isEqualTo(new MailboxPath("", USERNAME_WITH_MAIL, "")); } @Test - default void buildPathShouldAcceptEmpty() { + public void buildPathShouldAcceptEmpty() { assertThat(pathConverter().buildFullPath("")) .isEqualTo(new MailboxPath("", USERNAME_WITH_MAIL, "")); } @Test - default void buildPathShouldAcceptRelativeMailboxName() { + public void buildPathShouldAcceptRelativeMailboxName() { String mailboxName = "mailboxName"; assertThat(pathConverter().buildFullPath(mailboxName)) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, mailboxName)); } @Test - default void buildFullPathShouldAcceptUserNamespace() { + public void buildFullPathShouldAcceptUserNamespace() { assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE)) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, "")); } @Test - default void buildFullPathShouldAcceptUserNamespaceAndDelimiter() { - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER)) + public void buildFullPathShouldAcceptUserNamespaceAndDelimiter() { + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter())) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, "")); } @Test - default void buildFullPathShouldAcceptFullAbsoluteUserPath() { + public void buildFullPathShouldAcceptFullAbsoluteUserPath() { String mailboxName = "mailboxName"; - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER + mailboxName)) + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter() + mailboxName)) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, mailboxName)); } @Test - default void buildFullPathShouldAcceptRelativePathWithSubFolder() { - String mailboxName = "mailboxName" + PATH_DELIMITER + "subFolder"; + public void buildFullPathShouldAcceptRelativePathWithSubFolder() { + String mailboxName = "mailboxName" + pathDelimiter() + "subFolder"; assertThat(pathConverter().buildFullPath(mailboxName)) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, mailboxName)); } @Test - default void buildFullPathShouldAcceptAbsoluteUserPathWithSubFolder() { - String mailboxName = "mailboxName.subFolder"; - assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + PATH_DELIMITER + mailboxName)) + public void buildFullPathShouldAcceptAbsoluteUserPathWithSubFolder() { + String mailboxName = adjustToTestDelimiter("mailboxName.subFolder"); + assertThat(pathConverter().buildFullPath(MailboxConstants.USER_NAMESPACE + pathDelimiter() + mailboxName)) .isEqualTo(MailboxPath.forUser(USERNAME_WITH_MAIL, mailboxName)); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPath() { - assertThat(pathConverter().buildFullPath("#user.username2.abc")) + public void buildFullPathShouldAcceptAbsoluteOtherUserPath() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username2.abc"))) .isEqualTo(MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc")); } @Test - default void buildFullPathShouldAcceptAbsoluteOtherUserPathWithSubfolder() { - assertThat(pathConverter().buildFullPath("#user.username2.abc.def")) - .isEqualTo(MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc.def")); + public void buildFullPathShouldAcceptAbsoluteOtherUserPathWithSubfolder() { + assertThat(pathConverter().buildFullPath(adjustToTestDelimiter("#user.username2.abc.def"))) + .isEqualTo(MailboxPath.forUser(USERNAME2_WITH_MAIL, adjustToTestDelimiter("abc.def"))); } @Test - default void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() { - assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxSession)) + public void mailboxNameShouldReturnNameOnlyWhenRelativeAndUserMailbox() { + assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxWithEmailSession)) .contains("abc"); } @Test - default void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() { - assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxSession)) - .contains("#user.username2.abc"); + public void mailboxNameShouldReturnFQDNWhenRelativeAndOtherUserMailbox() { + assertThat(pathConverter().mailboxName(RELATIVE, MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxWithEmailSession)) + .contains(adjustToTestDelimiter("#user.username2.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() { - assertThat(pathConverter().mailboxName(RELATIVE, new MailboxPath("#Shared", Username.of("market...@apache.org"), "abc"), mailboxSession)) - .contains("#Shared.marketing.abc"); + public void mailboxNameShouldReturnFQDNWhenRelativeAndSharedMailbox() { + assertThat(pathConverter().mailboxName(RELATIVE, new MailboxPath("#Shared", Username.of("market...@apache.org"), "abc"), mailboxWithEmailSession)) + .contains(adjustToTestDelimiter("#Shared.marketing.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() { - assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxSession)) - .contains("#private.abc"); + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndUserMailbox() { + assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME_WITH_MAIL, "abc"), mailboxWithEmailSession)) + .contains(adjustToTestDelimiter("#private.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() { - assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxSession)) - .contains("#user.username2.abc"); + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndOtherUserMailbox() { + assertThat(pathConverter().mailboxName(!RELATIVE, MailboxPath.forUser(USERNAME2_WITH_MAIL, "abc"), mailboxWithEmailSession)) + .contains(adjustToTestDelimiter("#user.username2.abc")); } @Test - default void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() { - assertThat(pathConverter().mailboxName(!RELATIVE, new MailboxPath("#Shared", Username.of("market...@apache.org"), "abc"), mailboxSession)) - .contains("#Shared.marketing.abc"); + public void mailboxNameShouldReturnFQDNWhenNotRelativeAndSharedMailbox() { + assertThat(pathConverter().mailboxName(!RELATIVE, new MailboxPath("#Shared", Username.of("market...@apache.org"), "abc"), mailboxWithEmailSession)) + .contains(adjustToTestDelimiter("#Shared.marketing.abc")); } } } diff --git a/server/apps/cassandra-app/docker-configuration/jvm.properties b/server/apps/cassandra-app/docker-configuration/jvm.properties index 85e932e7c9..3c81157e45 100644 --- a/server/apps/cassandra-app/docker-configuration/jvm.properties +++ b/server/apps/cassandra-app/docker-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # Required to locate Cassandra driver configuration config.file=/root/conf/cassandra-driver.conf diff --git a/server/apps/cassandra-app/sample-configuration/jvm.properties b/server/apps/cassandra-app/sample-configuration/jvm.properties index 82ea594769..d763daefa8 100644 --- a/server/apps/cassandra-app/sample-configuration/jvm.properties +++ b/server/apps/cassandra-app/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # Required to locate Cassandra driver configuration config.file=conf/cassandra-driver.conf diff --git a/server/apps/distributed-app/docker-configuration/jvm.properties b/server/apps/distributed-app/docker-configuration/jvm.properties index 573d064bcc..3c81157e45 100644 --- a/server/apps/distributed-app/docker-configuration/jvm.properties +++ b/server/apps/distributed-app/docker-configuration/jvm.properties @@ -1,12 +1,18 @@ # ============================================= Extra JVM System Properties =========================================== # To avoid clutter on the command line, any properties in this file will be added as system properties on server start. -# Required to locate Cassandra driver configuration -config.file=/root/conf/cassandra-driver.conf - # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + +# Required to locate Cassandra driver configuration +config.file=/root/conf/cassandra-driver.conf + # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. # Below, data is stored in memory. Above data is stored on disk. diff --git a/server/apps/distributed-app/sample-configuration/jvm.properties b/server/apps/distributed-app/sample-configuration/jvm.properties index a98626760d..600d91b329 100644 --- a/server/apps/distributed-app/sample-configuration/jvm.properties +++ b/server/apps/distributed-app/sample-configuration/jvm.properties @@ -1,11 +1,17 @@ # ============================================= Extra JVM System Properties =========================================== # To avoid clutter on the command line, any properties in this file will be added as system properties on server start. +# Example: If you need an option -Dmy.property=whatever, you can instead add it here as +# my.property=whatever + # Required to locate Cassandra driver configuration config.file=conf/cassandra-driver.conf -# Example: If you need an option -Dmy.property=whatever, you can instead add it here as -# my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. diff --git a/server/apps/distributed-pop3-app/docker-configuration/jvm.properties b/server/apps/distributed-pop3-app/docker-configuration/jvm.properties index 85e932e7c9..3c81157e45 100644 --- a/server/apps/distributed-pop3-app/docker-configuration/jvm.properties +++ b/server/apps/distributed-pop3-app/docker-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # Required to locate Cassandra driver configuration config.file=/root/conf/cassandra-driver.conf diff --git a/server/apps/distributed-pop3-app/sample-configuration/jvm.properties b/server/apps/distributed-pop3-app/sample-configuration/jvm.properties index 3901fdf50c..37646e5cec 100644 --- a/server/apps/distributed-pop3-app/sample-configuration/jvm.properties +++ b/server/apps/distributed-pop3-app/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # Required to locate Cassandra driver configuration config.file=conf/cassandra-driver.conf diff --git a/server/apps/jpa-app/sample-configuration/jvm.properties b/server/apps/jpa-app/sample-configuration/jvm.properties index d6d2e0ae4b..8cf7dfb861 100644 --- a/server/apps/jpa-app/sample-configuration/jvm.properties +++ b/server/apps/jpa-app/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. # Below, data is stored in memory. Above data is stored on disk. diff --git a/server/apps/jpa-smtp-app/sample-configuration/jvm.properties b/server/apps/jpa-smtp-app/sample-configuration/jvm.properties index 04cfad0b6c..a90fd7a31f 100644 --- a/server/apps/jpa-smtp-app/sample-configuration/jvm.properties +++ b/server/apps/jpa-smtp-app/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. # Below, data is stored in memory. Above data is stored on disk. diff --git a/server/apps/memory-app/sample-configuration/jvm.properties b/server/apps/memory-app/sample-configuration/jvm.properties index 317261dd03..c362f00894 100644 --- a/server/apps/memory-app/sample-configuration/jvm.properties +++ b/server/apps/memory-app/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. # Below, data is stored in memory. Above data is stored on disk. diff --git a/server/apps/scaling-pulsar-smtp/sample-configuration/jvm.properties b/server/apps/scaling-pulsar-smtp/sample-configuration/jvm.properties index 579b688dcb..886dec96f5 100644 --- a/server/apps/scaling-pulsar-smtp/sample-configuration/jvm.properties +++ b/server/apps/scaling-pulsar-smtp/sample-configuration/jvm.properties @@ -4,6 +4,12 @@ # Example: If you need an option -Dmy.property=whatever, you can instead add it here as # my.property=whatever +# The delimiter used to separate parent/child folders. +# Optional. Allowed values are: dot (will use '.' as delimiter), slash (will use '/' as delimiter). +# WARNING: This value should only be changed when setting up a new deployment. Changing the parameter for an existing deployments +# will likely lead to failure of some system components, as occurrences of old delimiter will still be present in the database/data store. +# james.mailbox.folder.delimiter=dot + # (Optional). String (size, integer + size units, example: `12 KIB`, supported units are bytes KIB MIB GIB TIB). Defaults to 100KIB. # This governs the threshold MimeMessageInputStreamSource relies on for storing MimeMessage content on disk. # Below, data is stored in memory. Above data is stored on disk. --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org