diff --git a/src/main/java/it/inaf/oats/vospace/FileServiceClient.java b/src/main/java/it/inaf/oats/vospace/FileServiceClient.java index f17719eafe7923c02b8e591d87b496cae92d27d8..a976e921463f9705737e3daf966af811b50418a5 100644 --- a/src/main/java/it/inaf/oats/vospace/FileServiceClient.java +++ b/src/main/java/it/inaf/oats/vospace/FileServiceClient.java @@ -7,14 +7,19 @@ package it.inaf.oats.vospace; import com.fasterxml.jackson.databind.ObjectMapper; import it.inaf.ia2.aa.data.User; +import it.inaf.oats.vospace.datamodel.NodeUtils; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; +import it.inaf.oats.vospace.exception.NodeNotFoundException; import it.inaf.oats.vospace.parent.exchange.ArchiveEntryDescriptor; +import it.inaf.oats.vospace.persistence.NodeDAO; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; +import net.ivoa.xml.vospace.v2.ContainerNode; +import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Transfer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -41,10 +46,13 @@ public class FileServiceClient { @Autowired private HttpServletRequest request; - + @Autowired private LinkService linkService; + @Autowired + private NodeDAO nodeDAO; + public String startArchiveJob(Transfer transfer, String jobId) { String target = transfer.getTarget().substring("vos://".length() + authority.length()); @@ -69,11 +77,33 @@ public class FileServiceClient { // Add target path vosPaths.add(target); } - - // OK generate descriptors - + + // Generate descriptors + // Expand container nodes into direct children list + List<String> expandedVosPaths = new ArrayList<>(); + + for (String vosPath : vosPaths) { + Node node + = nodeDAO.listNode(vosPath) + .orElseThrow(() -> { + throw new NodeNotFoundException(vosPath); + }); + + if (node instanceof ContainerNode) { + List<Node> nodes = ((ContainerNode) node).getNodes(); + if (nodes.isEmpty()) { + expandedVosPaths.add(NodeUtils.getVosPath(node)); + } else { + expandedVosPaths.addAll(nodes + .stream().map(n -> NodeUtils.getVosPath(n)) + .collect(Collectors.toList())); + } + } + + } + // follow links to links in vosPaths - List<ArchiveEntryDescriptor> entryDescriptors = linkService.followLinksForArchiveService(vosPaths); + List<ArchiveEntryDescriptor> entryDescriptors = linkService.followLinksForArchiveService(expandedVosPaths); ArchiveRequest archiveRequest = new ArchiveRequest(); archiveRequest.setJobId(jobId); @@ -97,17 +127,17 @@ public class FileServiceClient { return res.getHeaders().getLocation().toString(); }, new Object[]{}); } - - public void startFileCopyJob(String sourceVosPath, + + public void startFileCopyJob(String sourceVosPath, String destiantionVosPath, String jobId, User user) { - + CopyRequest copyRequest = new CopyRequest(); copyRequest.setJobId(jobId); copyRequest.setSourceRootVosPath(sourceVosPath); copyRequest.setDestinationRootVosPath(destiantionVosPath); - + String url = fileServiceUrl + "/copy"; - + String token = user.getAccessToken(); restTemplate.execute(url, HttpMethod.POST, req -> { HttpHeaders headers = req.getHeaders(); @@ -119,12 +149,12 @@ public class FileServiceClient { try (OutputStream os = req.getBody()) { MAPPER.writeValue(os, copyRequest); } - }, res -> { - return null; + }, res -> { + return null; }, new Object[]{}); - + } - + public static class CopyRequest { private String jobId; @@ -161,7 +191,7 @@ public class FileServiceClient { private String type; private String jobId; - private List<ArchiveEntryDescriptor> entryDescriptors; + private List<ArchiveEntryDescriptor> entryDescriptors; public String getType() { return type; diff --git a/src/main/java/it/inaf/oats/vospace/LinkService.java b/src/main/java/it/inaf/oats/vospace/LinkService.java index 06530cb45b8c875cc3a431efd0690f45b6769eb1..729c643a34a5d83eefc9b5972fbe6b76b9455760 100644 --- a/src/main/java/it/inaf/oats/vospace/LinkService.java +++ b/src/main/java/it/inaf/oats/vospace/LinkService.java @@ -67,7 +67,7 @@ public class LinkService { } private ArchiveEntryDescriptor getLinkNodeArchiveEntryDescriptor(LinkNode node){ - String vosPath = NodeUtils.getVosPath(node); + String vosPath = NodeUtils.getVosPath(node); String targetNodeVosPath = NodeUtils.getVosPath(this.followLink(node)); return new ArchiveEntryDescriptor(vosPath, targetNodeVosPath); diff --git a/src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java b/src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java index 0ed704218f9b3d8a161f59fea50f45da648c039d..9ec78b9fb679cb4250975eb692873f656978d8e2 100644 --- a/src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java +++ b/src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java @@ -11,12 +11,16 @@ import it.inaf.oats.vospace.FileServiceClient.ArchiveRequest; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; import it.inaf.oats.vospace.parent.exchange.ArchiveEntryDescriptor; +import it.inaf.oats.vospace.persistence.NodeDAO; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URI; import java.util.List; +import java.util.Optional; import javax.servlet.http.HttpServletRequest; +import net.ivoa.xml.vospace.v2.ContainerNode; +import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.Param; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.View; @@ -30,6 +34,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -59,6 +64,9 @@ public class FileServiceClientTest { @Mock private LinkService linkService; + + @Mock + private NodeDAO nodeDAO; @InjectMocks private FileServiceClient fileServiceClient; @@ -98,6 +106,11 @@ public class FileServiceClientTest { view.setUri(Views.ZIP_VIEW_URI); transfer.setView(view); + ContainerNode node = Mockito.mock(ContainerNode.class); + when(node.getNodes()).thenReturn(List.of()); + when(node.getUri()).thenReturn("vos://example.com!vospace/mydir"); + when(nodeDAO.listNode(eq("/mydir"))).thenReturn(Optional.of(node)); + when(linkService.followLinksForArchiveService(any())) .thenReturn(List.of(new ArchiveEntryDescriptor("/mydir"))); @@ -162,6 +175,14 @@ public class FileServiceClientTest { param2.setValue("file2"); view.getParam().add(param2); + DataNode node1 = Mockito.mock(DataNode.class); + when(node1.getUri()).thenReturn("vos://example.com!vospace/parent_dir/file1"); + when(nodeDAO.listNode(eq("/parent_dir/file1"))).thenReturn(Optional.of(node1)); + + DataNode node2 = Mockito.mock(DataNode.class); + when(node2.getUri()).thenReturn("vos://example.com!vospace/parent_dir/file2"); + when(nodeDAO.listNode(eq("/parent_dir/file2"))).thenReturn(Optional.of(node2)); + when(linkService.followLinksForArchiveService(any())).thenReturn( List.of(new ArchiveEntryDescriptor("/parent_dir/file1"), new ArchiveEntryDescriptor("/parent_dir/file2") diff --git a/src/test/java/it/inaf/oats/vospace/LinkServiceTest.java b/src/test/java/it/inaf/oats/vospace/LinkServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..091e4d0ccd7348c8c494a3b6ec0e0646134025f6 --- /dev/null +++ b/src/test/java/it/inaf/oats/vospace/LinkServiceTest.java @@ -0,0 +1,61 @@ +/* + * This file is part of vospace-rest + * Copyright (C) 2021 Istituto Nazionale di Astrofisica + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package it.inaf.oats.vospace; + +import it.inaf.ia2.aa.data.User; +import it.inaf.oats.vospace.exception.NodeBusyException; +import it.inaf.oats.vospace.exception.NodeNotFoundException; +import it.inaf.oats.vospace.exception.PermissionDeniedException; +import it.inaf.oats.vospace.parent.exchange.ArchiveEntryDescriptor; +import it.inaf.oats.vospace.persistence.DataSourceConfigSingleton; +import it.inaf.oats.vospace.persistence.NodeDAO; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import net.ivoa.xml.vospace.v2.Transfer; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +//@AutoConfigureMockMvc +@TestPropertySource(locations = "classpath:test.properties", properties = {"vospace-authority=example.com!vospace", "file-service-url=http://file-service"}) +@ContextConfiguration(classes = {DataSourceConfigSingleton.class}) +public class LinkServiceTest { + + @Autowired + private LinkService linkService; + + @Test + public void testFollowLinksForArchiveService() { + List<String> vosPaths = List.of("/test3/m1/link2", "/test3/m1/m2"); + + List<ArchiveEntryDescriptor> aed = linkService.followLinksForArchiveService(vosPaths); + + assertEquals(2, aed.size()); + List<String> targetVosPaths = aed.stream().map(a -> a.getTargetNodeVosPath()) + .collect(Collectors.toList()); + + System.out.println(targetVosPaths); + assertTrue(targetVosPaths.containsAll(List.of("/test3/m1/m2", "/test1/f1/f2_renamed/f3"))); + + } + + +} diff --git a/src/test/resources/test-data.sql b/src/test/resources/test-data.sql index 7827a3af033234d0933bc14a43b5393a98ce348f..b9e8f6d18bb59a785e9e6dd52c923bfda64f70e2 100644 --- a/src/test/resources/test-data.sql +++ b/src/test/resources/test-data.sql @@ -43,6 +43,7 @@ INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, gro INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, group_write, group_read, is_public, location_id) VALUES ('19', '', 'destination2', 'container', 'user3', '{"group1"}', '{"group1"}', false, 3); -- /mycontainer/destination2 INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, group_write, group_read, is_public, location_id) VALUES ('19.21', '20', 'control', 'container', 'user3', '{"group1"}', '{"group1"}', false, 3); -- /mycontainer/destination2/control +INSERT INTO node (parent_path, parent_relative_path, name, type, creator_id, group_write, group_read, is_public, location_id, target) VALUES ('9.10', '', 'link2', 'link', 'user3', '{"group1"}', '{"group1"}', false, 3, 'vos://example.com!vospace/test1/f1/f2_renamed/f3'); -- /test3/m1/link2 DELETE FROM job;