Loading src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java +4 −32 Original line number Diff line number Diff line Loading @@ -6,18 +6,13 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.persistence.ListOfFilesDAO; import it.inaf.ia2.transfer.persistence.JobDAO; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; Loading Loading @@ -47,9 +42,6 @@ public class PutFileController extends FileController { @Autowired private JobDAO jobDAO; @Autowired private ListOfFilesDAO listOfFilesDAO; @PutMapping("/**") public ResponseEntity<?> putFile(@RequestHeader(value = HttpHeaders.CONTENT_ENCODING, required = false) String contentEncoding, @RequestParam(value = "file", required = false) MultipartFile file, Loading @@ -74,38 +66,18 @@ public class PutFileController extends FileController { try (InputStream in = file != null ? file.getInputStream() : request.getInputStream()) { FileInfo fileInfo = optFileInfo.get(); if (fileInfo.getAcceptViews() != null && fileInfo.getAcceptViews().contains("urn:list-of-files")) { storeListOfFiles(fileInfo, in); } else { if (file != null) { fileInfo.setContentType(file.getContentType()); } fileInfo.setContentEncoding(contentEncoding); storeGenericFile(fileInfo, in, jobId); } } return ResponseEntity.ok().build(); } else { return new ResponseEntity<>("File " + path + " not found", NOT_FOUND); } } private void storeListOfFiles(FileInfo fileInfo, InputStream is) throws IOException { List<String> filePaths = parseListOfFiles(is); listOfFilesDAO.createList(fileInfo.getVirtualPath(), filePaths); } private List<String> parseListOfFiles(InputStream is) throws IOException { List<String> filePaths = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { String line; while ((line = br.readLine()) != null && !line.isBlank()) { filePaths.add(line.trim()); } } return filePaths; } private void storeGenericFile(FileInfo fileInfo, InputStream is, String jobId) throws IOException, NoSuchAlgorithmException { File file = new File(fileInfo.getOsPath()); Loading src/main/java/it/inaf/ia2/transfer/persistence/ListOfFilesDAO.javadeleted 100644 → 0 +0 −96 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.persistence; import java.sql.PreparedStatement; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class ListOfFilesDAO { private final JdbcTemplate jdbcTemplate; @Autowired public ListOfFilesDAO(DataSource fileCatalogDatasource) { this.jdbcTemplate = new JdbcTemplate(fileCatalogDatasource); } public void createList(String vosListNodePath, List<String> vosPaths) { List<NodeIdPath> idPaths = getAllNodeIdPaths(vosListNodePath, vosPaths); if (idPaths.size() != (vosPaths.size() + 1)) { throw new IllegalStateException("Unable to retrieve some file identifiers from paths"); } Integer listNodeId = null; List<Integer> nodeIds = new ArrayList<>(); for (NodeIdPath idPath : idPaths) { if (vosListNodePath.equals(idPath.nodePath)) { listNodeId = idPath.nodeId; } else { nodeIds.add(idPath.nodeId); } } if (listNodeId == null) { throw new IllegalStateException("List node id not found for path " + vosListNodePath); } createList(listNodeId, nodeIds); } private List<NodeIdPath> getAllNodeIdPaths(String vosListNodePath, List<String> vosPaths) { List<String> allPaths = new ArrayList<>(vosPaths); allPaths.add(vosListNodePath); String sql = "SELECT node_id, vos_path FROM node_vos_path WHERE vos_path IN (" + String.join(",", Collections.nCopies(allPaths.size(), "?")) + ")"; return jdbcTemplate.query(conn -> { PreparedStatement ps = conn.prepareStatement(sql); int i = 0; for (String path : allPaths) { ps.setString(++i, path); } return ps; }, (row, index) -> { NodeIdPath nodeIdPath = new NodeIdPath(); nodeIdPath.nodeId = row.getInt("node_id"); nodeIdPath.nodePath = row.getString("vos_path"); return nodeIdPath; }); } private void createList(int listNodeId, List<Integer> nodes) { String sql = "INSERT INTO list_of_files (list_node_id, node_id) VALUES " + String.join(",", Collections.nCopies(nodes.size(), "(?, ?)")); jdbcTemplate.update(conn -> { PreparedStatement ps = conn.prepareStatement(sql); int i = 0; for (int nodeId : nodes) { ps.setInt(++i, listNodeId); ps.setInt(++i, nodeId); } return ps; }); } static class NodeIdPath { int nodeId; String nodePath; } } src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java +0 −25 Original line number Diff line number Diff line Loading @@ -7,11 +7,9 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.persistence.JobDAO; import it.inaf.ia2.transfer.persistence.ListOfFilesDAO; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.Optional; import java.util.UUID; import net.ivoa.xml.uws.v1.ExecutionPhase; Loading @@ -23,7 +21,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -51,9 +48,6 @@ public class PutFileControllerTest { @MockBean private JobDAO jobDAO; @MockBean private ListOfFilesDAO listOfFilesDAO; @Autowired private MockMvc mockMvc; Loading Loading @@ -177,25 +171,6 @@ public class PutFileControllerTest { assertTrue(file.delete()); } @Test public void putListOfFiles() throws Exception { String randomFileName = UUID.randomUUID().toString(); FileInfo fileInfo = createBaseFileInfo(randomFileName); fileInfo.setAcceptViews(Collections.singletonList("urn:list-of-files")); String content = "/path/to/file1\n/path/to/file2"; MockMultipartFile fakeFile = new MockMultipartFile("file", "test.txt", "text/plain", content.getBytes()); mockMvc.perform(putMultipart("/path/to/test.txt") .file(fakeFile)) .andDo(print()) .andExpect(status().isOk()); verify(listOfFilesDAO, times(1)).createList(any(), argThat(list -> list.size() == 2)); } private FileInfo createBaseFileInfo(String fileName) { FileInfo fileInfo = new FileInfo(); fileInfo.setOsPath(getTestFilePath(fileName)); Loading src/test/java/it/inaf/ia2/transfer/persistence/ListOfFilesDAOTest.javadeleted 100644 → 0 +0 −38 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.persistence; import java.util.Arrays; import java.util.List; import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {DataSourceConfig.class}) @TestPropertySource(locations = "classpath:test.properties") public class ListOfFilesDAOTest { @Autowired private DataSource dataSource; private ListOfFilesDAO listOfFilesDao; @BeforeEach public void init() { listOfFilesDao = new ListOfFilesDAO(dataSource); } @Test public void testCreateListOfFiles() { List<String> vosPaths = Arrays.asList("/test1/file1.txt", "/test1/file2.txt"); listOfFilesDao.createList("/test1/.tmp-123.txt", vosPaths); } } Loading
src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java +4 −32 Original line number Diff line number Diff line Loading @@ -6,18 +6,13 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.persistence.ListOfFilesDAO; import it.inaf.ia2.transfer.persistence.JobDAO; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; Loading Loading @@ -47,9 +42,6 @@ public class PutFileController extends FileController { @Autowired private JobDAO jobDAO; @Autowired private ListOfFilesDAO listOfFilesDAO; @PutMapping("/**") public ResponseEntity<?> putFile(@RequestHeader(value = HttpHeaders.CONTENT_ENCODING, required = false) String contentEncoding, @RequestParam(value = "file", required = false) MultipartFile file, Loading @@ -74,38 +66,18 @@ public class PutFileController extends FileController { try (InputStream in = file != null ? file.getInputStream() : request.getInputStream()) { FileInfo fileInfo = optFileInfo.get(); if (fileInfo.getAcceptViews() != null && fileInfo.getAcceptViews().contains("urn:list-of-files")) { storeListOfFiles(fileInfo, in); } else { if (file != null) { fileInfo.setContentType(file.getContentType()); } fileInfo.setContentEncoding(contentEncoding); storeGenericFile(fileInfo, in, jobId); } } return ResponseEntity.ok().build(); } else { return new ResponseEntity<>("File " + path + " not found", NOT_FOUND); } } private void storeListOfFiles(FileInfo fileInfo, InputStream is) throws IOException { List<String> filePaths = parseListOfFiles(is); listOfFilesDAO.createList(fileInfo.getVirtualPath(), filePaths); } private List<String> parseListOfFiles(InputStream is) throws IOException { List<String> filePaths = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { String line; while ((line = br.readLine()) != null && !line.isBlank()) { filePaths.add(line.trim()); } } return filePaths; } private void storeGenericFile(FileInfo fileInfo, InputStream is, String jobId) throws IOException, NoSuchAlgorithmException { File file = new File(fileInfo.getOsPath()); Loading
src/main/java/it/inaf/ia2/transfer/persistence/ListOfFilesDAO.javadeleted 100644 → 0 +0 −96 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.persistence; import java.sql.PreparedStatement; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class ListOfFilesDAO { private final JdbcTemplate jdbcTemplate; @Autowired public ListOfFilesDAO(DataSource fileCatalogDatasource) { this.jdbcTemplate = new JdbcTemplate(fileCatalogDatasource); } public void createList(String vosListNodePath, List<String> vosPaths) { List<NodeIdPath> idPaths = getAllNodeIdPaths(vosListNodePath, vosPaths); if (idPaths.size() != (vosPaths.size() + 1)) { throw new IllegalStateException("Unable to retrieve some file identifiers from paths"); } Integer listNodeId = null; List<Integer> nodeIds = new ArrayList<>(); for (NodeIdPath idPath : idPaths) { if (vosListNodePath.equals(idPath.nodePath)) { listNodeId = idPath.nodeId; } else { nodeIds.add(idPath.nodeId); } } if (listNodeId == null) { throw new IllegalStateException("List node id not found for path " + vosListNodePath); } createList(listNodeId, nodeIds); } private List<NodeIdPath> getAllNodeIdPaths(String vosListNodePath, List<String> vosPaths) { List<String> allPaths = new ArrayList<>(vosPaths); allPaths.add(vosListNodePath); String sql = "SELECT node_id, vos_path FROM node_vos_path WHERE vos_path IN (" + String.join(",", Collections.nCopies(allPaths.size(), "?")) + ")"; return jdbcTemplate.query(conn -> { PreparedStatement ps = conn.prepareStatement(sql); int i = 0; for (String path : allPaths) { ps.setString(++i, path); } return ps; }, (row, index) -> { NodeIdPath nodeIdPath = new NodeIdPath(); nodeIdPath.nodeId = row.getInt("node_id"); nodeIdPath.nodePath = row.getString("vos_path"); return nodeIdPath; }); } private void createList(int listNodeId, List<Integer> nodes) { String sql = "INSERT INTO list_of_files (list_node_id, node_id) VALUES " + String.join(",", Collections.nCopies(nodes.size(), "(?, ?)")); jdbcTemplate.update(conn -> { PreparedStatement ps = conn.prepareStatement(sql); int i = 0; for (int nodeId : nodes) { ps.setInt(++i, listNodeId); ps.setInt(++i, nodeId); } return ps; }); } static class NodeIdPath { int nodeId; String nodePath; } }
src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java +0 −25 Original line number Diff line number Diff line Loading @@ -7,11 +7,9 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.persistence.JobDAO; import it.inaf.ia2.transfer.persistence.ListOfFilesDAO; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.Optional; import java.util.UUID; import net.ivoa.xml.uws.v1.ExecutionPhase; Loading @@ -23,7 +21,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -51,9 +48,6 @@ public class PutFileControllerTest { @MockBean private JobDAO jobDAO; @MockBean private ListOfFilesDAO listOfFilesDAO; @Autowired private MockMvc mockMvc; Loading Loading @@ -177,25 +171,6 @@ public class PutFileControllerTest { assertTrue(file.delete()); } @Test public void putListOfFiles() throws Exception { String randomFileName = UUID.randomUUID().toString(); FileInfo fileInfo = createBaseFileInfo(randomFileName); fileInfo.setAcceptViews(Collections.singletonList("urn:list-of-files")); String content = "/path/to/file1\n/path/to/file2"; MockMultipartFile fakeFile = new MockMultipartFile("file", "test.txt", "text/plain", content.getBytes()); mockMvc.perform(putMultipart("/path/to/test.txt") .file(fakeFile)) .andDo(print()) .andExpect(status().isOk()); verify(listOfFilesDAO, times(1)).createList(any(), argThat(list -> list.size() == 2)); } private FileInfo createBaseFileInfo(String fileName) { FileInfo fileInfo = new FileInfo(); fileInfo.setOsPath(getTestFilePath(fileName)); Loading
src/test/java/it/inaf/ia2/transfer/persistence/ListOfFilesDAOTest.javadeleted 100644 → 0 +0 −38 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.persistence; import java.util.Arrays; import java.util.List; import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {DataSourceConfig.class}) @TestPropertySource(locations = "classpath:test.properties") public class ListOfFilesDAOTest { @Autowired private DataSource dataSource; private ListOfFilesDAO listOfFilesDao; @BeforeEach public void init() { listOfFilesDao = new ListOfFilesDAO(dataSource); } @Test public void testCreateListOfFiles() { List<String> vosPaths = Arrays.asList("/test1/file1.txt", "/test1/file2.txt"); listOfFilesDao.createList("/test1/.tmp-123.txt", vosPaths); } }