Skip to content
FileServiceClient.java 7.38 KiB
Newer Older
/*
 * 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 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.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;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class FileServiceClient {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Value("${vospace-authority}")
    private String authority;

    @Value("${file-service-url}")
    private String fileServiceUrl;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private LinkService linkService;
    @Autowired
    private NodeDAO nodeDAO;

    public String startArchiveJob(Transfer transfer, String jobId) {

        String target = NodeUtils.getVosPath(transfer.getTarget());

        String viewUri = transfer.getView().getUri();

        // Generate list of paths using view include parameters
        List<String> vosPaths = transfer.getView().getParam().stream()
                .map(p -> {
                    if (p.getUri().equals(viewUri + "/include")) {
                        if (p.getValue().contains("../")) {
                            throw new InvalidArgumentException("Relative paths are not supported");
                        }
                        return target + "/" + p.getValue();
                    } else {
                        throw new InvalidArgumentException("Unsupported view parameter: " + p.getUri());
                    }
                })
                .collect(Collectors.toList());

        if (vosPaths.isEmpty()) {
            // Add target path
            vosPaths.add(target);

        // 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()));
                }
nfcalabria's avatar
nfcalabria committed
            } else {
                expandedVosPaths.add(vosPath);
        List<ArchiveEntryDescriptor> entryDescriptors = linkService.followLinksForArchiveService(expandedVosPaths);

        ArchiveRequest archiveRequest = new ArchiveRequest();
        archiveRequest.setJobId(jobId);
        archiveRequest.setEntryDescriptors(entryDescriptors);
        archiveRequest.setType(archiveTypeFromViewUri(transfer.getView().getUri()));

        String url = fileServiceUrl + "/archive";

        String token = ((User) request.getUserPrincipal()).getAccessToken();

        return restTemplate.execute(url, HttpMethod.POST, req -> {
            HttpHeaders headers = req.getHeaders();
            if (token != null) {
                headers.setBearerAuth(token);
            }
            headers.setContentType(MediaType.APPLICATION_JSON);
            try (OutputStream os = req.getBody()) {
                MAPPER.writeValue(os, archiveRequest);
            }
        }, res -> {
            return res.getHeaders().getLocation().toString();
        }, new Object[]{});
    }

    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();
            if (token != null) {
                headers.setBearerAuth(token);
            }

            headers.setContentType(MediaType.APPLICATION_JSON);
            try (OutputStream os = req.getBody()) {
                MAPPER.writeValue(os, copyRequest);
            }
        }, new Object[]{});
    public static class CopyRequest {

        private String jobId;
        private String sourceRootVosPath;
        private String destinationRootVosPath;

        public String getJobId() {
            return jobId;
        }

        public void setJobId(String jobId) {
            this.jobId = jobId;
        }

        public String getSourceRootVosPath() {
            return sourceRootVosPath;
        }

        public void setSourceRootVosPath(String sourceRootVosPath) {
            this.sourceRootVosPath = sourceRootVosPath;
        }

        public String getDestinationRootVosPath() {
            return destinationRootVosPath;
        }

        public void setDestinationRootVosPath(String destinationRootVosPath) {
            this.destinationRootVosPath = destinationRootVosPath;
        }

    }
    public static class ArchiveRequest {

        private String type;
        private String jobId;
        private List<ArchiveEntryDescriptor> entryDescriptors;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getJobId() {
            return jobId;
        }

        public void setJobId(String jobId) {
            this.jobId = jobId;
        }

        public List<ArchiveEntryDescriptor> getEntryDescriptors() {
            return entryDescriptors;
        public void setEntryDescriptors(List<ArchiveEntryDescriptor> entryDescriptors) {
            this.entryDescriptors = entryDescriptors;
        }
    }

    private static String archiveTypeFromViewUri(String viewUri) {
        switch (viewUri) {
                return "ZIP";
            default:
                throw new IllegalArgumentException("Archive type not defined for " + viewUri);
        }
    }
}