diff --git a/src/main/java/it/inaf/oats/vospace/TransferController.java b/src/main/java/it/inaf/oats/vospace/TransferController.java index 330e1dcb4068cb3bcfba69dce5b3216a38f65e34..292ff53474bc3345a784aa9bc87d0560bb6b1762 100644 --- a/src/main/java/it/inaf/oats/vospace/TransferController.java +++ b/src/main/java/it/inaf/oats/vospace/TransferController.java @@ -25,6 +25,7 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import net.ivoa.xml.uws.v1.ErrorSummary; import net.ivoa.xml.vospace.v2.Protocol; @RestController @@ -97,7 +98,7 @@ public class TransferController { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(jobSummary.getErrorSummary().getMessage()); } - + // Behaves as if REQUEST=redirect was set, for compatibility with CADC client String endpoint = transfer.getProtocols().get(0).getEndpoint(); HttpHeaders headers = new HttpHeaders(); @@ -110,6 +111,24 @@ public class TransferController { return jobDAO.getJob(jobId).map(j -> ResponseEntity.ok(j)).orElse(ResponseEntity.notFound().build()); } + @GetMapping(value = "/transfers/{jobId}/error", produces = {MediaType.TEXT_PLAIN_VALUE}) + public ResponseEntity<String> getJobError(@PathVariable("jobId") String jobId) { + return jobDAO.getJob(jobId).map(j -> { + if (j.getPhase().equals(ExecutionPhase.ERROR)) { + + ErrorSummary e = j.getErrorSummary(); + + if (e.isHasDetail()) { + return ResponseEntity.ok(e.getDetailMessage()); + } else { + return ResponseEntity.ok("No error details available"); + } + } else { + return ResponseEntity.ok("Job is not in ERROR phase"); + } + }).orElse(ResponseEntity.notFound().build()); + } + @PostMapping(value = "/transfers/{jobId}/phase") public ResponseEntity<?> setJobPhase(@PathVariable("jobId") String jobId, @RequestParam("PHASE") String phase, User principal) { diff --git a/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java b/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java index 85fce66cc1981d25098af3a53fc204aa766f11c6..ecbd244686e729e468434bc8c331377c0f22c14d 100644 --- a/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java +++ b/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java @@ -3,6 +3,8 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import static it.inaf.oats.vospace.VOSpaceXmlTestUtil.loadDocument; import it.inaf.oats.vospace.datamodel.NodeProperties; +import it.inaf.oats.vospace.exception.ErrorSummaryFactory; +import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.persistence.JobDAO; import it.inaf.oats.vospace.persistence.LocationDAO; import it.inaf.oats.vospace.persistence.NodeDAO; @@ -46,6 +48,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.w3c.dom.Document; import java.util.List; +import net.ivoa.xml.uws.v1.ErrorSummary; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import static org.mockito.ArgumentMatchers.argThat; @@ -258,6 +261,54 @@ public class TransferControllerTest { verify(jobDao, times(1)).getJob(eq("123")); } + + @Test + public void testErrorEndpoint() throws Exception { + JobSummary job = new JobSummary(); + job.setJobId("123"); + job.setPhase(ExecutionPhase.EXECUTING); + ErrorSummary e = ErrorSummaryFactory.newErrorSummary( + new PermissionDeniedException("/pippo1/pippo2") + ); + job.setErrorSummary(e); + + when(jobDao.getJob(eq("123"))).thenReturn(Optional.of(job)); + + String response = mockMvc.perform(get("/transfers/123/error") + .accept(MediaType.TEXT_PLAIN_VALUE)) + .andDo(print()) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + assertEquals("Job is not in ERROR phase", response); + + job.setPhase(ExecutionPhase.ERROR); + + response = mockMvc.perform(get("/transfers/123/error") + .accept(MediaType.TEXT_PLAIN_VALUE)) + .andDo(print()) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + assertEquals(e.getDetailMessage(), response); + + e.setHasDetail(false); + + response = mockMvc.perform(get("/transfers/123/error") + .accept(MediaType.TEXT_PLAIN_VALUE)) + .andDo(print()) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + assertEquals("No error details available", response); + + when(jobDao.getJob(eq("124"))).thenReturn(Optional.ofNullable(null)); + + mockMvc.perform(get("/transfers/124/error") + .accept(MediaType.TEXT_PLAIN_VALUE)) + .andDo(print()) + .andExpect(status().is4xxClientError()); + } @Test public void testGetJobs() throws Exception {