RepositoryApiServiceImpl.java

  1. /*
  2.  * Copyright 2024 Global Crop Diversity Trust
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *   http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */

  16. package org.genesys.server.api.v2.facade.impl;

  17. import org.genesys.blocks.security.model.AclAwareModel;
  18. import org.genesys.filerepository.FolderNotEmptyException;
  19. import org.genesys.filerepository.InvalidRepositoryFileDataException;
  20. import org.genesys.filerepository.InvalidRepositoryPathException;
  21. import org.genesys.filerepository.NoSuchRepositoryFileException;
  22. import org.genesys.filerepository.NoSuchRepositoryFolderException;
  23. import org.genesys.filerepository.ReferencedRepositoryFileException;
  24. import org.genesys.filerepository.model.RepositoryFile;
  25. import org.genesys.filerepository.model.RepositoryFolder;
  26. import org.genesys.filerepository.service.ImageGalleryService;
  27. import org.genesys.filerepository.service.RepositoryService;
  28. import org.genesys.filerepository.service.VirusFoundException;
  29. import org.genesys.server.api.Pagination;
  30. import org.genesys.server.api.v2.facade.RepositoryApiService;
  31. import org.genesys.server.api.v2.mapper.MapstructMapper;
  32. import org.genesys.server.api.v2.model.impl.RepositoryFileDTO;
  33. import org.genesys.server.api.v2.model.impl.RepositoryFolderDTO;
  34. import org.genesys.server.api.v2.model.impl.RepositoryImageDTO;
  35. import org.genesys.server.exception.NotFoundElement;
  36. import org.genesys.server.service.impl.FilesMetadataInfo;
  37. import org.springframework.beans.factory.annotation.Autowired;
  38. import org.springframework.data.domain.Page;
  39. import org.springframework.data.domain.Pageable;
  40. import org.springframework.data.domain.Sort;
  41. import org.springframework.stereotype.Service;
  42. import org.springframework.transaction.annotation.Transactional;
  43. import org.springframework.web.servlet.HandlerMapping;

  44. import javax.servlet.http.HttpServletRequest;
  45. import javax.servlet.http.HttpServletResponse;
  46. import java.io.File;
  47. import java.io.IOException;
  48. import java.io.InputStream;
  49. import java.io.OutputStream;
  50. import java.nio.file.Path;
  51. import java.nio.file.Paths;
  52. import java.util.List;
  53. import java.util.UUID;
  54. import java.util.stream.Stream;

  55. @Service
  56. @Transactional(readOnly = true)
  57. public class RepositoryApiServiceImpl implements RepositoryApiService {

  58.     @Autowired
  59.     private RepositoryService service;
  60.    
  61.     @Autowired
  62.     private ImageGalleryService imageGalleryService;

  63.     @Autowired
  64.     private FilesMetadataInfo filesMetadataInfo;
  65.    
  66.     @Autowired
  67.     private MapstructMapper mapper;
  68.    
  69.     @Override
  70.     @Transactional
  71.     public <T extends RepositoryFileDTO> T addFile(Path repositoryPath, String originalFilename, String contentType, byte[] bytes, T metaData) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
  72.         return (T) mapper.map(service.addFile(repositoryPath, originalFilename, contentType, bytes, mapper.map(metaData)));
  73.     }

  74.     @Override
  75.     @Transactional
  76.     public <T extends RepositoryFileDTO> T addFile(Path repositoryPath, String originalFilename, String contentType, File fileWithData, T metaData) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
  77.         return (T) mapper.map(service.addFile(repositoryPath, originalFilename, contentType, fileWithData, mapper.map(metaData)));
  78.     }

  79.     @Override
  80.     @Transactional
  81.     public <T extends RepositoryFileDTO> T addFile(Path repositoryPath, String originalFilename, String contentType, InputStream inputStream, T metaData) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
  82.         return (T) mapper.map(service.addFile(repositoryPath, originalFilename, contentType, inputStream, mapper.map(metaData)));
  83.     }

  84.     @Override
  85.     @Transactional
  86.     public void ensureThumbnails(RepositoryImageDTO repositoryImageDTO) {
  87.         service.ensureThumbnails(mapper.map(repositoryImageDTO));
  88.     }

  89.     @Override
  90.     public <T extends RepositoryFileDTO> T getFile(UUID fileUuid) throws NoSuchRepositoryFileException {
  91.         return (T) mapper.map((RepositoryFile) service.getFile(fileUuid));
  92.     }

  93.     @Override
  94.     public <T extends RepositoryFileDTO> T getFile(UUID fileUuid, int version) throws NoSuchRepositoryFileException {
  95.         return (T) mapper.map((RepositoryFile) service.getFile(fileUuid, version));
  96.     }

  97.     @Override
  98.     public <T extends RepositoryFileDTO> T getFile(Path path, String filename) throws NoSuchRepositoryFileException, InvalidRepositoryPathException {
  99.         return (T) mapper.map((RepositoryFile) service.getFile(path, filename));
  100.     }

  101.     @Override
  102.     public byte[] getFileBytes(RepositoryFileDTO repositoryFileDTO) throws IOException {
  103.         return service.getFileBytes(mapper.map(repositoryFileDTO));
  104.     }

  105.     @Override
  106.     public void streamFileBytes(RepositoryFileDTO repositoryFileDTO, OutputStream outputStream) throws IOException {
  107.         service.streamFileBytes(mapper.map(repositoryFileDTO), outputStream);
  108.     }

  109.     @Override
  110.     public OutputStream getFolderAsZip(RepositoryFolderDTO repositoryFolderDTO, OutputStream outputStream, int maxFilesLimit) throws InvalidRepositoryPathException, IOException {
  111.         return service.getFolderAsZip(mapper.map(repositoryFolderDTO), outputStream, maxFilesLimit);
  112.     }

  113.     @Override
  114.     public OutputStream getFolderAsZip(RepositoryFolderDTO repositoryFolderDTO, OutputStream outputStream) throws InvalidRepositoryPathException, IOException {
  115.         return service.getFolderAsZip(mapper.map(repositoryFolderDTO), outputStream);
  116.     }

  117.     @Override
  118.     @Transactional
  119.     public List<RepositoryFileDTO> extractZip(RepositoryFileDTO repositoryFileDTO) throws InvalidRepositoryFileDataException, IOException, InvalidRepositoryPathException, NoSuchRepositoryFileException {
  120.         return mapper.map(service.extractZip(mapper.map(repositoryFileDTO)), mapper::map);
  121.     }

  122.     @Override
  123.     public <T extends RepositoryFileDTO> void scanBytes(T repositoryFileDTO) throws VirusFoundException, IOException {
  124.         service.scanBytes(mapper.map(repositoryFileDTO));
  125.     }

  126.     @Override
  127.     public List<RepositoryFileDTO> getFiles(Path folderPath, Sort sort) throws InvalidRepositoryPathException {
  128.         return mapper.map(service.getFiles(folderPath, sort), mapper::map);
  129.     }

  130.     @Override
  131.     public Page<RepositoryFileDTO> listFiles(Path folderPath, Pageable page) throws InvalidRepositoryPathException {
  132.         return mapper.map(service.listFiles(folderPath, page), mapper::map);
  133.     }

  134.     @Override
  135.     public Stream<RepositoryFileDTO> streamFiles(Path root, Sort sort) throws InvalidRepositoryPathException {
  136.         return service.streamFiles(root, sort).map(mapper::map);
  137.     }

  138.     @Override
  139.     @Transactional
  140.     public <T extends RepositoryFileDTO> T updateMetadata(T repositoryFileDTO) throws NoSuchRepositoryFileException {
  141.         return (T) mapper.map(service.updateMetadata(mapper.map(repositoryFileDTO)));
  142.     }

  143.     @Override
  144.     @Transactional
  145.     public <T extends RepositoryFileDTO> T updateBytes(T repositoryFileDTO, String contentType, byte[] bytes) throws NoSuchRepositoryFileException, IOException {
  146.         return (T) mapper.map(service.updateBytes(mapper.map(repositoryFileDTO), contentType, bytes));
  147.     }

  148.     @Override
  149.     @Transactional
  150.     public <T extends RepositoryFileDTO> T updateBytes(T repositoryFileDTO, String contentType, InputStream inputStream) throws NoSuchRepositoryFileException, IOException {
  151.         return (T) mapper.map(service.updateBytes(mapper.map(repositoryFileDTO), contentType, inputStream));
  152.     }

  153.     @Override
  154.     @Transactional
  155.     public <T extends RepositoryFileDTO> T updateBytes(T repositoryFileDTO, String contentType, File fileWithBytes) throws NoSuchRepositoryFileException, IOException {
  156.         return (T) mapper.map(service.updateBytes(mapper.map(repositoryFileDTO), contentType, fileWithBytes));
  157.     }

  158.     @Override
  159.     @Transactional
  160.     public RepositoryImageDTO updateImageBytes(RepositoryImageDTO repositoryImageDTO, String contentType, byte[] bytes) throws NoSuchRepositoryFileException, IOException {
  161.         return mapper.map(service.updateImageBytes(mapper.map(repositoryImageDTO), contentType, bytes));
  162.     }

  163.     @Override
  164.     @Transactional
  165.     public <T extends RepositoryFileDTO> T removeFileIfPossible(T repositoryFileDTO) throws NoSuchRepositoryFileException, ReferencedRepositoryFileException, IOException {
  166.         return (T) mapper.map(service.removeFileIfPossible(mapper.map(repositoryFileDTO)));
  167.     }

  168.     @Override
  169.     @Transactional
  170.     public <T extends RepositoryFileDTO> T removeFile(T repositoryFileDTO) throws NoSuchRepositoryFileException, IOException {
  171.         return (T) mapper.map(service.removeFile(mapper.map(repositoryFileDTO)));
  172.     }

  173.     @Override
  174.     @Transactional
  175.     public <T extends RepositoryFileDTO> T moveFile(T repositoryFileDTO, Path target) throws NoSuchRepositoryFileException, InvalidRepositoryPathException {
  176.         return (T) mapper.map(service.moveFile(mapper.map(repositoryFileDTO), target));
  177.     }

  178.     @Override
  179.     @Transactional
  180.     public <T extends RepositoryFileDTO> T moveAndRenameFile(T repositoryFileDTO, Path fullPath) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException {
  181.         return (T) mapper.map(service.moveAndRenameFile(mapper.map(repositoryFileDTO), fullPath));
  182.     }

  183.     @Override
  184.     public List<RepositoryImageDTO> listImages(Path path, Sort sort) {
  185.         return mapper.map(service.listImages(path, sort), mapper::map);
  186.     }

  187.     @Override
  188.     public List<RepositoryFolderDTO> listPathsRecursively(Path root) throws InvalidRepositoryPathException {
  189.         return mapper.map(service.listPathsRecursively(root), mapper::map);
  190.     }

  191.     @Override
  192.     @Transactional
  193.     public RepositoryImageDTO addImage(Path repositoryPath, String originalFilename, String contentType, byte[] bytes, RepositoryImageDTO metaData) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
  194.         return mapper.map(service.addImage(repositoryPath, originalFilename, contentType, bytes, mapper.map(metaData)));
  195.     }

  196.     @Override
  197.     @Transactional
  198.     public RepositoryImageDTO updateImageMetadata(RepositoryImageDTO repositoryImageDTO) throws NoSuchRepositoryFileException {
  199.         return mapper.map(service.updateImageMetadata(mapper.map(repositoryImageDTO)));
  200.     }

  201.     @Override
  202.     @Transactional
  203.     public RepositoryImageDTO removeImage(RepositoryImageDTO repositoryImageDTO) throws NoSuchRepositoryFileException, IOException, ReferencedRepositoryFileException {
  204.         return mapper.map(service.removeImage(mapper.map(repositoryImageDTO)));
  205.     }

  206.     @Override
  207.     public RepositoryFolderDTO getFolder(UUID uuid) {
  208.         return mapper.map(service.getFolder(uuid));
  209.     }

  210.     @Override
  211.     public RepositoryFolderDTO getFolder(Path folderPath) throws InvalidRepositoryPathException {
  212.         return mapper.map(service.getFolder(folderPath));
  213.     }

  214.     @Override
  215.     @Transactional
  216.     public RepositoryFolderDTO updateFolder(RepositoryFolderDTO folder) throws NoSuchRepositoryFolderException, InvalidRepositoryPathException {
  217.         return mapper.map(service.updateFolder(mapper.map(folder)));
  218.     }

  219.     @Override
  220.     public boolean hasPath(Path path) throws InvalidRepositoryPathException {
  221.         return service.hasPath(path);
  222.     }

  223.     @Override
  224.     @Transactional
  225.     public RepositoryFolderDTO renamePath(Path currentPath, Path newPath) throws InvalidRepositoryPathException {
  226.         return mapper.map(service.renamePath(currentPath, newPath));
  227.     }

  228.     @Override
  229.     @Transactional
  230.     public RepositoryFolderDTO ensureFolder(Path path) throws InvalidRepositoryPathException {
  231.         return mapper.map(service.ensureFolder(path));
  232.     }

  233.     // TODO AclAwareModel aclParentObject
  234.     @Override
  235.     @Transactional
  236.     public RepositoryFolderDTO ensureFolder(Path path, AclAwareModel aclParentObject) throws InvalidRepositoryPathException {
  237.         return mapper.map(service.ensureFolder(path, aclParentObject));
  238.     }

  239.     @Override
  240.     @Transactional(rollbackFor = Throwable.class)
  241.     public RepositoryFolderDTO deleteFolder(Path path) throws FolderNotEmptyException, InvalidRepositoryPathException {
  242.         return mapper.map(service.deleteFolder(path));
  243.     }

  244.     @Override
  245.     public List<RepositoryFolderDTO> getFolders(Path root, Sort sort) throws InvalidRepositoryPathException {
  246.         return mapper.map(service.getFolders(root, sort), mapper::map);
  247.     }

  248.     @Override
  249.     public Page<RepositoryFolderDTO> listFolders(Path root, Pageable page) throws InvalidRepositoryPathException {
  250.         return mapper.map(service.listFolders(root, page), mapper::map);
  251.     }

  252.     @Override
  253.     public byte[] getThumbnail(Path path, String name, String extension, RepositoryFileDTO repositoryFileDTO) throws Exception {
  254.         return service.getThumbnail(path, name, extension, mapper.map(repositoryFileDTO));
  255.     }

  256.     @Override
  257.     @Transactional
  258.     public FolderDetails renameFolder(final UUID folderUuid, String fullPath) throws InvalidRepositoryPathException {
  259.         RepositoryFolder folder = service.getFolder(folderUuid);
  260.         if (folder == null) {
  261.             throw new NotFoundElement("No folder with uuid=" + folderUuid);
  262.         }
  263.         return folderDetails(Paths.get(renamePath(folder.getFolderPath(), Paths.get(fullPath)).getPath()));
  264.     }

  265.     /**
  266.      * Folder details.
  267.      *
  268.      * @param path the path
  269.      * @return the folder details
  270.      * @throws InvalidRepositoryPathException the invalid repository path exception
  271.      */
  272.     @Transactional
  273.     @Override
  274.     public FolderDetails folderDetails(final Path path) throws InvalidRepositoryPathException {
  275.         FolderDetails fd = new FolderDetails();
  276.         fd.folder = getFolder(path);
  277.         fd.subFolders = listFolders(path, Pagination.toPageRequest(50, RepositoryFolder.DEFAULT_SORT));
  278.         if (fd.folder == null && !path.toAbsolutePath().toString().equals("/")) {
  279.             throw new NotFoundElement("No such folder");
  280.         }
  281.         fd.files = listFiles(path, Pagination.toPageRequest(50, RepositoryFile.DEFAULT_SORT));
  282.         fd.gallery = mapper.map(imageGalleryService.loadImageGallery(path));
  283.         return fd;
  284.     }

  285.     @Override
  286.     public void downloadFolderMetadata(HttpServletRequest request, HttpServletResponse response, String controllerUrl)
  287.             throws NotFoundElement, IOException, InvalidRepositoryPathException {
  288.         final String folderPath = ((String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)).substring((controllerUrl + "/download/folder-metadata").length());
  289.         final RepositoryFolderDTO folder = getFolder(Paths.get(folderPath));
  290.         if (folder == null) {
  291.             throw new NotFoundElement("No folder with path=" + folderPath);
  292.         }
  293.         response.setContentType("text/csv;charset=UTF-8");
  294.         response.setHeader("Content-Disposition", "attachment; filename=" + folder.getName() + "_files_metadata.csv ");

  295.         Stream<RepositoryFile> files = service.streamFiles(Paths.get(folder.getPath()), RepositoryFile.DEFAULT_SORT);
  296.         filesMetadataInfo.downloadMetadata(files, response, '\t', '"', '\\', "\n", "UTF-8");
  297.     }
  298. }