com.epam.ta.reportportal.ws.controller.impl.LogController.java Source code

Java tutorial

Introduction

Here is the source code for com.epam.ta.reportportal.ws.controller.impl.LogController.java

Source

/*
 * Copyright 2016 EPAM Systems
 * 
 * 
 * This file is part of EPAM Report Portal.
 * https://github.com/reportportal/service-api
 * 
 * Report Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Report Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Report Portal.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.epam.ta.reportportal.ws.controller.impl;

import com.epam.reportportal.commons.ContentTypeResolver;
import com.epam.ta.reportportal.commons.EntityUtils;
import com.epam.ta.reportportal.commons.Predicates;
import com.epam.ta.reportportal.commons.validation.BusinessRule;
import com.epam.ta.reportportal.commons.validation.Suppliers;
import com.epam.ta.reportportal.core.log.ICreateLogHandler;
import com.epam.ta.reportportal.core.log.IDeleteLogHandler;
import com.epam.ta.reportportal.core.log.IGetLogHandler;
import com.epam.ta.reportportal.database.BinaryData;
import com.epam.ta.reportportal.database.entity.Log;
import com.epam.ta.reportportal.database.search.Condition;
import com.epam.ta.reportportal.database.search.Filter;
import com.epam.ta.reportportal.exception.ReportPortalException;
import com.epam.ta.reportportal.ws.controller.ILogController;
import com.epam.ta.reportportal.ws.model.*;
import com.epam.ta.reportportal.ws.model.log.LogResource;
import com.epam.ta.reportportal.ws.model.log.SaveLogRQ;
import com.epam.ta.reportportal.ws.resolver.FilterCriteriaResolver;
import com.epam.ta.reportportal.ws.resolver.FilterFor;
import com.epam.ta.reportportal.ws.resolver.SortFor;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.SortDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.Path.Node;
import javax.validation.Validator;
import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.security.Principal;
import java.util.*;

import static com.epam.ta.reportportal.auth.permissions.Permissions.ASSIGNED_TO_PROJECT;
import static org.springframework.http.HttpStatus.CREATED;

/**
 * Log Controller implementation
 *
 * @author Andrei Varabyeu
 */
@Controller
@RequestMapping("/{projectName}/log")
@PreAuthorize(ASSIGNED_TO_PROJECT)
public class LogController implements ILogController {

    private final ICreateLogHandler createLogMessageHandler;
    private final IDeleteLogHandler deleteLogMessageHandler;
    private final IGetLogHandler getLogHandler;
    private final ContentTypeResolver contentTypeResolver;
    private final Validator validator;

    @Autowired
    public LogController(ICreateLogHandler createLogMessageHandler, IDeleteLogHandler deleteLogMessageHandler,
            IGetLogHandler getLogHandler, ContentTypeResolver contentTypeResolver, Validator validator) {
        this.createLogMessageHandler = createLogMessageHandler;
        this.deleteLogMessageHandler = deleteLogMessageHandler;
        this.getLogHandler = getLogHandler;
        this.contentTypeResolver = contentTypeResolver;
        this.validator = validator;
    }

    @Override
    @RequestMapping(method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseBody
    @ResponseStatus(CREATED)
    @ApiOperation("Create log")
    public EntryCreatedRS createLog(@PathVariable String projectName, @RequestBody SaveLogRQ createLogRQ,
            Principal principal) {
        validateSaveRQ(createLogRQ);
        return createLogMessageHandler.createLog(createLogRQ, null, null,
                EntityUtils.normalizeProjectName(projectName));
    }

    @Override
    @RequestMapping(method = RequestMethod.POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
    @ResponseBody
    // @ApiOperation("Create log (batching operation)")
    // Specific handler should be added for springfox in case of similar POST
    // request mappings
    @ApiIgnore
    public ResponseEntity<BatchSaveOperatingRS> createLog(@PathVariable String projectName,
            @RequestPart(value = Constants.LOG_REQUEST_JSON_PART) SaveLogRQ[] createLogRQs,
            HttpServletRequest request, Principal principal) {

        String prjName = EntityUtils.normalizeProjectName(projectName);
        /*
         * Since this is multipart request we can retrieve list of uploaded
        * files
        */
        Map<String, MultipartFile> uploadedFiles = getUploadedFiles(request);
        BatchSaveOperatingRS response = new BatchSaveOperatingRS();
        EntryCreatedRS responseItem;
        /* Go through all provided save log request items */
        for (SaveLogRQ createLogRq : createLogRQs) {
            try {
                validateSaveRQ(createLogRq);
                String filename = createLogRq.getFile() == null ? null : createLogRq.getFile().getName();
                if (StringUtils.isEmpty(filename)) {
                    /*
                     * There is no filename in request. Use simple save
                     * method
                     */
                    responseItem = createLog(prjName, createLogRq, principal);

                } else {
                    /* Find by request part */
                    MultipartFile data = findByFileName(filename, uploadedFiles);
                    BusinessRule.expect(data, Predicates.notNull()).verify(ErrorType.BINARY_DATA_CANNOT_BE_SAVED,
                            Suppliers.formattedSupplier("There is no request part or file with name {}", filename));
                    /*
                     * If provided content type is null or this is octet
                     * stream, try to detect real content type of binary
                     * data
                     */
                    if (!StringUtils.isEmpty(data.getContentType())
                            && !MediaType.APPLICATION_OCTET_STREAM_VALUE.equals(data.getContentType())) {
                        responseItem = createLogMessageHandler.createLog(createLogRq,
                                new BinaryData(data.getContentType(), data.getSize(), data.getInputStream()),
                                data.getOriginalFilename(), prjName);
                    } else {
                        byte[] consumedData = IOUtils.toByteArray(data.getInputStream());
                        responseItem = createLogMessageHandler.createLog(createLogRq,
                                new BinaryData(contentTypeResolver.detectContentType(consumedData), data.getSize(),
                                        new ByteArrayInputStream(consumedData)),
                                data.getOriginalFilename(), prjName);

                    }
                }
                response.addResponse(new BatchElementCreatedRS(responseItem.getId()));
            } catch (Exception e) {
                response.addResponse(
                        new BatchElementCreatedRS(ExceptionUtils.getStackTrace(e), ExceptionUtils.getMessage(e)));
            }
        }
        return new ResponseEntity<>(response, HttpStatus.CREATED);
    }

    @Override
    @RequestMapping(value = "/{logId}", method = RequestMethod.DELETE)
    @ResponseBody
    @ApiOperation("Delete log")
    public OperationCompletionRS deleteLog(@PathVariable String projectName, @PathVariable String logId,
            Principal principal) {
        return deleteLogMessageHandler.deleteLog(logId, EntityUtils.normalizeProjectName(projectName),
                principal.getName());
    }

    @Override
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("Get logs by filter")
    public Iterable<LogResource> getLogs(@PathVariable String projectName,
            @RequestParam(value = FilterCriteriaResolver.DEFAULT_FILTER_PREFIX + Condition.EQ
                    + Log.TEST_ITEM_ID) String testStepId,
            @FilterFor(Log.class) Filter filter, @SortDefault({ "time" }) @SortFor(Log.class) Pageable pageable,
            Principal principal) {
        return getLogHandler.getLogs(testStepId, EntityUtils.normalizeProjectName(projectName), filter, pageable);
    }

    @Override
    @RequestMapping(value = "/{logId}/page", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("Get logs by filter")
    public Map<String, Serializable> getPageNumber(@PathVariable String projectName, @PathVariable String logId,
            @FilterFor(Log.class) Filter filter, @SortFor(Log.class) Pageable pageable, Principal principal) {
        return ImmutableMap.<String, Serializable>builder().put("number",
                getLogHandler.getPageNumber(logId, EntityUtils.normalizeProjectName(projectName), filter, pageable))
                .build();
    }

    @Override
    @RequestMapping(value = "/{logId}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation("Get log")
    public LogResource getLog(@PathVariable String projectName, @PathVariable String logId, Principal principal) {
        return getLogHandler.getLog(logId, EntityUtils.normalizeProjectName(projectName));
    }

    /**
     * Tries to find request part or file with specified name in multipart files
     * map.
     *
     * @param filename
     * @param files
     * @return
     */
    private MultipartFile findByFileName(String filename, Map<String, MultipartFile> files) {
        /* Request part name? */
        if (files.containsKey(filename)) {
            return files.get(filename);
        }
        /* Filename? */
        for (MultipartFile file : files.values()) {
            if (filename.equals(file.getOriginalFilename())) {
                return file;
            }
        }
        return null;
    }

    private void validateSaveRQ(SaveLogRQ saveLogRQ) {
        Set<ConstraintViolation<SaveLogRQ>> constraintViolations = validator.validate(saveLogRQ);
        if (constraintViolations != null && !constraintViolations.isEmpty()) {
            StringBuilder messageBuilder = new StringBuilder();
            for (ConstraintViolation<SaveLogRQ> constraintViolation : constraintViolations) {
                messageBuilder.append("[");
                messageBuilder.append("Incorrect value in save log request '");
                messageBuilder.append(constraintViolation.getInvalidValue());
                messageBuilder.append("' in field '");
                Iterator<Node> iterator = constraintViolation.getPropertyPath().iterator();
                messageBuilder.append(iterator.hasNext() ? iterator.next().getName() : "");
                messageBuilder.append("'.]");
            }
            throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, messageBuilder.toString());
        }
    }

    private Map<String, MultipartFile> getUploadedFiles(HttpServletRequest request) {
        Map<String, MultipartFile> uploadedFiles = new HashMap<>();
        if (request instanceof MultipartHttpServletRequest) {
            MultiValueMap<String, MultipartFile> multiFileMap = (((MultipartHttpServletRequest) request))
                    .getMultiFileMap();
            for (List<MultipartFile> multipartFiles : multiFileMap.values()) {
                for (MultipartFile file : multipartFiles) {
                    uploadedFiles.put(file.getOriginalFilename(), file);
                }
            }
        }
        return uploadedFiles;
    }
}