You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2018/01/25 05:02:17 UTC

[06/16] james-project git commit: JAMES-2293 WebAdmin should allow to remove all mails from a mail repository

JAMES-2293 WebAdmin should allow to remove all mails from a mail repository

A task would be generated as the action can potentially be long.


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f2d8f04e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f2d8f04e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f2d8f04e

Branch: refs/heads/master
Commit: f2d8f04ebd9cf7600466f054aaee24dec30198be
Parents: 3c2559c
Author: benwa <bt...@linagora.com>
Authored: Mon Jan 22 13:46:58 2018 +0700
Committer: benwa <bt...@linagora.com>
Committed: Thu Jan 25 11:39:06 2018 +0700

----------------------------------------------------------------------
 .../webadmin/routes/MailRepositoriesRoutes.java |  68 +++++++++++-
 .../service/ClearMailRepositoryTask.java        |  97 +++++++++++++++++
 .../service/MailRepositoryStoreService.java     |   5 +
 .../routes/MailRepositoriesRoutesTest.java      | 109 ++++++++++++++++++-
 4 files changed, 275 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f2d8f04e/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java
index 4f106b7..5879de7 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/routes/MailRepositoriesRoutes.java
@@ -32,11 +32,15 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskId;
+import org.apache.james.task.TaskManager;
 import org.apache.james.util.streams.Limit;
 import org.apache.james.util.streams.Offset;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.ExtendedMailRepositoryResponse;
+import org.apache.james.webadmin.dto.TaskIdDto;
 import org.apache.james.webadmin.service.MailRepositoryStoreService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.ErrorResponder.ErrorType;
@@ -51,6 +55,7 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
+import io.swagger.jaxrs.PATCH;
 import spark.Request;
 import spark.Service;
 
@@ -63,12 +68,14 @@ public class MailRepositoriesRoutes implements Routes {
 
     private final JsonTransformer jsonTransformer;
     private final MailRepositoryStoreService repositoryStoreService;
+    private final TaskManager taskManager;
     private Service service;
 
     @Inject
-    public MailRepositoriesRoutes(MailRepositoryStoreService repositoryStoreService, JsonTransformer jsonTransformer) {
+    public MailRepositoriesRoutes(MailRepositoryStoreService repositoryStoreService, JsonTransformer jsonTransformer, TaskManager taskManager) {
         this.repositoryStoreService = repositoryStoreService;
         this.jsonTransformer = jsonTransformer;
+        this.taskManager = taskManager;
     }
 
     @Override
@@ -84,6 +91,8 @@ public class MailRepositoriesRoutes implements Routes {
         defineGetMail();
 
         defineDeleteMail();
+
+        defineDeleteAll();
     }
 
     @GET
@@ -169,7 +178,7 @@ public class MailRepositoriesRoutes implements Routes {
                         .type(ErrorResponder.ErrorType.NOT_FOUND)
                         .message("Could not retrieve " + mailKey)
                         .haltError());
-            } catch (MailRepositoryStore.MailRepositoryStoreException| MessagingException e) {
+            } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) {
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500)
                     .type(ErrorResponder.ErrorType.SERVER_ERROR)
@@ -237,7 +246,60 @@ public class MailRepositoriesRoutes implements Routes {
         });
     }
 
-private Optional<Integer> assertPositiveInteger(Request request, String parameterName) {
+    @PATCH
+    @Path("/{encodedUrl}/mails")
+    @ApiOperation(value = "Deleting all mails in that mailRepository")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+            required = true,
+            paramType = "query parameter",
+            dataType = "String",
+            example = "?action=clear",
+            value = "Specify the action. Only clear is supported. clear removes all mails from that mail repository.")
+    })
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.CREATED_201, message = "All mails are deleted", response = TaskIdDto.class),
+        @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side."),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - unknown action")
+    })
+    public void defineDeleteAll() {
+        service.patch(MAIL_REPOSITORIES + "/:encodedUrl/mails", (request, response) -> {
+            String url = URLDecoder.decode(request.params("encodedUrl"), StandardCharsets.UTF_8.displayName());
+            try {
+                ensureSpecifiedClearAction(request);
+                Task task = repositoryStoreService.createClearMailRepositoryTask(url);
+                TaskId taskId = taskManager.submit(task);
+                return TaskIdDto.respond(response, taskId);
+            } catch (MailRepositoryStore.MailRepositoryStoreException | MessagingException e) {
+                throw ErrorResponder.builder()
+                    .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500)
+                    .type(ErrorResponder.ErrorType.SERVER_ERROR)
+                    .cause(e)
+                    .message("Error while deleting all mails")
+                    .haltError();
+            }
+        }, jsonTransformer);
+    }
+
+    private void ensureSpecifiedClearAction(Request request) {
+        String action = request.queryParams("action");
+        if (Strings.isNullOrEmpty(action)) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+                .message("You need to specify an action. Currently only clear is supported.")
+                .haltError();
+        }
+        if (!action.equals("clear")) {
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+                .message("Unknown action " + action)
+                .haltError();
+        }
+    }
+
+    private Optional<Integer> assertPositiveInteger(Request request, String parameterName) {
         try {
             return Optional.ofNullable(request.queryParams(parameterName))
                 .filter(s -> !Strings.isNullOrEmpty(s))

http://git-wip-us.apache.org/repos/asf/james-project/blob/f2d8f04e/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java
new file mode 100644
index 0000000..132e36c
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/ClearMailRepositoryTask.java
@@ -0,0 +1,97 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.webadmin.service;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.task.Task;
+import org.apache.james.task.TaskExecutionDetails;
+
+import com.google.common.base.Throwables;
+
+public class ClearMailRepositoryTask implements Task {
+
+    public static final String TYPE = "clearMailRepository";
+
+    public static class AdditionalInformation implements TaskExecutionDetails.AdditionalInformation {
+        private final String repositoryUrl;
+        private final Supplier<Long> countSupplier;
+        private final long initialCount;
+
+        public AdditionalInformation(String repositoryUrl, Supplier<Long> countSupplier) {
+            this.repositoryUrl = repositoryUrl;
+            this.initialCount = countSupplier.get();
+            this.countSupplier = countSupplier;
+        }
+
+        public String getRepositoryUrl() {
+            return repositoryUrl;
+        }
+
+        public long getRemainingCount() {
+            return countSupplier.get();
+        }
+
+        public long getInitialCount() {
+            return initialCount;
+        }
+    }
+
+    private final MailRepository mailRepository;
+    private final AdditionalInformation additionalInformation;
+
+    public ClearMailRepositoryTask(MailRepository mailRepository, String url) {
+        this.mailRepository = mailRepository;
+        this.additionalInformation = new AdditionalInformation(url, this::getRemainingSize);
+    }
+
+    @Override
+    public Result run() {
+        try {
+            mailRepository.removeAll();
+            return Result.COMPLETED;
+        } catch (MessagingException e) {
+            LOGGER.error("Encountered error while clearing repository", e);
+            return Result.PARTIAL;
+        }
+    }
+
+    @Override
+    public String type() {
+        return TYPE;
+    }
+
+    @Override
+    public Optional<TaskExecutionDetails.AdditionalInformation> details() {
+        return Optional.of(additionalInformation);
+    }
+
+    public long getRemainingSize() {
+        try {
+            return mailRepository.size();
+        } catch (MessagingException e) {
+            throw Throwables.propagate(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f2d8f04e/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
index d7ca74a..fd17507 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/main/java/org/apache/james/webadmin/service/MailRepositoryStoreService.java
@@ -27,6 +27,7 @@ import javax.mail.MessagingException;
 
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.task.Task;
 import org.apache.james.util.streams.Iterators;
 import org.apache.james.util.streams.Limit;
 import org.apache.james.util.streams.Offset;
@@ -85,4 +86,8 @@ public class MailRepositoryStoreService {
             .remove(mailKey);
     }
 
+    public Task createClearMailRepositoryTask(String url) throws MailRepositoryStore.MailRepositoryStoreException, MessagingException {
+        return new ClearMailRepositoryTask(mailRepositoryStore.select(url), url);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/f2d8f04e/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
index 6a3f0ac..6829f22 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
@@ -21,6 +21,7 @@ package org.apache.james.webadmin.routes;
 
 import static com.jayway.restassured.RestAssured.given;
 import static com.jayway.restassured.RestAssured.when;
+import static com.jayway.restassured.RestAssured.with;
 import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
 import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
 import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
@@ -32,6 +33,7 @@ import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.isEmptyOrNullString;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -41,8 +43,10 @@ import java.util.List;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.memory.MemoryMailRepository;
 import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.service.ClearMailRepositoryTask;
 import org.apache.james.webadmin.service.MailRepositoryStoreService;
 import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
@@ -71,9 +75,13 @@ public class MailRepositoriesRoutesTest {
         mailRepositoryStore = mock(MailRepositoryStore.class);
         mailRepository = new MemoryMailRepository();
 
+        MemoryTaskManager taskManager = new MemoryTaskManager();
+        JsonTransformer jsonTransformer = new JsonTransformer();
         webAdminServer = WebAdminUtils.createWebAdminServer(
                 new NoopMetricFactory(),
-                new MailRepositoriesRoutes(new MailRepositoryStoreService(mailRepositoryStore), new JsonTransformer()));
+                new MailRepositoriesRoutes(new MailRepositoryStoreService(mailRepositoryStore),
+                    jsonTransformer, taskManager),
+            new TasksRoutes(taskManager, jsonTransformer));
         webAdminServer.configure(NO_CONFIGURATION);
         webAdminServer.await();
 
@@ -472,4 +480,103 @@ public class MailRepositoriesRoutesTest {
             .statusCode(HttpStatus.NO_CONTENT_204);
     }
 
+    @Test
+    public void deletingAllMailsShouldCreateATask() throws Exception {
+        when(mailRepositoryStore.select(URL_MY_REPO)).thenReturn(mailRepository);
+
+        when()
+            .patch(URL_ESCAPED_MY_REPO + "/mails?action=clear")
+        .then()
+            .statusCode(HttpStatus.CREATED_201)
+            .header("Location", is(notNullValue()))
+            .body("taskId", is(notNullValue()));
+    }
+
+    @Test
+    public void patchShouldOnlySupportClear() throws Exception {
+        when(mailRepositoryStore.select(URL_MY_REPO)).thenReturn(mailRepository);
+
+        when()
+            .patch(URL_ESCAPED_MY_REPO + "/mails?action=invalid")
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .body("statusCode", is(400))
+            .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+            .body("message", is("Unknown action invalid"));
+    }
+
+    @Test
+    public void patchShouldRequireAnAction() throws Exception {
+        when(mailRepositoryStore.select(URL_MY_REPO)).thenReturn(mailRepository);
+
+        when()
+            .patch(URL_ESCAPED_MY_REPO + "/mails")
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .body("statusCode", is(400))
+            .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+            .body("message", is("You need to specify an action. Currently only clear is supported."));
+    }
+
+    @Test
+    public void clearTaskShouldHaveDetails() throws Exception {
+        when(mailRepositoryStore.select(URL_MY_REPO)).thenReturn(mailRepository);
+
+        String name1 = "name1";
+        String name2 = "name2";
+        mailRepository.store(FakeMail.builder()
+            .name(name1)
+            .build());
+        mailRepository.store(FakeMail.builder()
+            .name(name2)
+            .build());
+
+        String taskId = with()
+            .patch(URL_ESCAPED_MY_REPO + "/mails?action=clear")
+            .jsonPath()
+            .get("taskId");
+
+        given()
+            .basePath(TasksRoutes.BASE)
+        .when()
+            .get(taskId + "/await")
+        .then()
+            .body("status", is("completed"))
+            .body("taskId", is(notNullValue()))
+            .body("type", is(ClearMailRepositoryTask.TYPE))
+            .body("additionalInformation.repositoryUrl", is(URL_MY_REPO))
+            .body("additionalInformation.initialCount", is(2))
+            .body("additionalInformation.remainingCount", is(0))
+            .body("startedDate", is(notNullValue()))
+            .body("submitDate", is(notNullValue()))
+            .body("completedDate", is(notNullValue()));
+    }
+
+    @Test
+    public void clearTaskShouldRemoveAllTheMailsFromTheMailRepository() throws Exception {
+        when(mailRepositoryStore.select(URL_MY_REPO)).thenReturn(mailRepository);
+
+        mailRepository.store(FakeMail.builder()
+            .name("name1")
+            .build());
+        mailRepository.store(FakeMail.builder()
+            .name("name2")
+            .build());
+
+        String taskId = with()
+            .patch(URL_ESCAPED_MY_REPO + "/mails?action=clear")
+            .jsonPath()
+            .get("taskId");
+
+        given()
+            .basePath(TasksRoutes.BASE)
+            .get(taskId + "/await");
+
+        when()
+            .get(URL_ESCAPED_MY_REPO + "/mails")
+        .then()
+            .statusCode(HttpStatus.OK_200)
+            .body("", hasSize(0));
+    }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org