Commit 86f91ae9 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Handled jobId parameter also on GetFileController and improved error handling

parent 5bd13b15
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
    <parent>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <version>2.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    </parent>
    <groupId>it.inaf.ia2</groupId>
    <groupId>it.inaf.ia2</groupId>
+4 −4
Original line number Original line Diff line number Diff line
@@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RestController
public class ArchiveFileController {
public class ArchiveFileController extends FileController {


    @Autowired
    @Autowired
    private ArchiveService archiveService;
    private ArchiveService archiveService;
@@ -48,7 +48,7 @@ public class ArchiveFileController {
        job.setVosPaths(archiveRequest.getPaths());
        job.setVosPaths(archiveRequest.getPaths());


        CompletableFuture.runAsync(() -> {
        CompletableFuture.runAsync(() -> {
            archiveService.createArchive(job);
            handleFileJob(() -> archiveService.createArchive(job), job.getJobId());
        });
        });


        HttpHeaders headers = new HttpHeaders();
        HttpHeaders headers = new HttpHeaders();
@@ -57,12 +57,12 @@ public class ArchiveFileController {
    }
    }


    @GetMapping(value = "/archive/{fileName}")
    @GetMapping(value = "/archive/{fileName}")
    public ResponseEntity<?> getArchiveFile(@PathVariable("fileName") String fileName) {
    public void getArchiveFile(@PathVariable("fileName") String fileName) {


        TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal();
        TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal();


        File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile();
        File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile();


        return FileResponseUtil.getFileResponse(response, file);
        FileResponseUtil.getFileResponse(response, file);
    }
    }
}
}
+32 −0
Original line number Original line Diff line number Diff line
@@ -5,18 +5,28 @@
 */
 */
package it.inaf.ia2.transfer.controller;
package it.inaf.ia2.transfer.controller;


import it.inaf.ia2.transfer.exception.JobException;
import it.inaf.ia2.transfer.persistence.JobDAO;
import java.net.URLDecoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;


public abstract class FileController {
public abstract class FileController {


    private static final Logger LOG = LoggerFactory.getLogger(FileController.class);

    @Autowired
    @Autowired
    protected HttpServletRequest request;
    protected HttpServletRequest request;


    @Autowired
    private JobDAO jobDAO;

    public String getPath() {
    public String getPath() {


        String uri = request.getRequestURI().substring(request.getContextPath().length());
        String uri = request.getRequestURI().substring(request.getContextPath().length());
@@ -26,4 +36,26 @@ public abstract class FileController {
                .map(p -> URLDecoder.decode(p, StandardCharsets.UTF_8))
                .map(p -> URLDecoder.decode(p, StandardCharsets.UTF_8))
                .collect(Collectors.toList()));
                .collect(Collectors.toList()));
    }
    }

    public void handleFileJob(Runnable action, String jobId) {
        try {
            action.run();
            if (jobId != null) {
                jobDAO.updateJobPhase(ExecutionPhase.COMPLETED, jobId);
            }
        } catch (Throwable t) {
            JobException jobException;
            if (t instanceof JobException) {
                jobException = (JobException) t;
            } else {
                LOG.error("Unexpected error happened", t);
                jobException = new JobException(JobException.Type.FATAL, "Internal Fault")
                        .setErrorDetail("InternalFault: Unexpected error happened");
            }
            if (jobId != null) {
                jobDAO.setJobError(jobId, jobException);
            }
            throw t;
        }
    }
}
}
+11 −10
Original line number Original line Diff line number Diff line
@@ -5,6 +5,8 @@
 */
 */
package it.inaf.ia2.transfer.controller;
package it.inaf.ia2.transfer.controller;


import it.inaf.ia2.transfer.exception.FileNotFoundException;
import it.inaf.ia2.transfer.exception.JobException;
import java.io.File;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.IOException;
@@ -16,32 +18,32 @@ import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactory;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import org.springframework.http.ResponseEntity;


public class FileResponseUtil {
public class FileResponseUtil {


    private static final Logger LOG = LoggerFactory.getLogger(FileResponseUtil.class);
    private static final Logger LOG = LoggerFactory.getLogger(FileResponseUtil.class);


    public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file) {
    public static void getFileResponse(HttpServletResponse response, File file) {
        return getFileResponse(response, file, null);
        getFileResponse(response, file, null);
    }
    }


    public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file, String fileName) {
    public static void getFileResponse(HttpServletResponse response, File file, String vosPath) {

        String fileName = vosPath == null ? file.getName() : vosPath.substring(vosPath.lastIndexOf("/") + 1);


        if (!file.exists()) {
        if (!file.exists()) {
            LOG.error("File not found: " + file.getAbsolutePath());
            LOG.error("File not found: " + file.getAbsolutePath());
            return new ResponseEntity<>("File " + file.getName() + " not found", NOT_FOUND);
            throw new FileNotFoundException(vosPath == null ? file.getAbsolutePath() : vosPath);
        }
        }


        if (!file.canRead()) {
        if (!file.canRead()) {
            LOG.error("File not readable: " + file.getAbsolutePath());
            LOG.error("File not readable: " + file.getAbsolutePath());
            return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR);
            throw new JobException(JobException.Type.FATAL, "Internal Fault")
                    .setErrorDetail("InternalFault: File " + file.getName() + " is not readable");
        }
        }


        response.setHeader("Content-Disposition", "attachment; filename="
        response.setHeader("Content-Disposition", "attachment; filename="
                + URLEncoder.encode(fileName == null ? file.getName() : fileName, StandardCharsets.UTF_8));
                + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");


@@ -54,6 +56,5 @@ public class FileResponseUtil {
        } catch (IOException ex) {
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
            throw new UncheckedIOException(ex);
        }
        }
        return null;
    }
    }
}
}
+30 −19
Original line number Original line Diff line number Diff line
@@ -7,7 +7,11 @@ package it.inaf.ia2.transfer.controller;


import it.inaf.ia2.transfer.persistence.model.FileInfo;
import it.inaf.ia2.transfer.persistence.model.FileInfo;
import it.inaf.ia2.transfer.auth.TokenPrincipal;
import it.inaf.ia2.transfer.auth.TokenPrincipal;
import it.inaf.ia2.transfer.exception.FileNotFoundException;
import it.inaf.ia2.transfer.exception.InvalidArgumentException;
import it.inaf.ia2.transfer.exception.PermissionDeniedException;
import it.inaf.ia2.transfer.persistence.FileDAO;
import it.inaf.ia2.transfer.persistence.FileDAO;
import it.inaf.ia2.transfer.persistence.JobDAO;
import it.inaf.ia2.transfer.service.AuthorizationService;
import it.inaf.ia2.transfer.service.AuthorizationService;
import java.io.File;
import java.io.File;
import java.util.Optional;
import java.util.Optional;
@@ -15,10 +19,8 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RestController
@@ -29,6 +31,9 @@ public class GetFileController extends FileController {
    @Autowired
    @Autowired
    private FileDAO fileDAO;
    private FileDAO fileDAO;


    @Autowired
    private JobDAO jobDAO;

    @Autowired
    @Autowired
    private AuthorizationService authorizationService;
    private AuthorizationService authorizationService;


@@ -36,12 +41,23 @@ public class GetFileController extends FileController {
    private HttpServletResponse response;
    private HttpServletResponse response;


    @GetMapping("/**")
    @GetMapping("/**")
    public ResponseEntity<?> getFile() {
    public void getFile(@RequestParam(value = "jobId", required = false) String jobId) {


        String path = getPath();
        String path = getPath();


        LOG.debug("getFile called for path {}", path);
        LOG.debug("getFile called for path {}", path);


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

            if (!jobDAO.isJobExisting(jobId)) {
                throw new InvalidArgumentException("Job " + jobId + " not found");
            }
        }

        handleFileJob(() -> {
            Optional<FileInfo> optFileInfo = fileDAO.getFileInfo(path);
            Optional<FileInfo> optFileInfo = fileDAO.getFileInfo(path);


            if (optFileInfo.isPresent()) {
            if (optFileInfo.isPresent()) {
@@ -49,19 +65,14 @@ public class GetFileController extends FileController {
                FileInfo fileInfo = optFileInfo.get();
                FileInfo fileInfo = optFileInfo.get();


                if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) {
                if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) {
                return new ResponseEntity<>("Unauthorized", UNAUTHORIZED);
                    throw new PermissionDeniedException(path);
                }
                }


            return getFileResponse(fileInfo);
                File file = new File(fileInfo.getOsPath());
                FileResponseUtil.getFileResponse(response, file, path);
            } else {
            } else {
            return new ResponseEntity<>("File " + path + " not found", NOT_FOUND);
                throw new FileNotFoundException(path);
            }
            }
    }
        }, jobId);

    private ResponseEntity<?> getFileResponse(FileInfo fileInfo) {

        File file = new File(fileInfo.getOsPath());

        return FileResponseUtil.getFileResponse(response, file, fileInfo.getVirtualName());
    }
    }
}
}
Loading