diff --git a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java index 1cd389646..9af2dcd2f 100644 --- a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java +++ b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java @@ -378,7 +378,6 @@ public Collection run(Path scratchPath) { var jsonWebrevPath = scratchPath.resolve("mlbridge-webrevs").resolve("json"); var htmlWebrevPath = scratchPath.resolve("mlbridge-webrevs").resolve("html"); - var listServer = MailingListServerFactory.createMailmanServer(bot.listArchive(), bot.smtpServer(), bot.sendInterval()); var archiver = new ReviewArchive(pr, bot.emailAddress()); var lastDraftTime = pr.lastMarkedAsDraftTime().orElse(null); @@ -449,7 +448,7 @@ public Collection run(Path scratchPath) { .headers(bot.headers()) .recipients(recipients) .build(); - listServer.post(filteredEmail); + bot.mailingListServer().post(filteredEmail); } // Mixing forge time and local time for the latency is not ideal, but the best // we can do here. diff --git a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java index 862c78f0f..0d7fac1bd 100644 --- a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java +++ b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java @@ -35,7 +35,7 @@ import java.util.stream.Collectors; public class MailingListArchiveReaderBot implements Bot { - private final MailingListReader list; + private final MailingListReader mailingListReader; private final HostedRepository repository; private final Map parsedConversations = new HashMap<>(); private final Map resolvedPullRequests = new HashMap<>(); @@ -44,8 +44,8 @@ public class MailingListArchiveReaderBot implements Bot { private static final Pattern PULL_REQUEST_LINK_PATTERN = Pattern.compile("^(?:PR: |Pull request:\\R)(.*?)$", Pattern.MULTILINE); private final Logger log = Logger.getLogger("org.openjdk.skara.bots.mlbridge"); - MailingListArchiveReaderBot(MailingListReader list, HostedRepository repository) { - this.list = list; + MailingListArchiveReaderBot(MailingListReader mailingListReader, HostedRepository repository) { + this.mailingListReader = mailingListReader; this.repository = repository; } @@ -131,7 +131,7 @@ synchronized void inspect(Conversation conversation) { @Override public List getPeriodicItems() { - var readerItems = new ArchiveReaderWorkItem(this, list); + var readerItems = new ArchiveReaderWorkItem(this, mailingListReader); var ret = new ArrayList(); ret.add(readerItems); @@ -145,6 +145,10 @@ public List getPeriodicItems() { return ret; } + public MailingListReader mailingListReader() { + return mailingListReader; + } + @Override public String name() { return MailingListBridgeBotFactory.NAME; diff --git a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java index 0fff80acc..c3747f7b4 100644 --- a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java +++ b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java @@ -32,6 +32,7 @@ import java.util.*; import java.util.logging.Logger; import java.util.regex.Pattern; +import org.openjdk.skara.mailinglist.MailingListServer; public class MailingListBridgeBot implements Bot { private final EmailAddress emailAddress; @@ -43,19 +44,17 @@ public class MailingListBridgeBot implements Bot { private final List lists; private final Set ignoredUsers; private final Set ignoredComments; - private final URI listArchive; - private final String smtpServer; private final WebrevStorage webrevStorage; private final Set readyLabels; private final Map readyComments; private final Map headers; private final URI issueTracker; - private final Duration sendInterval; private final Duration cooldown; private final boolean repoInSubject; private final Pattern branchInSubject; private final Path seedStorage; private final PullRequestPoller poller; + private final MailingListServer mailingListServer; private final Logger log = Logger.getLogger("org.openjdk.skara.bots.mlbridge"); @@ -63,13 +62,13 @@ public class MailingListBridgeBot implements Bot { MailingListBridgeBot(EmailAddress from, HostedRepository repo, HostedRepository archive, String archiveRef, HostedRepository censusRepo, String censusRef, List lists, - Set ignoredUsers, Set ignoredComments, URI listArchive, String smtpServer, + Set ignoredUsers, Set ignoredComments, HostedRepository webrevStorageHTMLRepository, HostedRepository webrevStorageJSONRepository, String webrevStorageRef, Path webrevStorageBase, URI webrevStorageBaseUri, boolean webrevGenerateHTML, boolean webrevGenerateJSON, Set readyLabels, Map readyComments, URI issueTracker, Map headers, - Duration sendInterval, Duration cooldown, boolean repoInSubject, Pattern branchInSubject, - Path seedStorage) { + Duration cooldown, boolean repoInSubject, Pattern branchInSubject, + Path seedStorage, MailingListServer mailingListServer) { emailAddress = from; codeRepo = repo; archiveRepo = archive; @@ -79,17 +78,15 @@ public class MailingListBridgeBot implements Bot { this.lists = lists; this.ignoredUsers = ignoredUsers; this.ignoredComments = ignoredComments; - this.listArchive = listArchive; - this.smtpServer = smtpServer; this.readyLabels = readyLabels; this.readyComments = readyComments; this.headers = headers; this.issueTracker = issueTracker; - this.sendInterval = sendInterval; this.cooldown = cooldown; this.repoInSubject = repoInSubject; this.branchInSubject = branchInSubject; this.seedStorage = seedStorage; + this.mailingListServer = mailingListServer; webrevStorage = new WebrevStorage(webrevStorageHTMLRepository, webrevStorageJSONRepository, webrevStorageRef, webrevStorageBase, webrevStorageBaseUri, from, @@ -129,10 +126,6 @@ List lists() { return lists; } - Duration sendInterval() { - return sendInterval; - } - Duration cooldown() { return cooldown; } @@ -145,14 +138,6 @@ Set ignoredComments() { return ignoredComments; } - URI listArchive() { - return listArchive; - } - - String smtpServer() { - return smtpServer; - } - WebrevStorage webrevStorage() { return webrevStorage; } @@ -193,6 +178,10 @@ public void setLabelsUpdated(boolean labelsUpdated) { this.labelsUpdated = labelsUpdated; } + public MailingListServer mailingListServer() { + return mailingListServer; + } + @Override public List getPeriodicItems() { List ret = new LinkedList<>(); diff --git a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java index 4226f8b9f..89679b250 100644 --- a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java +++ b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java @@ -22,6 +22,7 @@ */ package org.openjdk.skara.bots.mlbridge; +import org.openjdk.skara.mailinglist.MailingListServer; import org.openjdk.skara.vcs.Branch; import org.openjdk.skara.vcs.VCS; import org.openjdk.skara.email.EmailAddress; @@ -43,8 +44,6 @@ public class MailingListBridgeBotBuilder { private List lists; private Set ignoredUsers = Set.of(); private Set ignoredComments = Set.of(); - private URI listArchive; - private String smtpServer; private HostedRepository webrevStorageHTMLRepository; private HostedRepository webrevStorageJSONRepository; private String webrevStorageRef; @@ -56,11 +55,11 @@ public class MailingListBridgeBotBuilder { private Map readyComments = Map.of(); private URI issueTracker; private Map headers = Map.of(); - private Duration sendInterval = Duration.ZERO; private Duration cooldown = Duration.ZERO; private boolean repoInSubject = false; private Pattern branchInSubject = Pattern.compile("a^"); // Does not match anything private Path seedStorage = null; + private MailingListServer mailingListServer; MailingListBridgeBotBuilder() { } @@ -110,16 +109,6 @@ public MailingListBridgeBotBuilder ignoredComments(Set ignoredComments) return this; } - public MailingListBridgeBotBuilder listArchive(URI listArchive) { - this.listArchive = listArchive; - return this; - } - - public MailingListBridgeBotBuilder smtpServer(String smtpServer) { - this.smtpServer = smtpServer; - return this; - } - public MailingListBridgeBotBuilder webrevStorageHTMLRepository(HostedRepository webrevStorageHTMLRepository) { this.webrevStorageHTMLRepository = webrevStorageHTMLRepository; return this; @@ -175,11 +164,6 @@ public MailingListBridgeBotBuilder headers(Map headers) { return this; } - public MailingListBridgeBotBuilder sendInterval(Duration sendInterval) { - this.sendInterval = sendInterval; - return this; - } - public MailingListBridgeBotBuilder cooldown(Duration cooldown) { this.cooldown = cooldown; return this; @@ -200,12 +184,17 @@ public MailingListBridgeBotBuilder seedStorage(Path seedStorage) { return this; } + public MailingListBridgeBotBuilder mailingListServer(MailingListServer mailingListServer) { + this.mailingListServer = mailingListServer; + return this; + } + public MailingListBridgeBot build() { return new MailingListBridgeBot(from, repo, archive, archiveRef, censusRepo, censusRef, lists, - ignoredUsers, ignoredComments, listArchive, smtpServer, + ignoredUsers, ignoredComments, webrevStorageHTMLRepository, webrevStorageJSONRepository, webrevStorageRef, webrevStorageBase, webrevStorageBaseUri, webrevGenerateHTML, webrevGenerateJSON, - readyLabels, readyComments, issueTracker, headers, sendInterval, - cooldown, repoInSubject, branchInSubject, seedStorage); + readyLabels, readyComments, issueTracker, headers, + cooldown, repoInSubject, branchInSubject, seedStorage, mailingListServer); } } diff --git a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java index f45acdeeb..d259aa8b7 100644 --- a/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java +++ b/bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java @@ -22,9 +22,11 @@ */ package org.openjdk.skara.bots.mlbridge; +import java.net.URI; import org.openjdk.skara.bot.*; import org.openjdk.skara.email.EmailAddress; import org.openjdk.skara.mailinglist.MailingListReader; +import org.openjdk.skara.mailinglist.MailingListServer; import org.openjdk.skara.network.URIBuilder; import org.openjdk.skara.json.*; import org.openjdk.skara.mailinglist.MailingListServerFactory; @@ -77,8 +79,13 @@ public List create(BotConfiguration configuration) { .map(pattern -> Pattern.compile(pattern, Pattern.MULTILINE | Pattern.DOTALL)) .collect(Collectors.toSet()); var listArchive = URIBuilder.base(specific.get("server").get("archive").asString()).build(); + String archiveType = null; + if (specific.get("server").contains("type")) { + archiveType = specific.get("server").get("type").asString(); + } var listSmtp = specific.get("server").get("smtp").asString(); - var interval = specific.get("server").contains("interval") ? Duration.parse(specific.get("server").get("interval").asString()) : Duration.ofSeconds(1); + var interval = specific.get("server").contains("interval") ? + Duration.parse(specific.get("server").get("interval").asString()) : Duration.ofSeconds(1); var webrevHTMLRepo = configuration.repository(specific.get("webrevs").get("repository").get("html").asString()); var webrevJSONRepo = configuration.repository(specific.get("webrevs").get("repository").get("json").asString()); @@ -101,7 +108,7 @@ public List create(BotConfiguration configuration) { if (specific.get("server").contains("etag")) { useEtag = specific.get("server").get("etag").asBoolean(); } - var mailmanServer = MailingListServerFactory.createMailmanServer(listArchive, listSmtp, Duration.ZERO, useEtag); + MailingListServer mailmanServer = createMailmanServer(archiveType, listArchive, listSmtp, interval, useEtag); var mailingListReaderMap = new HashMap, MailingListReader>(); @@ -161,8 +168,6 @@ public List create(BotConfiguration configuration) { .lists(lists) .ignoredUsers(ignoredUsers) .ignoredComments(ignoredComments) - .listArchive(listArchive) - .smtpServer(listSmtp) .webrevStorageHTMLRepository(webrevHTMLRepo) .webrevStorageJSONRepository(webrevJSONRepo) .webrevStorageRef(webrevRef) @@ -174,9 +179,9 @@ public List create(BotConfiguration configuration) { .readyComments(readyComments) .issueTracker(issueTracker) .headers(headers) - .sendInterval(interval) .cooldown(cooldown) - .seedStorage(configuration.storageFolder().resolve("seeds")); + .seedStorage(configuration.storageFolder().resolve("seeds")) + .mailingListServer(mailmanServer); if (repoConfig.contains("reponame")) { botBuilder.repoInSubject(repoConfig.get("reponame").asBoolean()); @@ -189,4 +194,17 @@ public List create(BotConfiguration configuration) { return ret; } + + private static MailingListServer createMailmanServer(String archiveType, URI listArchive, String listSmtp, + Duration sendInterval, boolean useEtag) { + MailingListServer mailmanServer; + if (archiveType == null || archiveType.equals("mailman2")) { + mailmanServer = MailingListServerFactory.createMailman2Server(listArchive, listSmtp, sendInterval, useEtag); + } else if (archiveType.equals("mailman3")) { + mailmanServer = MailingListServerFactory.createMailman3Server(listArchive, listSmtp, sendInterval); + } else { + throw new RuntimeException("Invalid server archive type: " + archiveType); + } + return mailmanServer; + } } diff --git a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java index 830666f5a..275b58c7c 100644 --- a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java +++ b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java @@ -38,7 +38,7 @@ public class LabelsUpdaterTests { @Test void simple(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); - var listServer = new TestMailmanServer();) { + var listServer = TestMailmanServer.createV2();) { var targetRepo = credentials.getHostedRepository(); var listAddress = EmailAddress.parse(listServer.createList("test")); var mlBot = MailingListBridgeBot.newBuilder() @@ -70,7 +70,7 @@ void simple(TestInfo testInfo) throws IOException { @Test void update(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); - var listServer = new TestMailmanServer();) { + var listServer = TestMailmanServer.createV2();) { var targetRepo = credentials.getHostedRepository(); var listAddress = EmailAddress.parse(listServer.createList("test")); var listAddress2 = EmailAddress.parse(listServer.createList("test2")); diff --git a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java index 6ae36d563..273eae262 100644 --- a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java +++ b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java @@ -59,7 +59,7 @@ private void addReply(Conversation conversation, EmailAddress recipient, Mailing void simpleArchive(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -68,6 +68,8 @@ void simpleArchive(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -75,18 +77,14 @@ void simpleArchive(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); - // The mailing list as well - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), - Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var readerBot = new MailingListArchiveReaderBot(mailmanList, archive); @@ -134,7 +132,7 @@ void simpleArchive(TestInfo testInfo) throws IOException { void rememberBridged(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -143,6 +141,8 @@ void rememberBridged(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -150,19 +150,15 @@ void rememberBridged(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .repoInSubject(true) + .mailingListServer(mailmanServer) .build(); - // The mailing list as well - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), - Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var readerBot = new MailingListArchiveReaderBot(mailmanList, archive); @@ -211,7 +207,7 @@ void rememberBridged(TestInfo testInfo) throws IOException { void largeEmail(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -220,6 +216,9 @@ void largeEmail(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + // The mailing list as well + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -227,18 +226,14 @@ void largeEmail(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); - // The mailing list as well - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), - Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var readerBot = new MailingListArchiveReaderBot(mailmanList, archive); @@ -293,7 +288,7 @@ void largeEmail(TestInfo testInfo) throws IOException { void branchMissing(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -302,6 +297,8 @@ void branchMissing(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -309,13 +306,12 @@ void branchMissing(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository diff --git a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java index 0b7f4ddc1..17735ae72 100644 --- a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java +++ b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java @@ -25,6 +25,8 @@ import org.junit.jupiter.api.Test; import org.openjdk.skara.bot.Bot; import org.openjdk.skara.json.JWCC; +import org.openjdk.skara.mailinglist.MailingListReader; +import org.openjdk.skara.mailinglist.MailingListServer; import org.openjdk.skara.test.TemporaryDirectory; import org.openjdk.skara.test.TestBotFactory; import org.openjdk.skara.test.TestHost; @@ -165,72 +167,79 @@ public void testCreate() { assertEquals(2, mailingListArchiveReaderBots.size()); assertEquals(3, mailingListBridgeBots.size()); - assertEquals("MailingListArchiveReaderBot@repo3", mailingListArchiveReaderBots.get(0).toString()); - assertEquals("MailingListArchiveReaderBot@repo5", mailingListArchiveReaderBots.get(1).toString()); + MailingListArchiveReaderBot mailingListArchiveReaderBot1 = + (MailingListArchiveReaderBot) mailingListArchiveReaderBots.get(0); + assertEquals("MailingListArchiveReaderBot@repo3", mailingListArchiveReaderBot1.toString()); + MailingListReader readerBot1MailingListReader = mailingListArchiveReaderBot1.mailingListReader(); + assertTrue(readerBot1MailingListReader.getClass().getName().contains("Mailman2"), + readerBot1MailingListReader.getClass().getName()); + + MailingListArchiveReaderBot mailingListArchiveReaderBot2 = + (MailingListArchiveReaderBot) mailingListArchiveReaderBots.get(1); + assertEquals("MailingListArchiveReaderBot@repo5", mailingListArchiveReaderBot2.toString()); + MailingListReader readerBot2MailingListReader = mailingListArchiveReaderBot2.mailingListReader(); + assertTrue(readerBot2MailingListReader.getClass().getName().contains("Mailman2"), + readerBot2MailingListReader.getClass().getName()); MailingListBridgeBot mailingListBridgeBot1 = (MailingListBridgeBot) mailingListBridgeBots.get(0); assertEquals("MailingListBridgeBot@repo3", mailingListBridgeBot1.toString()); assertEquals("repo3", mailingListBridgeBot1.codeRepo().name()); assertEquals("archive", mailingListBridgeBot1.archiveRepo().name()); assertEquals("master", mailingListBridgeBot1.archiveRef()); - assertEquals("https://mail.test.org/test/", mailingListBridgeBot1.listArchive().toString()); assertEquals("master", mailingListBridgeBot1.censusRef()); assertEquals("census", mailingListBridgeBot1.censusRepo().name()); assertEquals("", mailingListBridgeBot1.lists().get(0).list().toString()); assertEquals("[ignore1[bot], ignore2[bot], ignore4[bot], ignore3[bot]]", mailingListBridgeBot1.ignoredUsers().toString()); assertEquals("[]", mailingListBridgeBot1.ignoredComments().toString()); - assertEquals("0.0.0.0", mailingListBridgeBot1.smtpServer()); assertEquals("[rfr]", mailingListBridgeBot1.readyLabels().toString()); assertEquals("{test_user[bot]=}", mailingListBridgeBot1.readyComments().toString()); assertEquals("{Approved=test}", mailingListBridgeBot1.headers().toString()); assertEquals("https://bugs.test.org/browse/", mailingListBridgeBot1.issueTracker().toString()); - assertEquals(Duration.ofSeconds(5), mailingListBridgeBot1.sendInterval()); assertEquals(Duration.ofMinutes(2), mailingListBridgeBot1.cooldown()); assertFalse(mailingListBridgeBot1.repoInSubject()); assertEquals("dev", mailingListBridgeBot1.branchInSubject().toString()); - + MailingListServer bridgeBot1MailingListServer = mailingListBridgeBot1.mailingListServer(); + assertTrue(bridgeBot1MailingListServer.getClass().getName().contains("Mailman2")); MailingListBridgeBot mailingListBridgeBot2 = (MailingListBridgeBot) mailingListBridgeBots.get(1); assertEquals("MailingListBridgeBot@repo4", mailingListBridgeBot2.toString()); assertEquals("repo4", mailingListBridgeBot2.codeRepo().name()); assertEquals("archive", mailingListBridgeBot2.archiveRepo().name()); assertEquals("master", mailingListBridgeBot2.archiveRef()); - assertEquals("https://mail.test.org/test/", mailingListBridgeBot2.listArchive().toString()); assertEquals("master", mailingListBridgeBot2.censusRef()); assertEquals("census", mailingListBridgeBot2.censusRepo().name()); assertEquals("", mailingListBridgeBot2.lists().get(0).list().toString()); assertEquals("[ignore1[bot], ignore2[bot], ignore4[bot], ignore3[bot]]", mailingListBridgeBot2.ignoredUsers().toString()); assertEquals("[]", mailingListBridgeBot2.ignoredComments().toString()); - assertEquals("0.0.0.0", mailingListBridgeBot2.smtpServer()); assertEquals("[rfr]", mailingListBridgeBot2.readyLabels().toString()); assertEquals("{test_user[bot]=}", mailingListBridgeBot2.readyComments().toString()); assertEquals(0, mailingListBridgeBot2.headers().size()); assertEquals("https://bugs.test.org/browse/", mailingListBridgeBot2.issueTracker().toString()); - assertEquals(Duration.ofSeconds(5), mailingListBridgeBot2.sendInterval()); assertEquals(Duration.ofMinutes(2), mailingListBridgeBot2.cooldown()); assertTrue(mailingListBridgeBot2.repoInSubject()); + MailingListServer bridgeBot2MailingListServer = mailingListBridgeBot2.mailingListServer(); + assertTrue(bridgeBot2MailingListServer.getClass().getName().contains("Mailman2")); MailingListBridgeBot mailingListBridgeBot3 = (MailingListBridgeBot) mailingListBridgeBots.get(2); assertEquals("MailingListBridgeBot@repo5", mailingListBridgeBot3.toString()); assertEquals("repo5", mailingListBridgeBot3.codeRepo().name()); assertEquals("archive", mailingListBridgeBot3.archiveRepo().name()); assertEquals("master", mailingListBridgeBot3.archiveRef()); - assertEquals("https://mail.test.org/test/", mailingListBridgeBot3.listArchive().toString()); assertEquals("master", mailingListBridgeBot3.censusRef()); assertEquals("census", mailingListBridgeBot3.censusRepo().name()); assertEquals("", mailingListBridgeBot3.lists().get(0).list().toString()); assertEquals("[label1, label2, label3]", mailingListBridgeBot3.lists().get(0).labels().toString()); assertEquals("[ignore1[bot], ignore2[bot], ignore4[bot], ignore3[bot]]", mailingListBridgeBot3.ignoredUsers().toString()); assertEquals("[]", mailingListBridgeBot3.ignoredComments().toString()); - assertEquals("0.0.0.0", mailingListBridgeBot3.smtpServer()); assertEquals("[rfr]", mailingListBridgeBot3.readyLabels().toString()); assertEquals("{test_user[bot]=}", mailingListBridgeBot3.readyComments().toString()); assertEquals("{Approved=test5}", mailingListBridgeBot3.headers().toString()); assertEquals("https://test.test.com/issueProject", mailingListBridgeBot3.issueTracker().toString()); - assertEquals(Duration.ofSeconds(5), mailingListBridgeBot3.sendInterval()); assertEquals(Duration.ofMinutes(2), mailingListBridgeBot3.cooldown()); assertTrue(mailingListBridgeBot3.repoInSubject()); assertEquals("master", mailingListBridgeBot3.branchInSubject().toString()); + MailingListServer bridgeBot3MailingListServer = mailingListBridgeBot3.mailingListServer(); + assertTrue(bridgeBot3MailingListServer.getClass().getName().contains("Mailman2")); } } -} \ No newline at end of file +} diff --git a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java index 8bf64d217..7668aba27 100644 --- a/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java +++ b/bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java @@ -111,7 +111,7 @@ void simpleArchive(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -120,6 +120,7 @@ void simpleArchive(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -128,8 +129,7 @@ void simpleArchive(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) + .mailingListServer(mailmanServer) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -138,7 +138,6 @@ void simpleArchive(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) .build(); // Populate the projects repository @@ -230,7 +229,6 @@ void simpleArchive(TestInfo testInfo) throws IOException { // The mailing list as well listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -307,7 +305,7 @@ void archiveIntegrated(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -316,6 +314,8 @@ void archiveIntegrated(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -323,13 +323,12 @@ void archiveIntegrated(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -400,7 +399,7 @@ void archiveLegacyIntegrated(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -409,6 +408,8 @@ void archiveLegacyIntegrated(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -416,13 +417,12 @@ void archiveLegacyIntegrated(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -474,7 +474,7 @@ void archiveDirectToIntegrated(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -483,6 +483,8 @@ void archiveDirectToIntegrated(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -490,13 +492,12 @@ void archiveDirectToIntegrated(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -553,7 +554,7 @@ void archiveIntegratedRetainPrefix(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -562,6 +563,8 @@ void archiveIntegratedRetainPrefix(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -569,14 +572,13 @@ void archiveIntegratedRetainPrefix(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .readyLabels(Set.of("rfr")) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -630,7 +632,7 @@ void archiveClosed(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -639,6 +641,8 @@ void archiveClosed(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -646,14 +650,13 @@ void archiveClosed(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .readyLabels(Set.of("rfr")) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -719,7 +722,7 @@ void archiveFailedAutoMerge(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -728,6 +731,8 @@ void archiveFailedAutoMerge(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -735,13 +740,12 @@ void archiveFailedAutoMerge(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -773,7 +777,7 @@ void reviewComment(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -782,6 +786,8 @@ void reviewComment(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -789,13 +795,12 @@ void reviewComment(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -835,7 +840,6 @@ void reviewComment(TestInfo testInfo) throws IOException { assertFalse(archiveContains(archiveFolder.path(), "Don't mind me")); // The mailing list as well - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -882,7 +886,7 @@ void combineComments(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -890,19 +894,20 @@ void combineComments(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -936,7 +941,6 @@ void combineComments(TestInfo testInfo) throws IOException { assertEquals(2, archiveContainsCount(archiveFolder.path(), "^On.*wrote:")); // As well as the mailing list - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -979,7 +983,7 @@ void commentThreading(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -989,19 +993,20 @@ void commentThreading(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1057,7 +1062,6 @@ void commentThreading(TestInfo testInfo) throws IOException { assertTrue(archiveText.indexOf("Looks fine") < archiveText.indexOf("The final review comment")); // Check the mailing list - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -1108,7 +1112,7 @@ void commentThreadingSeparated(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -1118,19 +1122,20 @@ void commentThreadingSeparated(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1180,7 +1185,7 @@ void commentWithMention(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -1190,19 +1195,20 @@ void commentWithMention(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1244,7 +1250,7 @@ void reviewCommentWithMention(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -1254,19 +1260,20 @@ void reviewCommentWithMention(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1309,7 +1316,7 @@ void commentWithQuote(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -1319,19 +1326,20 @@ void commentWithQuote(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1374,7 +1382,7 @@ void reviewContext(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1382,19 +1390,20 @@ void reviewContext(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1430,7 +1439,7 @@ void multipleReviewContexts(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1438,19 +1447,20 @@ void multipleReviewContexts(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1506,7 +1516,7 @@ void filterComments(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1514,19 +1524,20 @@ void filterComments(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1595,7 +1606,7 @@ void incrementalChanges(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1604,19 +1615,20 @@ void incrementalChanges(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1667,7 +1679,6 @@ void incrementalChanges(TestInfo testInfo) throws IOException { assertEquals(1, webrevComments.size()); // Check that sender address is set properly - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -1706,7 +1717,7 @@ void forcePushed(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository("author"); var main = credentials.getHostedRepository("main"); @@ -1715,19 +1726,20 @@ void forcePushed(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var sender = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(sender) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1775,7 +1787,6 @@ void forcePushed(TestInfo testInfo) throws IOException { assertEquals(1, webrevComments.size()); // Check that sender address is set properly - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -1793,7 +1804,7 @@ void rebased(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository("author"); var main = credentials.getHostedRepository("main"); @@ -1802,19 +1813,20 @@ void rebased(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var sender = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(sender) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1869,7 +1881,6 @@ void rebased(TestInfo testInfo) throws IOException { assertEquals(1, webrevComments.size()); // Check that sender address is set properly - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -1887,7 +1898,7 @@ void incrementalAfterRebase(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1895,6 +1906,8 @@ void incrementalAfterRebase(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var sender = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(sender) .repo(author) @@ -1902,13 +1915,12 @@ void incrementalAfterRebase(TestInfo testInfo) throws IOException { .archiveRef("archive") .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -1966,7 +1978,7 @@ void mergeWebrev(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -1975,6 +1987,8 @@ void mergeWebrev(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -1982,13 +1996,12 @@ void mergeWebrev(TestInfo testInfo) throws IOException { .archiveRef("archive") .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2052,7 +2065,7 @@ void mergeWebrevConflict(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2061,6 +2074,8 @@ void mergeWebrevConflict(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -2068,13 +2083,12 @@ void mergeWebrevConflict(TestInfo testInfo) throws IOException { .archiveRef("archive") .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2124,7 +2138,7 @@ void mergeWebrevNoConflict(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2133,6 +2147,8 @@ void mergeWebrevNoConflict(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -2140,13 +2156,12 @@ void mergeWebrevNoConflict(TestInfo testInfo) throws IOException { .archiveRef("archive") .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2195,7 +2210,7 @@ void skipAddingExistingWebrev(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2204,6 +2219,8 @@ void skipAddingExistingWebrev(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -2211,13 +2228,12 @@ void skipAddingExistingWebrev(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2275,7 +2291,7 @@ void notifyReviewVerdicts(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2285,19 +2301,20 @@ void notifyReviewVerdicts(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2344,7 +2361,6 @@ void notifyReviewVerdicts(TestInfo testInfo) throws IOException { listServer.processIncoming(); listServer.processIncoming(); listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertTrue(conversations.get(0).allMessages().get(1).body().contains("hosted.git/pr/1/review/0")); @@ -2368,7 +2384,7 @@ void ignoreComments(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var ignored = credentials.getHostedRepository(); @@ -2377,6 +2393,8 @@ void ignoreComments(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -2385,13 +2403,12 @@ void ignoreComments(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of(Pattern.compile("ignore this comment", Pattern.MULTILINE | Pattern.DOTALL))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2434,7 +2451,7 @@ void replyToEmptyReview(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var reviewer = credentials.getHostedRepository(); @@ -2444,19 +2461,20 @@ void replyToEmptyReview(TestInfo testInfo) throws IOException { .addReviewer(reviewer.forge().currentUser().id()) .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2495,7 +2513,7 @@ void cooldown(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var bot = credentials.getHostedRepository(); var author = credentials.getHostedRepository(); @@ -2504,6 +2522,8 @@ void cooldown(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBotBuilder = MailingListBridgeBot.newBuilder() .from(from) .repo(bot) @@ -2511,13 +2531,12 @@ void cooldown(TestInfo testInfo) throws IOException { .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) - .issueTracker(URIBuilder.base("http://issues.test/browse/").build()); + .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer); // Populate the projects repository var reviewFile = Path.of("reviewfile.txt"); @@ -2560,7 +2579,7 @@ void cooldownNewRevision(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var bot = credentials.getHostedRepository(); var author = credentials.getHostedRepository(); @@ -2569,6 +2588,8 @@ void cooldownNewRevision(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBotBuilder = MailingListBridgeBot.newBuilder() .from(from) .repo(bot) @@ -2576,13 +2597,12 @@ void cooldownNewRevision(TestInfo testInfo) throws IOException { .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) - .issueTracker(URIBuilder.base("http://issues.test/browse/").build()); + .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer); // Populate the projects repository var reviewFile = Path.of("reviewfile.txt"); @@ -2626,7 +2646,7 @@ void retryAfterCooldown(TestInfo testInfo) throws IOException, InterruptedExcept try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var bot = credentials.getHostedRepository(); var author = credentials.getHostedRepository(); @@ -2636,6 +2656,8 @@ void retryAfterCooldown(TestInfo testInfo) throws IOException, InterruptedExcept .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); var cooldown = Duration.ofMillis(500); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBotBuilder = MailingListBridgeBot.newBuilder() .from(from) .repo(bot) @@ -2643,13 +2665,12 @@ void retryAfterCooldown(TestInfo testInfo) throws IOException, InterruptedExcept .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) - .issueTracker(URIBuilder.base("http://issues.test/browse/").build()); + .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer); // Populate the projects repository var reviewFile = Path.of("reviewfile.txt"); @@ -2718,7 +2739,7 @@ void branchPrefix(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2726,20 +2747,21 @@ void branchPrefix(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .branchInSubject(Pattern.compile(".*")) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2775,7 +2797,7 @@ void repoPrefix(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2783,20 +2805,21 @@ void repoPrefix(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .repoInSubject(true) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2832,7 +2855,7 @@ void repoAndBranchPrefix(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2840,14 +2863,14 @@ void repoAndBranchPrefix(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -2855,6 +2878,7 @@ void repoAndBranchPrefix(TestInfo testInfo) throws IOException { .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .repoInSubject(true) .branchInSubject(Pattern.compile(".*")) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -2890,7 +2914,7 @@ void retryNewRevisionAfterCooldown(TestInfo testInfo) throws IOException, Interr try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var bot = credentials.getHostedRepository(); var author = credentials.getHostedRepository(); @@ -2900,6 +2924,8 @@ void retryNewRevisionAfterCooldown(TestInfo testInfo) throws IOException, Interr .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); var cooldown = Duration.ofMillis(500); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBotBuilder = MailingListBridgeBot.newBuilder() .from(from) .repo(bot) @@ -2907,13 +2933,12 @@ void retryNewRevisionAfterCooldown(TestInfo testInfo) throws IOException, Interr .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) - .issueTracker(URIBuilder.base("http://issues.test/browse/").build()); + .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer); // Populate the projects repository var reviewFile = Path.of("reviewfile.txt"); @@ -2983,7 +3008,7 @@ void multipleRecipients(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -2992,6 +3017,8 @@ void multipleRecipients(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -2999,13 +3026,12 @@ void multipleRecipients(TestInfo testInfo) throws IOException { .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress1, Set.of("list1")), new MailingListConfiguration(listAddress2, Set.of("list2")))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3027,7 +3053,6 @@ void multipleRecipients(TestInfo testInfo) throws IOException { listServer.processIncoming(); // The mail should have been sent to list1 - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress1.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -3062,7 +3087,7 @@ void jsonArchive(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(false); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3071,6 +3096,8 @@ void jsonArchive(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3079,8 +3106,6 @@ void jsonArchive(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageJSONRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3091,7 +3116,7 @@ void jsonArchive(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3159,7 +3184,6 @@ void jsonArchive(TestInfo testInfo) throws IOException { // The mailing list as well listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -3263,7 +3287,7 @@ void rebaseOnRetry(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3272,6 +3296,8 @@ void rebaseOnRetry(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3280,8 +3306,6 @@ void rebaseOnRetry(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3289,7 +3313,7 @@ void rebaseOnRetry(TestInfo testInfo) throws IOException { .readyLabels(Set.of("rfr")) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3351,7 +3375,7 @@ void dependent(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3359,19 +3383,20 @@ void dependent(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3423,7 +3448,7 @@ void commentWithQuoteFromBridged(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var bridge = credentials.getHostedRepository(); @@ -3432,19 +3457,20 @@ void commentWithQuoteFromBridged(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) .archive(archive) .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) .webrevStorageBaseUri(webrevServer.uri()) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3499,7 +3525,7 @@ void notArchiveDraftPR(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3508,6 +3534,8 @@ void notArchiveDraftPR(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3516,8 +3544,6 @@ void notArchiveDraftPR(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3526,7 +3552,7 @@ void notArchiveDraftPR(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the repository. @@ -3676,7 +3702,7 @@ void noWebrev(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3685,6 +3711,8 @@ void noWebrev(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3693,8 +3721,6 @@ void noWebrev(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3705,7 +3731,7 @@ void noWebrev(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3771,7 +3797,6 @@ void noWebrev(TestInfo testInfo) throws IOException { // The mailing list as well listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -3822,7 +3847,7 @@ void mergeWithoutWebrev(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3831,6 +3856,8 @@ void mergeWithoutWebrev(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3838,8 +3865,6 @@ void mergeWithoutWebrev(TestInfo testInfo) throws IOException { .archiveRef("archive") .censusRepo(censusBuilder.build()) .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3847,6 +3872,7 @@ void mergeWithoutWebrev(TestInfo testInfo) throws IOException { .webrevGenerateJSON(false) .webrevGenerateHTML(false) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3908,7 +3934,7 @@ void archiveLongBody(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -3917,6 +3943,8 @@ void archiveLongBody(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -3925,8 +3953,6 @@ void archiveLongBody(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -3935,7 +3961,7 @@ void archiveLongBody(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -3980,7 +4006,6 @@ void archiveLongBody(TestInfo testInfo) throws IOException { // The mailing list as well listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); @@ -4002,7 +4027,7 @@ void largeDiffArchive(TestInfo testInfo) throws IOException { var tempFolder = new TemporaryDirectory(); var archiveFolder = new TemporaryDirectory(); var webrevFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var webrevServer = new TestWebrevServer()) { var author = credentials.getHostedRepository(); var archive = credentials.getHostedRepository(); @@ -4011,6 +4036,8 @@ void largeDiffArchive(TestInfo testInfo) throws IOException { var censusBuilder = credentials.getCensusBuilder() .addAuthor(author.forge().currentUser().id()); var from = EmailAddress.from("test", "test@test.mail"); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), + listServer.getSMTP(), Duration.ZERO); var mlBot = MailingListBridgeBot.newBuilder() .from(from) .repo(author) @@ -4019,8 +4046,6 @@ void largeDiffArchive(TestInfo testInfo) throws IOException { .lists(List.of(new MailingListConfiguration(listAddress, Set.of()))) .ignoredUsers(Set.of(ignored.forge().currentUser().username())) .ignoredComments(Set.of()) - .listArchive(listServer.getArchive()) - .smtpServer(listServer.getSMTP()) .webrevStorageHTMLRepository(archive) .webrevStorageRef("webrev") .webrevStorageBase(Path.of("test")) @@ -4029,7 +4054,7 @@ void largeDiffArchive(TestInfo testInfo) throws IOException { .readyComments(Map.of(ignored.forge().currentUser().username(), Pattern.compile("ready"))) .issueTracker(URIBuilder.base("http://issues.test/browse/").build()) .headers(Map.of("Extra1", "val1", "Extra2", "val2")) - .sendInterval(Duration.ZERO) + .mailingListServer(mailmanServer) .build(); // Populate the projects repository @@ -4063,7 +4088,6 @@ void largeDiffArchive(TestInfo testInfo) throws IOException { assertTrue(pr.store().comments().get(1).body().contains("[Full](Webrev is not available because diff is too large)")); // The mailing list as well listServer.processIncoming(); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var conversations = mailmanList.conversations(Duration.ofDays(1)); assertEquals(1, conversations.size()); diff --git a/bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java b/bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java index 9c8576e1b..d421c4d0f 100644 --- a/bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java +++ b/bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java @@ -27,7 +27,6 @@ import org.openjdk.skara.email.EmailAddress; import org.openjdk.skara.json.JSONObject; import org.openjdk.skara.mailinglist.MailingListServerFactory; -import org.openjdk.skara.network.URIBuilder; import java.time.Duration; import java.util.regex.Pattern; @@ -43,9 +42,8 @@ public String name() { public Notifier create(BotConfiguration botConfiguration, JSONObject notifierConfiguration) { var smtp = notifierConfiguration.get("smtp").asString(); var sender = EmailAddress.parse(notifierConfiguration.get("sender").asString()); - var archive = URIBuilder.base(notifierConfiguration.get("archive").asString()).build(); var interval = notifierConfiguration.contains("interval") ? Duration.parse(notifierConfiguration.get("interval").asString()) : Duration.ofSeconds(1); - var listServer = MailingListServerFactory.createMailmanServer(archive, smtp, interval); + var listServer = MailingListServerFactory.createSendOnlyServer(smtp, interval); var recipient = notifierConfiguration.get("recipient").asString(); var recipientAddress = EmailAddress.parse(recipient); diff --git a/bots/notify/src/test/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierTests.java b/bots/notify/src/test/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierTests.java index 2cd3e0bd3..9eaa8c41f 100644 --- a/bots/notify/src/test/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierTests.java +++ b/bots/notify/src/test/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierTests.java @@ -40,7 +40,7 @@ public class MailingListNotifierTests { @Test void testMailingList(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -51,7 +51,7 @@ void testMailingList(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -114,7 +114,7 @@ void testMailingList(TestInfo testInfo) throws IOException { @Test void testMailingListMultiple(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -125,7 +125,7 @@ void testMailingListMultiple(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -191,7 +191,7 @@ void testMailingListMultiple(TestInfo testInfo) throws IOException { @Test void testMailingListMerge(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -202,7 +202,7 @@ void testMailingListMerge(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -271,7 +271,7 @@ void testMailingListMerge(TestInfo testInfo) throws IOException { @Test void testMailingListSponsored(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -282,7 +282,7 @@ void testMailingListSponsored(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -336,7 +336,7 @@ void testMailingListSponsored(TestInfo testInfo) throws IOException { @Test void testMailingListMultipleBranches(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -348,7 +348,7 @@ void testMailingListMultipleBranches(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -441,7 +441,7 @@ void testMailingListMultipleBranches(TestInfo testInfo) throws IOException { @Test void testMailingListPROnlyMultipleBranches(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -452,7 +452,7 @@ void testMailingListPROnlyMultipleBranches(TestInfo testInfo) throws IOException localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -526,7 +526,7 @@ void testMailingListPROnlyMultipleBranches(TestInfo testInfo) throws IOException @Test void testMailingListPR(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -537,7 +537,7 @@ void testMailingListPR(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -617,7 +617,7 @@ void testMailingListPR(TestInfo testInfo) throws IOException { @Test void testMailingListMergePR(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -628,7 +628,7 @@ void testMailingListMergePR(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -715,7 +715,7 @@ void testMailingListMergePR(TestInfo testInfo) throws IOException { @Test void testMailingListPROnce(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -727,7 +727,7 @@ void testMailingListPROnce(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -814,7 +814,7 @@ void testMailingListPROnce(TestInfo testInfo) throws IOException { void testMailinglistTag(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer(); + var listServer = TestMailmanServer.createV3(); var scratchFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); var localRepoFolder = tempFolder.path().resolve("repo"); @@ -825,7 +825,7 @@ void testMailinglistTag(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -938,7 +938,7 @@ void testMailinglistTag(TestInfo testInfo) throws IOException { void testMailinglistPlainTags(TestInfo testInfo) throws IOException { try (var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory(); - var listServer = new TestMailmanServer()) { + var listServer = TestMailmanServer.createV3()) { var repo = credentials.getHostedRepository(); var localRepoFolder = tempFolder.path().resolve("repo"); var localRepo = CheckableRepository.init(localRepoFolder, repo.repositoryType()); @@ -948,7 +948,7 @@ void testMailinglistPlainTags(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -1033,7 +1033,7 @@ void testMailinglistPlainTags(TestInfo testInfo) throws IOException { @Test void testMailingListBranch(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -1045,7 +1045,7 @@ void testMailingListBranch(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -1114,7 +1114,7 @@ void testMailingListBranch(TestInfo testInfo) throws IOException { @Test void testMailingListNoIdempotence(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -1125,7 +1125,7 @@ void testMailingListNoIdempotence(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); @@ -1181,7 +1181,7 @@ void testMailingListNoIdempotence(TestInfo testInfo) throws IOException { @Test void testMailingListWithExistingRepo(TestInfo testInfo) throws IOException { - try (var listServer = new TestMailmanServer(); + try (var listServer = TestMailmanServer.createV3(); var credentials = new HostCredentials(testInfo); var tempFolder = new TemporaryDirectory()) { var repo = credentials.getHostedRepository(); @@ -1192,7 +1192,7 @@ void testMailingListWithExistingRepo(TestInfo testInfo) throws IOException { localRepo.pushAll(repo.authenticatedUrl()); var listAddress = EmailAddress.parse(listServer.createList("test")); - var mailmanServer = MailingListServerFactory.createMailmanServer(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); + var mailmanServer = MailingListServerFactory.createMailman3Server(listServer.getArchive(), listServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress.address()); var tagStorage = createTagStorage(repo); var branchStorage = createBranchStorage(repo); diff --git a/email/src/main/java/org/openjdk/skara/email/Email.java b/email/src/main/java/org/openjdk/skara/email/Email.java index 9e3946ed9..0bd3cd182 100644 --- a/email/src/main/java/org/openjdk/skara/email/Email.java +++ b/email/src/main/java/org/openjdk/skara/email/Email.java @@ -22,10 +22,12 @@ */ package org.openjdk.skara.email; +import java.nio.charset.StandardCharsets; import java.time.ZonedDateTime; import java.time.format.*; import java.time.temporal.ChronoUnit; import java.util.*; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -43,6 +45,10 @@ public class Email { "(\\r\\n){2}|(\\n){2}", Pattern.MULTILINE); private final static Pattern mboxMessageHeaderPattern = Pattern.compile( "^([-\\w]+): ((?:.(?!\\R\\w))*.)", Pattern.MULTILINE | Pattern.DOTALL); + private final static Pattern mimeHeadersPattern = Pattern.compile( + "^(Content-Type|Content-Transfer-Encoding): .*"); + private final static Pattern quotedPrintableUtf8Pattern = Pattern.compile("=([0-9A-Fa-f]{2})=([0-9A-Fa-f]{2})"); + private final static Pattern quotedPrintablePattern = Pattern.compile("=([0-9A-Fa-f]{2})"); Email(EmailAddress id, ZonedDateTime date, List recipients, EmailAddress author, EmailAddress sender, String subject, String body, Map headers) { this.id = id; @@ -71,10 +77,68 @@ private static MboxMessage parseMboxMessage(String message) { .replaceAll("\\R", ""))); ret.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); ret.headers.putAll(headers); - ret.body = parts[1].stripTrailing(); + + var boundary = extractContentBoundary(ret.headers); + if (boundary != null) { + var body = new StringBuilder(); + var bodySections = parts[1].split("\\R?--" + boundary + "(?:--)?\\R"); + for (String bodySection : bodySections) { + if (bodySection.lines().findFirst().map(e -> mimeHeadersPattern.matcher(e).matches()).orElse(false)) { + var mimeHeaders = bodySection.lines() + .takeWhile(s -> !s.isEmpty()) + .map(mboxMessageHeaderPattern::matcher) + .filter(Matcher::matches) + .collect(Collectors.toMap(match -> match.group(1), match -> match.group(2))); + // Skip any non plain text part + if (mimeHeaders.containsKey("Content-Type") && !mimeHeaders.get("Content-Type").startsWith("text/plain")) { + continue; + } + // Remove the mime headers from the rest of the body section + var bodySectionBody = bodySection.split("\\R{2}", 2)[1]; + // Mailman3 encodes mail bodies with "quoted-printable". + if ("quoted-printable".equals(mimeHeaders.get("Content-Transfer-Encoding"))) { + // Remove soft line breaks + bodySectionBody = bodySectionBody + .replace("=\r\n", "") + .replace("=\n", ""); + if (mimeHeaders.get("Content-Type").contains("charset=\"utf-8\"")) { + // Decode UTF-8 characters which are encoded as pairs of =XX=YY. + bodySectionBody = quotedPrintableUtf8Pattern.matcher(bodySectionBody).replaceAll(m -> { + var bytes = new byte[]{(byte) Integer.parseInt(m.group(1), 16), + (byte) Integer.parseInt(m.group(2), 16)}; + return new String(bytes, StandardCharsets.UTF_8); + }); + } + // Replace all possibly remaining single instances of =XX. + bodySectionBody = quotedPrintablePattern.matcher(bodySectionBody).replaceAll(m -> + Character.toString((char) Integer.parseInt(m.group(1), 16))); + } + body.append(bodySectionBody.stripTrailing()); + } else { + body.append(bodySection.stripTrailing()); + } + } + ret.body = body.toString(); + } else { + ret.body = parts[1].stripTrailing(); + } return ret; } + private final static Pattern mboxBoundaryPattern = Pattern.compile(".*boundary=\"([^\"]*)\".*"); + + // Content-Type: multipart/mixed; boundary="===============3685582790409215631==" + private static String extractContentBoundary(Map headers) { + if (headers.containsKey("Content-Type")) { + var contentType = headers.get("Content-Type"); + var matcher = mboxBoundaryPattern.matcher(contentType); + if (matcher.matches()) { + return matcher.group(1); + } + } + return null; + } + private static final Pattern redundantTimeZonePattern = Pattern.compile("^(.*[-+\\d{4}]) \\(\\w+\\)$"); public static Email parse(String raw) { diff --git a/email/src/test/java/org/openjdk/skara/email/EmailTests.java b/email/src/test/java/org/openjdk/skara/email/EmailTests.java index 9fb38726e..52081dd2f 100644 --- a/email/src/test/java/org/openjdk/skara/email/EmailTests.java +++ b/email/src/test/java/org/openjdk/skara/email/EmailTests.java @@ -150,4 +150,87 @@ void parseEncoded() { mail.recipients()); assertEquals("The body", mail.body()); } + + @Test + void parseContentType7bit() { + var mail = Email.parse(""" + Message-Id: + Date: Wed, 27 Mar 2019 14:31:00 +0100 + Subject: hello + From: B + To: C , + Content-Type: multipart/mixed; boundary="===============3685582790409215631==" + + --===============3685582790409215631== + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: 7bit + + The body text + + --===============3685582790409215631==-- + """ + ); + + assertEquals("The body text", mail.body()); + } + + @Test + void parseContentTypeQuotedPrintable() { + var mail = Email.parse(""" + Message-Id: + Date: Wed, 27 Mar 2019 14:31:00 +0100 + Subject: hello + From: B + To: C , + Content-Type: multipart/mixed; boundary="===============3685582790409215631==" + + --===============3685582790409215631== + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: quoted-printable + + A response with weird characters r=C3=A4ksm=C3=B6rg=C3=A5s and a line longer = + than 76=20 + characters. + + --===============3685582790409215631==-- + """ + ); + + assertEquals("A response with weird characters räksmörgås and a line longer than 76 \ncharacters.", mail.body()); + } + + @Test + void parseContentTypeMultipart() { + var mail = Email.parse(""" + Message-Id: + Date: Wed, 27 Mar 2019 14:31:00 +0100 + Subject: hello + From: B + To: C , + Content-Type: multipart/mixed; boundary="===============3685582790409215631==" + + --===============3685582790409215631== + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: 7bit + + The body text + + --===============3685582790409215631== + Content-Type: text/html + Content-Transfer-Encoding: base64 + Content-Disposition: attachment; filename="attachment.html" + MIME-Version: 1.0 + + PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+CjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlw + ZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4KICA8L2hlYWQ+CiAgPGJvZHk+ + CiAgICA8aDE+VGhpcyBpcyBhbiBlbWFpbCB3aXRoIGZvcm1hdHRpbmc8L2gxPgogICAgPHA+UGFy + YWdyYXBoIHRleHQuPC9wPgogICAgPHByZT5QcmVmb3JtYXQgdGV4dC48L3ByZT4KICA8L2JvZHk+ + CjwvaHRtbD4K + + --===============3685582790409215631==-- + """ + ); + + assertEquals("The body text", mail.body()); + } } diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/MailingListServerFactory.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/MailingListServerFactory.java index e8fcd022c..70caa0adc 100644 --- a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/MailingListServerFactory.java +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/MailingListServerFactory.java @@ -22,7 +22,9 @@ */ package org.openjdk.skara.mailinglist; -import org.openjdk.skara.mailinglist.mailman.MailmanServer; +import org.openjdk.skara.mailinglist.mailman.Mailman2Server; +import org.openjdk.skara.mailinglist.mailman.Mailman3Server; +import org.openjdk.skara.mailinglist.mailman.SendOnlyServer; import org.openjdk.skara.mailinglist.mboxfile.MboxFileListServer; import java.net.URI; @@ -30,12 +32,20 @@ import java.time.Duration; public class MailingListServerFactory { - public static MailingListServer createMailmanServer(URI archive, String smtp, Duration sendInterval) { - return new MailmanServer(archive, smtp, sendInterval, false); + public static MailingListServer createMailman2Server(URI archive, String smtp, Duration sendInterval) { + return new Mailman2Server(archive, smtp, sendInterval, false); } - public static MailingListServer createMailmanServer(URI archive, String smtp, Duration sendInterval, boolean useEtag) { - return new MailmanServer(archive, smtp, sendInterval, useEtag); + public static MailingListServer createMailman2Server(URI archive, String smtp, Duration sendInterval, boolean useEtag) { + return new Mailman2Server(archive, smtp, sendInterval, useEtag); + } + + public static MailingListServer createMailman3Server(URI archive, String smtp, Duration sendInterval) { + return new Mailman3Server(archive, smtp, sendInterval); + } + + public static MailingListServer createSendOnlyServer(String smtp, Duration sendInterval) { + return new SendOnlyServer(smtp, sendInterval); } public static MailingListServer createMboxFileServer(Path file) { diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman2Server.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman2Server.java new file mode 100644 index 000000000..ca9f80e3b --- /dev/null +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman2Server.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.skara.mailinglist.mailman; + +import java.net.URI; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Locale; +import org.openjdk.skara.mailinglist.MailingListReader; +import org.openjdk.skara.network.URIBuilder; + +public class Mailman2Server extends MailmanServer { + + public Mailman2Server(URI archive, String smtpServer, Duration sendInterval, boolean useEtag) { + super(archive, smtpServer, sendInterval, useEtag); + } + + URI getMboxUri(String listName, ZonedDateTime month) { + var dateStr = DateTimeFormatter.ofPattern("yyyy-MMMM", Locale.US).format(month); + return URIBuilder.base(archive).appendPath(listName + "/" + dateStr + ".txt").build(); + } + + @Override + public MailingListReader getListReader(String... listNames) { + return new Mailman2ListReader(this, Arrays.asList(listNames), useEtag); + } +} diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman3Server.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman3Server.java new file mode 100644 index 000000000..00c8e9051 --- /dev/null +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/Mailman3Server.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.skara.mailinglist.mailman; + +import java.net.URI; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Arrays; +import org.openjdk.skara.mailinglist.MailingListReader; + +public class Mailman3Server extends MailmanServer { + private final ZonedDateTime startTime; + + public Mailman3Server(URI archive, String smtpServer, Duration sendInterval, ZonedDateTime startTime) { + super(archive, smtpServer, sendInterval, false); + this.startTime = startTime; + } + + public Mailman3Server(URI archive, String smtpServer, Duration sendInterval) { + this(archive, smtpServer, sendInterval, ZonedDateTime.now()); + } + + URI getArchiveUri() { + return archive; + } + + @Override + public MailingListReader getListReader(String... listNames) { + return new Mailman3ListReader(this, Arrays.asList(listNames), startTime); + } +} diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanListReader.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanListReader.java index 4e33251f5..ad7170583 100644 --- a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanListReader.java +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanListReader.java @@ -22,6 +22,9 @@ */ package org.openjdk.skara.mailinglist.mailman; +import java.nio.charset.StandardCharsets; +import java.time.format.DateTimeFormatter; +import java.util.zip.GZIPInputStream; import org.openjdk.skara.email.*; import org.openjdk.skara.mailinglist.*; @@ -34,14 +37,14 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import org.openjdk.skara.metrics.Counter; +import org.openjdk.skara.network.URIBuilder; -public class MailmanListReader implements MailingListReader { - private final MailmanServer server; +public abstract class MailmanListReader implements MailingListReader { private final boolean useEtag; - private final List names = new ArrayList<>(); + protected final List names = new ArrayList<>(); private final Logger log = Logger.getLogger("org.openjdk.skara.mailinglist"); - private final ConcurrentMap> pageCache = new ConcurrentHashMap<>(); - private List cachedConversations = new ArrayList<>(); + protected final ConcurrentMap> pageCache = new ConcurrentHashMap<>(); + protected List cachedConversations = new ArrayList<>(); private static final HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); @@ -49,8 +52,7 @@ public class MailmanListReader implements MailingListReader { private static final Counter.WithOneLabel POLLING_COUNTER = Counter.name("skara_mailman_polling").labels("code").register(); - MailmanListReader(MailmanServer server, Collection names, boolean useEtag) { - this.server = server; + MailmanListReader(Collection names, boolean useEtag) { this.useEtag = useEtag; for (var name : names) { if (name.contains("@")) { @@ -61,29 +63,7 @@ public class MailmanListReader implements MailingListReader { } } - @Override - public String toString() { - return "MailmanList:" + String.join(", ", names); - } - - private List getMonthRange(Duration maxAge) { - var now = ZonedDateTime.now(); - var start = now.minus(maxAge); - List ret = new ArrayList<>(); - - // Iterate all the way until start is equal to now - while (!start.isAfter(now)) { - ret.add(start); - var next = start.plus(Duration.ofDays(1)); - while (start.getMonthValue() == next.getMonthValue()) { - next = next.plus(Duration.ofDays(1)); - } - start = next; - } - return ret; - } - - private Optional> getPage(URI uri) { + protected Optional> getPage(URI uri) { var requestBuilder = HttpRequest.newBuilder(uri) .timeout(Duration.ofSeconds(30)) .GET(); @@ -96,7 +76,7 @@ private Optional> getPage(URI uri) { var request = requestBuilder.build(); try { - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); POLLING_COUNTER.labels(String.valueOf(response.statusCode())).inc(); if (response.statusCode() == 200) { pageCache.put(uri, response); @@ -118,34 +98,73 @@ private Optional> getPage(URI uri) { } } + protected void updateCachedConversations(ArrayList emails, Duration maxAge) { + var conversations = Mbox.parseMbox(emails); + var threshold = ZonedDateTime.now().minus(maxAge); + cachedConversations = conversations.stream() + .filter(mail -> mail.first().date().isAfter(threshold)) + .collect(Collectors.toList()); + } +} + +class Mailman2ListReader extends MailmanListReader { + private final Mailman2Server server; + + Mailman2ListReader(Mailman2Server server, Collection names, boolean useEtag) { + super(names, useEtag); + this.server = server; + } + + @Override + public String toString() { + return "Mailman2List:" + String.join(", ", names); + } + + private List getMonthRange(Duration maxAge) { + var now = ZonedDateTime.now(); + var start = now.minus(maxAge); + List ret = new ArrayList<>(); + + // Iterate all the way until start is equal to now + while (!start.isAfter(now)) { + ret.add(start); + var next = start.plus(Duration.ofDays(1)); + while (start.getMonthValue() == next.getMonthValue()) { + next = next.plus(Duration.ofDays(1)); + } + start = next; + } + return ret; + } + @Override public List conversations(Duration maxAge) { // Order pages by most recent first var potentialPages = getMonthRange(maxAge).stream() .sorted(Comparator.reverseOrder()) - .collect(Collectors.toList()); + .toList(); var monthCount = 0; var newContent = false; var emails = new ArrayList(); for (var month : potentialPages) { for (var name : names) { - URI mboxUri = server.getMbox(name, month); + URI mboxUri = server.getMboxUri(name, month); var sender = EmailAddress.from(name + "@" + mboxUri.getHost()); // For archives older than the previous month, always use cached results if (monthCount > 1 && pageCache.containsKey(mboxUri)) { var cachedResponse = pageCache.get(mboxUri); if (cachedResponse != null && cachedResponse.statusCode() != 404) { - emails.addAll(0, Mbox.splitMbox(cachedResponse.body(), sender)); + emails.addAll(0, Mbox.splitMbox(new String(cachedResponse.body(), StandardCharsets.UTF_8), sender)); } } else { var mboxResponse = getPage(mboxUri); if (mboxResponse.isPresent()) { if (mboxResponse.get().statusCode() == 304) { - emails.addAll(0, Mbox.splitMbox(pageCache.get(mboxUri).body(), sender)); + emails.addAll(0, Mbox.splitMbox(new String(pageCache.get(mboxUri).body(), StandardCharsets.UTF_8), sender)); } else { - emails.addAll(0, Mbox.splitMbox(mboxResponse.get().body(), sender)); + emails.addAll(0, Mbox.splitMbox(new String(mboxResponse.get().body(), StandardCharsets.UTF_8), sender)); newContent = true; } } @@ -155,13 +174,113 @@ public List conversations(Duration maxAge) { } if (newContent) { - var conversations = Mbox.parseMbox(emails); - var threshold = ZonedDateTime.now().minus(maxAge); - cachedConversations = conversations.stream() - .filter(mail -> mail.first().date().isAfter(threshold)) - .collect(Collectors.toList()); + updateCachedConversations(emails, maxAge); } return cachedConversations; } } + +class Mailman3ListReader extends MailmanListReader { + private final Mailman3Server server; + private final ZonedDateTime startTime; + + Mailman3ListReader(Mailman3Server server, Collection names, ZonedDateTime startTime) { + // Mailman3 does not support etag for mbox API + super(names, false); + this.server = server; + this.startTime = startTime; + } + + /** + * Reads all emails newer than maxAge. Reads everything older than start + * time in one go and caches that result. This chunk will always read start + * time minus max age. Emails older than now minus max age are filtered out + * later. Chunks newer than start time are read one day at a time, each day + * getting cached when the next day starts. This means only the current day + * is refreshed each time this method is called. + * + * @param maxAge Maximum age of emails to read relative to the start time. + * @return Emails sorted in conversations + */ + @Override + public List conversations(Duration maxAge) { + var now = ZonedDateTime.now(); + // First interval is everything before start time + var start = startTime.minus(maxAge); + var end = startTime.plusDays(1); + + var emails = new ArrayList(); + var newContent = false; + // https://mail-dev.example.com/archives/list/skara-test@mail-dev.example.com/export/foo.mbox.gz?start=2024-10-25&end=2025-10-25 + + while (start.isBefore(now)) { + var query = Map.of("start", List.of(start.format(DateTimeFormatter.ISO_LOCAL_DATE)), + "end", List.of(end.format(DateTimeFormatter.ISO_LOCAL_DATE))); + for (String name : names) { + var mboxUri = URIBuilder.base(server.getArchiveUri()).appendPath("list/").appendPath(name) + .appendPath("@").appendPath(server.getArchiveUri().getHost()) + .appendPath("/export/foo.mbox.gz").setQuery(query).build(); + var sender = EmailAddress.from(name + "@" + server.getArchiveUri().getHost()); + // For archives older than today, always use cached results + if (end.isBefore(now) && pageCache.containsKey(mboxUri)) { + var cachedResponse = pageCache.get(mboxUri); + if (cachedResponse != null && cachedResponse.statusCode() != 404) { + emails.addAll(0, Mbox.splitMbox(gunzipToString(cachedResponse.body()), sender)); + } + } else { + var mboxResponse = getPage(mboxUri); + if (mboxResponse.isPresent()) { + emails.addAll(0, Mbox.splitMbox(gunzipToString(mboxResponse.get().body()), sender)); + newContent = true; + } + } + } + // Every interval after the first is one day + start = end; + end = end.plusDays(1); + } + + if (newContent) { + updateCachedConversations(emails, maxAge); + } + + return cachedConversations; + } + + private String gunzipToString(byte[] data) { + try (var in = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(data)), StandardCharsets.UTF_8)) { + var out = new StringBuilderWriter(); + in.transferTo(out); + return out.toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Simple StringWriter clone that uses a StringBuilder instead of a StringBuffer. + */ + private static class StringBuilderWriter extends Writer { + + private final StringBuilder buf = new StringBuilder(); + + @Override + public String toString() { + return buf.toString(); + } + + @Override + public void write(char[] cbuf, int off, int len) { + buf.append(cbuf, off, len); + } + + @Override + public void flush() { + } + + @Override + public void close() { + } + } +} diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanServer.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanServer.java index 7ac452ee8..85bcdf335 100644 --- a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanServer.java +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/MailmanServer.java @@ -24,22 +24,19 @@ import org.openjdk.skara.email.*; import org.openjdk.skara.mailinglist.*; -import org.openjdk.skara.network.URIBuilder; import java.io.*; import java.net.URI; import java.time.*; -import java.time.format.DateTimeFormatter; -import java.util.*; -public class MailmanServer implements MailingListServer { - private final URI archive; +public abstract class MailmanServer implements MailingListServer { + protected final URI archive; private final String smtpServer; private final Duration sendInterval; - private final boolean useEtag; + protected final boolean useEtag; private volatile Instant lastSend; - public MailmanServer(URI archive, String smtpServer, Duration sendInterval, boolean useEtag) { + protected MailmanServer(URI archive, String smtpServer, Duration sendInterval, boolean useEtag) { this.archive = archive; this.smtpServer = smtpServer; this.sendInterval = sendInterval; @@ -47,11 +44,6 @@ public MailmanServer(URI archive, String smtpServer, Duration sendInterval, bool lastSend = Instant.EPOCH; } - URI getMbox(String listName, ZonedDateTime month) { - var dateStr = DateTimeFormatter.ofPattern("yyyy-MMMM", Locale.US).format(month); - return URIBuilder.base(archive).appendPath(listName + "/" + dateStr + ".txt").build(); - } - void sendMessage(Email message) { while (lastSend.plus(sendInterval).isAfter(Instant.now())) { try { @@ -72,8 +64,7 @@ public void post(Email email) { sendMessage(email); } - @Override - public MailingListReader getListReader(String... listNames) { - return new MailmanListReader(this, Arrays.asList(listNames), useEtag); + public URI archive() { + return archive; } } diff --git a/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/SendOnlyServer.java b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/SendOnlyServer.java new file mode 100644 index 000000000..a55a51712 --- /dev/null +++ b/mailinglist/src/main/java/org/openjdk/skara/mailinglist/mailman/SendOnlyServer.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.skara.mailinglist.mailman; + +import java.time.Duration; +import org.openjdk.skara.mailinglist.MailingListReader; + +/** + * MailingListServer implementation that only implements the send message API. + */ +public class SendOnlyServer extends MailmanServer { + public SendOnlyServer(String smtpServer, Duration sendInterval) { + super(null, smtpServer, sendInterval, false); + } + + @Override + public MailingListReader getListReader(String... listNames) { + throw new UnsupportedOperationException(); + } +} diff --git a/mailinglist/src/test/java/org/openjdk/skara/mailinglist/MailmanTests.java b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman2Tests.java similarity index 95% rename from mailinglist/src/test/java/org/openjdk/skara/mailinglist/MailmanTests.java rename to mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman2Tests.java index 362ad663e..cefc0f29e 100644 --- a/mailinglist/src/test/java/org/openjdk/skara/mailinglist/MailmanTests.java +++ b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman2Tests.java @@ -32,12 +32,12 @@ import static org.junit.jupiter.api.Assertions.*; -class MailmanTests { +class Mailman2Tests { @Test void simple() throws IOException { - try (var testServer = new TestMailmanServer()) { + try (var testServer = TestMailmanServer.createV2()) { var listAddress = testServer.createList("test"); - var mailmanServer = MailingListServerFactory.createMailmanServer(testServer.getArchive(), testServer.getSMTP(), + var mailmanServer = MailingListServerFactory.createMailman2Server(testServer.getArchive(), testServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress); var sender = EmailAddress.from("Test", "test@test.email"); @@ -60,9 +60,9 @@ void simple() throws IOException { @Test void replies() throws IOException { - try (var testServer = new TestMailmanServer()) { + try (var testServer = TestMailmanServer.createV2()) { var listAddress = testServer.createList("test"); - var mailmanServer = MailingListServerFactory.createMailmanServer(testServer.getArchive(), testServer.getSMTP(), + var mailmanServer = MailingListServerFactory.createMailman2Server(testServer.getArchive(), testServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress); var sender = EmailAddress.from("Test", "test@test.email"); @@ -106,9 +106,9 @@ void replies() throws IOException { @Test void cached() throws IOException { - try (var testServer = new TestMailmanServer()) { + try (var testServer = TestMailmanServer.createV2()) { var listAddress = testServer.createList("test"); - var mailmanServer = MailingListServerFactory.createMailmanServer(testServer.getArchive(), testServer.getSMTP(), + var mailmanServer = MailingListServerFactory.createMailman2Server(testServer.getArchive(), testServer.getSMTP(), Duration.ZERO, true); var mailmanList = mailmanServer.getListReader(listAddress); var sender = EmailAddress.from("Test", "test@test.email"); @@ -140,9 +140,9 @@ void cached() throws IOException { @Test void interval() throws IOException { - try (var testServer = new TestMailmanServer()) { + try (var testServer = TestMailmanServer.createV2()) { var listAddress = testServer.createList("test"); - var mailmanServer = MailingListServerFactory.createMailmanServer(testServer.getArchive(), testServer.getSMTP(), + var mailmanServer = MailingListServerFactory.createMailman2Server(testServer.getArchive(), testServer.getSMTP(), Duration.ofDays(1)); var mailmanList = mailmanServer.getListReader(listAddress); var sender = EmailAddress.from("Test", "test@test.email"); @@ -172,9 +172,9 @@ void interval() throws IOException { @Test void poll3months() throws Exception { - try (var testServer = new TestMailmanServer()) { + try (var testServer = TestMailmanServer.createV2()) { var listAddress = testServer.createList("test"); - var mailmanServer = MailingListServerFactory.createMailmanServer(testServer.getArchive(), + var mailmanServer = MailingListServerFactory.createMailman2Server(testServer.getArchive(), testServer.getSMTP(), Duration.ZERO); var mailmanList = mailmanServer.getListReader(listAddress); var sender = EmailAddress.from("Test", "test@test.email"); diff --git a/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3IntegrationTests.java b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3IntegrationTests.java new file mode 100644 index 000000000..1df267654 --- /dev/null +++ b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3IntegrationTests.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.skara.mailinglist; + +import java.time.Duration; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.openjdk.skara.network.URIBuilder; +import org.openjdk.skara.test.EnabledIfTestProperties; +import org.openjdk.skara.test.TestProperties; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class Mailman3IntegrationTests { + + private static TestProperties props; + + @BeforeAll + static void beforeAll() { + props = TestProperties.load(); + } + + @Test + @EnabledIfTestProperties({"mailman3.url", "mailman3.list"}) + void testReviews() { + var url = props.get("mailman3.url"); + var listName = props.get("mailman3.list"); + var mailmanServer = MailingListServerFactory.createMailman3Server(URIBuilder.base(url).build(), null, null); + var listReader = mailmanServer.getListReader(listName); + var conversations = listReader.conversations(Duration.ofDays(365)); + assertFalse(conversations.isEmpty()); + } +} diff --git a/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3Tests.java b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3Tests.java new file mode 100644 index 000000000..c641c66df --- /dev/null +++ b/mailinglist/src/test/java/org/openjdk/skara/mailinglist/Mailman3Tests.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.skara.mailinglist; + +import java.io.IOException; +import java.time.Duration; +import java.time.ZonedDateTime; +import org.junit.jupiter.api.Test; +import org.openjdk.skara.email.Email; +import org.openjdk.skara.email.EmailAddress; +import org.openjdk.skara.mailinglist.mailman.Mailman3Server; +import org.openjdk.skara.test.TestMailmanServer; + +import static org.junit.jupiter.api.Assertions.*; + +class Mailman3Tests { + @Test + void simple() throws IOException { + try (var testServer = TestMailmanServer.createV3()) { + var listAddress = testServer.createList("test"); + var mailmanServer = MailingListServerFactory.createMailman3Server(testServer.getArchive(), testServer.getSMTP(), + Duration.ZERO); + var mailmanList = mailmanServer.getListReader(listAddress); + var sender = EmailAddress.from("Test", "test@test.email"); + var mail = Email.create(sender, "Subject", "Body") + .recipient(EmailAddress.parse(listAddress)) + .build(); + mailmanServer.post(mail); + var expectedMail = Email.from(mail) + .sender(EmailAddress.parse(listAddress)) + .build(); + + testServer.processIncoming(); + + var conversations = mailmanList.conversations(Duration.ofDays(1)); + assertEquals(1, conversations.size()); + var conversation = conversations.get(0); + assertEquals(expectedMail, conversation.first()); + } + } + + @Test + void replies() throws IOException { + try (var testServer = TestMailmanServer.createV3()) { + var listAddress = testServer.createList("test"); + var mailmanServer = MailingListServerFactory.createMailman3Server(testServer.getArchive(), testServer.getSMTP(), + Duration.ZERO); + var mailmanList = mailmanServer.getListReader(listAddress); + var sender = EmailAddress.from("Test", "test@test.email"); + var sentParent = Email.create(sender, "Subject", "Body") + .recipient(EmailAddress.parse(listAddress)) + .build(); + mailmanServer.post(sentParent); + testServer.processIncoming(); + var expectedParent = Email.from(sentParent) + .sender(EmailAddress.parse(listAddress)) + .build(); + + var conversations = mailmanList.conversations(Duration.ofDays(1)); + assertEquals(1, conversations.size()); + var conversation = conversations.get(0); + assertEquals(expectedParent, conversation.first()); + + var replier = EmailAddress.from("Replier", "replier@test.email"); + var sentReply = Email.create(replier, "Reply subject", "Reply body") + .recipient(EmailAddress.parse(listAddress)) + .header("In-Reply-To", sentParent.id().toString()) + .build(); + mailmanServer.post(sentReply); + var expectedReply = Email.from(sentReply) + .sender(EmailAddress.parse(listAddress)) + .build(); + + testServer.processIncoming(); + + conversations = mailmanList.conversations(Duration.ofDays(1)); + assertEquals(1, conversations.size()); + conversation = conversations.get(0); + assertEquals(expectedParent, conversation.first()); + + var replies = conversation.replies(conversation.first()); + assertEquals(1, replies.size()); + var reply = replies.get(0); + assertEquals(expectedReply, reply); + } + } + + @Test + void interval() throws IOException { + try (var testServer = TestMailmanServer.createV3()) { + var listAddress = testServer.createList("test"); + var mailmanServer = MailingListServerFactory.createMailman3Server(testServer.getArchive(), testServer.getSMTP(), + Duration.ofDays(1)); + var mailmanList = mailmanServer.getListReader(listAddress); + var sender = EmailAddress.from("Test", "test@test.email"); + var mail1 = Email.create(sender, "Subject 1", "Body 1") + .recipient(EmailAddress.parse(listAddress)) + .build(); + var mail2 = Email.create(sender, "Subject 2", "Body 2") + .recipient(EmailAddress.parse(listAddress)) + .build(); + new Thread(() -> { + mailmanServer.post(mail1); + mailmanServer.post(mail2); + }).start(); + var expectedMail = Email.from(mail1) + .sender(EmailAddress.parse(listAddress)) + .build(); + + testServer.processIncoming(); + assertThrows(RuntimeException.class, () -> testServer.processIncoming(Duration.ZERO)); + + var conversations = mailmanList.conversations(Duration.ofDays(1)); + assertEquals(1, conversations.size()); + var conversation = conversations.get(0); + assertEquals(expectedMail, conversation.first()); + } + } + + @Test + void poll3days() throws Exception { + try (var testServer = TestMailmanServer.createV3()) { + var listAddress = testServer.createList("test"); + var now = ZonedDateTime.now(); + var mailmanServer = new Mailman3Server(testServer.getArchive(), + testServer.getSMTP(), Duration.ZERO, now.minusDays(2)); + var mailmanList = mailmanServer.getListReader(listAddress); + var sender = EmailAddress.from("Test", "test@test.email"); + + var duration3Days = Duration.between(now.minusDays(3), now); + + { + // A 2 days old should be picked up + var mail2daysAgo = Email.create(sender, "Subject 2 day2 ago", "Body 1") + .recipient(EmailAddress.parse(listAddress)) + .date(now.minusDays(2)) + .build(); + mailmanServer.post(mail2daysAgo); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(1, conversations.size()); + assertEquals(3, testServer.callCount(), + "Server wasn't for initial interval plus every day since start time"); + } + { + // A 2 days old mail should not be picked up now as old results should be cached + var mail2daysAgo2 = Email.create(sender, "Subject 2 days ago 2", "Body 2") + .recipient(EmailAddress.parse(listAddress)) + .date(now.minusDays(2)) + .build(); + mailmanServer.post(mail2daysAgo2); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(1, conversations.size()); + assertEquals(1, testServer.callCount(), "Server wasn't called once"); + } + { + // A 1-day-old mail should not be picked up now as old results should be cached + var mail1dayAgo = Email.create(sender, "Subject 1 day ago", "Body 2") + .recipient(EmailAddress.parse(listAddress)) + .date(now.minusDays(1)) + .build(); + mailmanServer.post(mail1dayAgo); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(1, conversations.size()); + assertEquals(1, testServer.callCount()); + } + { + // A current mail should be found + var mailNow = Email.create(sender, "Subject now", "Body 3") + .recipient(EmailAddress.parse(listAddress)) + .build(); + mailmanServer.post(mailNow); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(2, conversations.size()); + assertEquals(1, testServer.callCount()); + } + { + // Another mail from last month should not be found + var mail1dayAgo2 = Email.create(sender, "Subject 1 day ago 2", "Body 2") + .recipient(EmailAddress.parse(listAddress)) + .date(now.minusDays(1)) + .build(); + mailmanServer.post(mail1dayAgo2); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(2, conversations.size()); + assertEquals(1, testServer.callCount()); + } + { + // Another current mail should be found + var mailNow2 = Email.create(sender, "Subject now 2", "Body 3") + .recipient(EmailAddress.parse(listAddress)) + .build(); + mailmanServer.post(mailNow2); + testServer.processIncoming(); + testServer.resetCallCount(); + var conversations = mailmanList.conversations(duration3Days); + assertEquals(3, conversations.size()); + assertEquals(1, testServer.callCount()); + } + } + } +} diff --git a/test/src/main/java/org/openjdk/skara/test/TestMailmanServer.java b/test/src/main/java/org/openjdk/skara/test/TestMailmanServer.java index e65815bde..ec8c51858 100644 --- a/test/src/main/java/org/openjdk/skara/test/TestMailmanServer.java +++ b/test/src/main/java/org/openjdk/skara/test/TestMailmanServer.java @@ -23,7 +23,11 @@ package org.openjdk.skara.test; import com.sun.net.httpserver.*; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.zip.GZIPOutputStream; import org.openjdk.skara.email.*; import org.openjdk.skara.mailinglist.Mbox; import org.openjdk.skara.network.URIBuilder; @@ -36,39 +40,35 @@ import java.util.*; import java.util.regex.Pattern; -public class TestMailmanServer implements AutoCloseable { - private final HttpServer httpServer; +public abstract class TestMailmanServer implements AutoCloseable { + protected final HttpServer httpServer; private final SMTPServer smtpServer; - private final Map> lists = new HashMap<>(); - private int callCount = 0; - private boolean lastResponseCached; - static private final Pattern listPathPattern = Pattern.compile("^/test/(.*?)/(.*)\\.txt"); + public static TestMailmanServer createV2() throws IOException { + return new TestMailman2Server(); + } + + public static TestMailmanServer createV3() throws IOException { + return new TestMailman3Server(); + } private class Handler implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { callCount++; - var listMatcher = listPathPattern.matcher(exchange.getRequestURI().getPath()); - if (!listMatcher.matches()) { - throw new RuntimeException(); - } - var listPath = listMatcher.group(1); - var datePath = listMatcher.group(2); - var listMap = lists.get(listPath); - if (!listMap.containsKey(datePath)) { + var mboxContents = getMboxContents(exchange); + if (mboxContents == null) { exchange.sendResponseHeaders(404, 0); exchange.close(); return; } - var response = listMap.get(datePath).toString(); lastResponseCached = false; try { var digest = MessageDigest.getInstance("SHA-256"); - digest.update(response.getBytes(StandardCharsets.UTF_8)); + digest.update(mboxContents); var etag = "\"" + Base64.getUrlEncoder().encodeToString(digest.digest()) + "\""; exchange.getResponseHeaders().add("ETag", etag); @@ -80,10 +80,9 @@ public void handle(HttpExchange exchange) throws IOException { } } - var responseBytes = response.getBytes(StandardCharsets.UTF_8); - exchange.sendResponseHeaders(200, responseBytes.length); + exchange.sendResponseHeaders(200, mboxContents.length); OutputStream outputStream = exchange.getResponseBody(); - outputStream.write(responseBytes); + outputStream.write(mboxContents); outputStream.close(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); @@ -91,8 +90,7 @@ public void handle(HttpExchange exchange) throws IOException { } } - public TestMailmanServer() throws IOException - { + protected TestMailmanServer() throws IOException { InetSocketAddress address = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); httpServer = HttpServer.create(address, 0); httpServer.createContext("/test", new Handler()); @@ -102,6 +100,8 @@ public TestMailmanServer() throws IOException smtpServer = new SMTPServer(); } + protected abstract byte[] getMboxContents(HttpExchange exchange); + public URI getArchive() { return URIBuilder.base("http://" + httpServer.getAddress().getHostString() + ":" + httpServer.getAddress().getPort() + "/test/").build(); } @@ -110,13 +110,9 @@ public String getSMTP() { return smtpServer.address(); } - public String createList(String name) throws IOException { - var listName = EmailAddress.parse(name + "@" + httpServer.getAddress().getHostString()).toString(); - lists.put(name, new HashMap<>()); - return listName; - } + public abstract String createList(String name); - public void processIncoming(Duration timeout) throws IOException { + public void processIncoming(Duration timeout) { var email = smtpServer.receive(timeout); var subject = email.subject(); if (subject.startsWith("Re: ")) { @@ -127,18 +123,12 @@ public void processIncoming(Duration timeout) throws IOException { .build(); var mboxEntry = Mbox.fromMail(stripped); - var listMap = email.recipients().stream() - .filter(recipient -> lists.containsKey(recipient.localPart())) - .map(recipient -> lists.get(recipient.localPart())) - .findAny().orElseThrow(); - var datePath = DateTimeFormatter.ofPattern("yyyy-MMMM", Locale.US).format(email.date()); - if (!listMap.containsKey(datePath)) { - listMap.put(datePath, new StringBuilder()); - } - listMap.get(datePath).append(mboxEntry); + archiveEmail(email, mboxEntry); } - public void processIncoming() throws IOException { + protected abstract void archiveEmail(Email email, String mboxEntry); + + public void processIncoming() { processIncoming(Duration.ofSeconds(10)); } @@ -160,3 +150,125 @@ public int callCount() { return callCount; } } + +class TestMailman2Server extends TestMailmanServer { + + private static final Pattern listPathPattern = Pattern.compile("^/test/(.*?)/(.*)\\.txt"); + // Map from local part of email list name to map from date string to mbox contents + private final Map> lists = new HashMap<>(); + + public TestMailman2Server() throws IOException { + super(); + } + + @Override + protected void archiveEmail(Email email, String mboxEntry) { + var listMap = email.recipients().stream() + .filter(recipient -> lists.containsKey(recipient.localPart())) + .map(recipient -> lists.get(recipient.localPart())) + .findAny().orElseThrow(); + var datePath = DateTimeFormatter.ofPattern("yyyy-MMMM", Locale.US).format(email.date()); + if (!listMap.containsKey(datePath)) { + listMap.put(datePath, new StringBuilder()); + } + listMap.get(datePath).append(mboxEntry); + } + + @Override + protected byte[] getMboxContents(HttpExchange exchange) { + var listMatcher = listPathPattern.matcher(exchange.getRequestURI().getPath()); + if (!listMatcher.matches()) { + throw new RuntimeException(); + } + var listPath = listMatcher.group(1); + var datePath = listMatcher.group(2); + var listMap = lists.get(listPath); + var contents = listMap.get(datePath); + if (contents != null) { + return contents.toString().getBytes(StandardCharsets.UTF_8); + } else { + return null; + } + } + + @Override + public String createList(String name) { + var listName = EmailAddress.parse(name + "@" + httpServer.getAddress().getHostString()).toString(); + lists.put(name, new HashMap<>()); + return listName; + } +} + +class TestMailman3Server extends TestMailmanServer { + + private record EmailEntry(Email email, String mbox) {} + + private Map> lists = new HashMap<>(); + + private static final Pattern listPathPattern = Pattern.compile("^/test/list/(.*?)/export/(.*)\\.mbox.gz"); + + protected TestMailman3Server() throws IOException { + super(); + } + + @Override + protected byte[] getMboxContents(HttpExchange exchange) { + // https://mail-dev.example.com/archives/list/skara-test@mail-dev.example.com/export/foo.mbox.gz?start=2024-10-25&end=2025-10-25 + var listMatcher = listPathPattern.matcher(exchange.getRequestURI().getPath()); + if (!listMatcher.matches()) { + throw new RuntimeException(); + } + var listPath = listMatcher.group(1); + + var query = exchange.getRequestURI().getRawQuery(); + String[] pairs = query.split("&"); + ZonedDateTime start = null; + ZonedDateTime end = null; + for (String pair : pairs) { + int i = pair.indexOf("="); + if (i > 0) { + String key = URLDecoder.decode(pair.substring(0, i), StandardCharsets.UTF_8); + String value = URLDecoder.decode(pair.substring(i + 1), StandardCharsets.UTF_8); + if ("start".equals(key)) { + start = LocalDate.parse(value).atStartOfDay(ZoneId.systemDefault()); + } else if ("end".equals(key)) { + end = LocalDate.parse(value).atStartOfDay(ZoneId.systemDefault()); + } + } else { + throw new RuntimeException(); + } + } + var entryList = lists.get(listPath); + var mbox = new StringBuilder(); + var startDate = start; + var endDate = end; + entryList.stream() + .filter(e -> startDate == null || startDate.isBefore(e.email.date())) + .filter(e -> endDate == null || endDate.isAfter(e.email.date())) + .forEach(e -> mbox.append(e.mbox)); + + var zipped = new ByteArrayOutputStream(); + try (var out = new OutputStreamWriter(new GZIPOutputStream(zipped))) { + out.write(mbox.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } + return zipped.toByteArray(); + } + + @Override + public String createList(String name) { + var emailAddress = EmailAddress.parse(name + "@" + httpServer.getAddress().getHostString()); + lists.put(emailAddress.address(), new ArrayList<>()); + return emailAddress.toString(); + } + + @Override + protected void archiveEmail(Email email, String mboxEntry) { + var entryList = email.recipients().stream() + .filter(recipient -> lists.containsKey(recipient.address())) + .map(recipient -> lists.get(recipient.address())) + .findAny().orElseThrow(); + entryList.add(new EmailEntry(email, mboxEntry)); + } +}