Skip to content
PutFileController.java 4 KiB
Newer Older
Sonia Zorba's avatar
Sonia Zorba committed
/*
 * This file is part of vospace-file-service
 * Copyright (C) 2021 Istituto Nazionale di Astrofisica
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package it.inaf.ia2.transfer.controller;

import it.inaf.ia2.transfer.persistence.model.FileInfo;
import it.inaf.ia2.transfer.persistence.FileDAO;
import it.inaf.ia2.transfer.service.PutFileService;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.NodeNotFoundException;
import it.inaf.oats.vospace.exception.QuotaExceededException;
import java.io.IOException;
import java.io.InputStream;
Nicola Fulvio Calabria's avatar
Nicola Fulvio Calabria committed
import java.io.UncheckedIOException;
import java.security.NoSuchAlgorithmException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.http.HttpHeaders;
public class PutFileController extends FileController {
    private static final Logger LOG = LoggerFactory.getLogger(PutFileController.class);
    @Autowired
    private FileDAO fileDAO;

    private PutFileService putFileService;
    public void putFile(@RequestHeader(value = HttpHeaders.CONTENT_ENCODING, required = false) String contentEncoding,
            @RequestParam(value = "file", required = false) MultipartFile file,
            @RequestParam(value = "jobId", required = false) String jobId,
            HttpServletRequest request) throws IOException, NoSuchAlgorithmException {
        String path = getPath();

        if (jobId == null) {
            LOG.debug("putFile called for path {}", path);
        } else {
            LOG.debug("putFile called for path {} with jobId {}", path, jobId);

            if (!jobDAO.isJobExisting(jobId)) {
                throw new InvalidArgumentException("Job " + jobId + " not found");
            int nodes = fileDAO.setBusy(path, jobId);

            if (nodes == 1) {
                try {
                    FileInfo fileInfo
                            = fileDAO.getFileInfo(path).orElseThrow(
                                    // This can happen only if some code ignores busy state
                                    // and deletes the node
                                    () -> {
                                        throw new NodeNotFoundException(path);
                                    });

                    String parentPath = FileInfo.getVosParentPath(fileInfo);
                    Long remainingQuota = fileDAO.getRemainingQuota(parentPath);

                    // if MultipartFile provides file size it is possible to check
                    // quota limit before reading the stream
                    if (remainingQuota != null && file != null && file.getSize() > remainingQuota) {
                        throw new QuotaExceededException("Path: " + fileInfo.getVirtualPath());
                    }
                    if (file != null) {
                        fileInfo.setContentType(file.getContentType());
                    }
                    fileInfo.setContentEncoding(contentEncoding);

                    try (InputStream in = file != null ? file.getInputStream() : request.getInputStream()) {
                        putFileService.storeFileFromInputStream(fileInfo, in, remainingQuota);
Nicola Fulvio Calabria's avatar
Nicola Fulvio Calabria committed
                    } catch (IOException ex) {                        
                        throw new UncheckedIOException(ex);
                    }

                } finally {
                    fileDAO.setBusy(path, null);
                throw new NodeNotFoundException(path);