Commit 14e76602 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Removed 'list of files' workaround

parent c144b440
Loading
Loading
Loading
Loading
Loading
+4 −32
Original line number Diff line number Diff line
@@ -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;
@@ -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,
@@ -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());
+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;
    }
}
+0 −25
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -51,9 +48,6 @@ public class PutFileControllerTest {
    @MockBean
    private JobDAO jobDAO;

    @MockBean
    private ListOfFilesDAO listOfFilesDAO;

    @Autowired
    private MockMvc mockMvc;

@@ -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));
+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);
    }
}