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 it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.NodeBusyException;
import it.inaf.oats.vospace.persistence.NodeDAO.ShortNodeDescriptor;
import java.util.Optional;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.CannotSerializeTransactionException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@Service
@EnableTransactionManagement
public class CopyService extends AbstractNodeService {
@Autowired
private NodeBranchService nodeBranchService;
@Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ)
public List<String> processCopyNodes(Transfer transfer, String jobId, User user) {
if (transfer.getTarget().size() != 1) {
throw new InvalidArgumentException("Invalid target size for copyNode: " + transfer.getTarget().size());
}
// Get Source Vos Path
String sourcePath = URIUtils.returnVosPathFromNodeURI(transfer.getTarget().get(0), authority);
// Get Destination Vos Path (it's in transfer direction)
String destinationPath = URIUtils.returnVosPathFromNodeURI(transfer.getDirection(), authority);
this.validatePath(sourcePath);
this.validatePath(destinationPath);
if (sourcePath.equals(destinationPath)) {
return List.of();
List<String> copiedNodesPaths = null;
try {
// check source branch for read and lock it
nodeBranchService.checkBranchForReadAndLock(sourcePath, jobId, user);
// Check destination
Optional<ShortNodeDescriptor> destShortNodeDescriptor
= nodeDao.getShortNodeDescriptor(destinationPath, user.getName(), user.getGroups());
if (destShortNodeDescriptor.isPresent()) {
this.validateDestinationContainer(destShortNodeDescriptor.get(), destinationPath);
copiedNodesPaths = nodeDao.copyBranch(
sourcePath,
destinationPath + "/" + NodeUtils.getNodeName(sourcePath),
jobId);
} else {
// Check if parent exists
String destinationParentPath = NodeUtils.getParentPath(destinationPath);
Optional<ShortNodeDescriptor> destShortNodeDescriptorParent
= nodeDao.getShortNodeDescriptor(destinationParentPath, user.getName(), user.getGroups());
if (destShortNodeDescriptorParent.isPresent()) {
this.validateDestinationContainer(destShortNodeDescriptorParent.get(), destinationParentPath);
copiedNodesPaths = nodeDao.copyBranch(sourcePath,
destinationPath, jobId);
} else {
throw new UnsupportedOperationException("Creation of destination upon copy not supported");
}
}
} catch (CannotSerializeTransactionException ex) {
// Concurrent transactions attempted to modify this set of nodes
throw new NodeBusyException(sourcePath);
}
return copiedNodesPaths;