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;
Sonia Zorba
committed
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.io.OutputStream;
Nicola Fulvio Calabria
committed
import java.util.ArrayList;
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;
Nicola Fulvio Calabria
committed
@Autowired
private LinkService linkService;
@Autowired
private NodeDAO nodeDAO;
public String startArchiveJob(Transfer transfer, String jobId) {
Sonia Zorba
committed
String target = transfer.getTarget().substring("vos://".length() + authority.length());
Sonia Zorba
committed
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
Sonia Zorba
committed
}
// 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()));
}
Nicola Fulvio Calabria
committed
// follow links to links in vosPaths
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);
}
}, res -> {
return null;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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) {
Sonia Zorba
committed
case Views.TAR_VIEW_URI:
return "TAR";
Sonia Zorba
committed
case Views.ZIP_VIEW_URI:
return "ZIP";
default:
throw new IllegalArgumentException("Archive type not defined for " + viewUri);
}
}
}