diff --git a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java index 4a24771868eb2407dbf48384cd370fb6c91b192e..b4a3a166e4a2a9994cda72d37de34ae880cfbb63 100644 --- a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java +++ b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java @@ -98,7 +98,9 @@ public class GetFileController { return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR); } - response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); + String vosName = fileInfo.getVirtualPath().substring(fileInfo.getVirtualPath().lastIndexOf("/") + 1); + + response.setHeader("Content-Disposition", "attachment; filename=" + vosName); response.setHeader("Content-Length", String.valueOf(file.length())); byte[] bytes = new byte[1024]; diff --git a/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java index 08a984f9ad8f55b8d6e207dea14eb97e06d784cf..4c9c724c739d2e5d1a94a5b060925afa9cb1624d 100644 --- a/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java +++ b/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java @@ -89,6 +89,51 @@ public class PutFileController { } } - Files.copy(is, file.toPath()); + String originalFileName = file.getName(); + file = getEmptyFile(file, 1); + if (!originalFileName.equals(file.getName())) { + fileDAO.setOsName(fileInfo.getNodeId(), file.getName()); + } + + try { + fileDAO.setBusy(fileInfo.getNodeId(), true); + Files.copy(is, file.toPath()); + } catch (IOException ex) { + throw ex; + } finally { + fileDAO.setBusy(fileInfo.getNodeId(), false); + } + } + + /** + * Handles duplicate file uploads generating a new non existent path. This + * is necessary in some edge cases, like when a file has been renamed in + * VOSpace only but the original file on disk still has the old name or if a + * file has been marked for deletion and a file with the same name is + * uploaded before the cleanup. + */ + private File getEmptyFile(File file, int index) { + if (file.exists()) { + + String fileName = file.getName(); + + String nameWithoutExtension; + String extension = null; + if (fileName.contains(".")) { + nameWithoutExtension = fileName.substring(0, fileName.lastIndexOf(".")); + extension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()); + } else { + nameWithoutExtension = fileName; + } + + String newName = nameWithoutExtension + "-" + index; + if (extension != null) { + newName += "." + extension; + } + + File newFile = file.toPath().getParent().resolve(newName).toFile(); + return getEmptyFile(newFile, index + 1); + } + return file; } } diff --git a/src/main/java/it/inaf/ia2/transfer/persistence/FileDAO.java b/src/main/java/it/inaf/ia2/transfer/persistence/FileDAO.java index 762f0dde4e6ae61e91325aea3a53895c2991725a..8bb43f7ad06c8234815bb455839e8f2eb51c2011 100644 --- a/src/main/java/it/inaf/ia2/transfer/persistence/FileDAO.java +++ b/src/main/java/it/inaf/ia2/transfer/persistence/FileDAO.java @@ -84,6 +84,8 @@ public class FileDAO { if (asyncLocation) { String username = rs.getString("username"); completeOsPath = completeOsPath.resolve(username).resolve("retrieve"); + } else { + completeOsPath = completeOsPath.resolve(fi.getOwnerId()); } completeOsPath = completeOsPath.resolve(osPath); @@ -96,4 +98,28 @@ public class FileDAO { } return Arrays.asList((String[]) array.getArray()); } + + public void setBusy(int nodeId, boolean busy) { + + String sql = "UPDATE node SET busy_state = ? WHERE node_id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setBoolean(1, busy); + ps.setInt(2, nodeId); + return ps; + }); + } + + public void setOsName(int nodeId, String newName) { + + String sql = "UPDATE node SET os_name = ? WHERE node_id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, newName); + ps.setInt(2, nodeId); + return ps; + }); + } } diff --git a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java index 37fbc8ff27cab539703982e5c929d86b99e7d8c4..9428c0ea5404510323934becd4ee2e40614ce38b 100644 --- a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java +++ b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java @@ -58,6 +58,7 @@ public class GetFileControllerTest { FileInfo fileInfo = new FileInfo(); fileInfo.setOsPath(tempFile.getAbsolutePath()); + fileInfo.setVirtualPath("/path/to/myfile"); fileInfo.setIsPublic(true); when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); @@ -124,6 +125,7 @@ public class GetFileControllerTest { FileInfo fileInfo = new FileInfo(); fileInfo.setOsPath(tempFile.getAbsolutePath()); + fileInfo.setVirtualPath("/path/to/myfile"); fileInfo.setGroupRead(Collections.singletonList("group1")); when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo)); @@ -138,6 +140,7 @@ public class GetFileControllerTest { when(tokenParser.getClaims(any())).thenReturn(claims); FileInfo fileInfo = new FileInfo(); + fileInfo.setVirtualPath("/path/to/myfile"); fileInfo.setOsPath(tempFile.getAbsolutePath()); fileInfo.setOwnerId("123"); @@ -153,6 +156,7 @@ public class GetFileControllerTest { public void testPrivateFileNullToken() throws Exception { FileInfo fileInfo = new FileInfo(); + fileInfo.setVirtualPath("/path/to/myfile"); when(fileDao.getFileInfo(any())).thenReturn(Optional.of(fileInfo));