Package org.zanata.file

Source Code of org.zanata.file.SourceDocumentUpload

/*
* Copyright 2013, Red Hat, Inc. and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.zanata.file;

import static org.zanata.file.DocumentUploadUtil.getInputStream;
import static org.zanata.file.DocumentUploadUtil.isSinglePart;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collections;

import javax.annotation.Nonnull;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import lombok.extern.slf4j.Slf4j;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.zanata.common.DocumentType;
import org.zanata.common.EntityStatus;
import org.zanata.common.LocaleId;
import org.zanata.dao.DocumentDAO;
import org.zanata.dao.DocumentUploadDAO;
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.exception.ChunkUploadException;
import org.zanata.exception.VirusDetectedException;
import org.zanata.exception.ZanataServiceException;
import org.zanata.model.HDocument;
import org.zanata.model.HDocumentUpload;
import org.zanata.model.HLocale;
import org.zanata.model.HProjectIteration;
import org.zanata.model.HRawDocument;
import org.zanata.rest.DocumentFileUploadForm;
import org.zanata.rest.StringSet;
import org.zanata.rest.dto.ChunkUploadResponse;
import org.zanata.rest.dto.extensions.ExtensionType;
import org.zanata.rest.dto.resource.Resource;
import org.zanata.rest.service.VirusScanner;
import org.zanata.security.ZanataIdentity;
import org.zanata.service.DocumentService;
import org.zanata.service.TranslationFileService;

import com.google.common.base.Optional;
import com.google.common.base.Strings;

//TODO damason: add thorough unit testing
@Slf4j
@Name("sourceDocumentUploader")
public class SourceDocumentUpload {

    private static final HLocale NULL_LOCALE = null;

    @In(create = true, value = "documentUploadUtil")
    private DocumentUploadUtil util;
    @In("filePersistService")
    private FilePersistService filePersistService;
    @In
    private ZanataIdentity identity;
    @In
    private ProjectIterationDAO projectIterationDAO;
    @In
    private TranslationFileService translationFileServiceImpl;
    @In
    private VirusScanner virusScanner;
    @In
    private DocumentDAO documentDAO;
    @In
    private DocumentUploadDAO documentUploadDAO;
    @In
    private DocumentService documentServiceImpl;

    public Response tryUploadSourceFileWithoutHash(GlobalDocumentId id,
            DocumentFileUploadForm uploadForm) {
        try {
            failIfSourceUploadNotValid(id, uploadForm);
        } catch (ChunkUploadException e) {
            return Response.status(e.getStatusCode())
                    .entity(new ChunkUploadResponse(e.getMessage())).build();
        }

        return tryValidatedUploadSourceFile(id, uploadForm);
    }

    public Response tryUploadSourceFile(GlobalDocumentId id,
            DocumentFileUploadForm uploadForm) {
        try {
            failIfSourceUploadNotValid(id, uploadForm);
            util.failIfHashNotPresent(uploadForm);
        } catch (ChunkUploadException e) {
            return Response.status(e.getStatusCode())
                    .entity(new ChunkUploadResponse(e.getMessage())).build();
        }

        return tryValidatedUploadSourceFile(id, uploadForm);
    }

    public Response tryValidatedUploadSourceFile(GlobalDocumentId id,
            DocumentFileUploadForm uploadForm) {
        try {
            Optional<File> tempFile;
            int totalChunks;

            if (!uploadForm.getLast()) {
                HDocumentUpload upload =
                        util.saveUploadPart(id, NULL_LOCALE, uploadForm);
                totalChunks = upload.getParts().size();
                return Response
                        .status(Status.ACCEPTED)
                        .entity(new ChunkUploadResponse(upload.getId(),
                                totalChunks, true,
                                "Chunk accepted, awaiting remaining chunks."))
                        .build();
            }

            if (isSinglePart(uploadForm)) {
                totalChunks = 1;
                tempFile = Optional.<File> absent();
            } else {
                HDocumentUpload previousParts =
                        documentUploadDAO.findById(uploadForm.getUploadId());
                totalChunks = previousParts.getParts().size();
                totalChunks++; // add final part
                tempFile =
                        Optional.of(util
                                .combineToTempFileAndDeleteUploadRecord(
                                        previousParts,
                                        uploadForm));
            }

            if (DocumentType.typeFor(uploadForm.getFileType()) == DocumentType.GETTEXT_PORTABLE_OBJECT_TEMPLATE) {
                InputStream potStream = getInputStream(tempFile, uploadForm);
                parsePotFile(potStream, id, uploadForm);
            } else {
                if (!tempFile.isPresent()) {
                    tempFile =
                            Optional.of(util
                                    .persistTempFileFromUpload(uploadForm));
                }
                processAdapterFile(tempFile.get(), id, uploadForm);
            }
            if (tempFile.isPresent()) {
                tempFile.get().delete();
            }
            return sourceUploadSuccessResponse(util.isNewDocument(id),
                    totalChunks);
        } catch (ChunkUploadException e) {
            return Response.status(e.getStatusCode())
                    .entity(new ChunkUploadResponse(e.getMessage())).build();
        } catch (FileNotFoundException e) {
            log.error("failed to create input stream from temp file", e);
            return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e)
                    .build();
        }
    }

    private void failIfSourceUploadNotValid(GlobalDocumentId id,
            DocumentFileUploadForm uploadForm) throws ChunkUploadException {
        util.failIfUploadNotValid(id, uploadForm);
        failIfSourceUploadNotAllowed(id);
        failIfFileTypeNotValid(uploadForm);
    }

    private void failIfSourceUploadNotAllowed(GlobalDocumentId id)
            throws ChunkUploadException {
        if (!isDocumentUploadAllowed(id)) {
            throw new ChunkUploadException(Status.FORBIDDEN,
                    "You do not have permission to upload source documents to project-version \""
                            + id.getProjectSlug() + ":" + id.getVersionSlug()
                            + "\".");
        }
    }

    private boolean isDocumentUploadAllowed(GlobalDocumentId id) {
        HProjectIteration projectIteration =
                projectIterationDAO.getBySlug(id.getProjectSlug(),
                        id.getVersionSlug());
        return projectIteration.getStatus() == EntityStatus.ACTIVE
                && projectIteration.getProject().getStatus() == EntityStatus.ACTIVE
                && identity != null
                && identity.hasPermission("import-template", projectIteration);
    }

    private void failIfFileTypeNotValid(DocumentFileUploadForm uploadForm)
            throws ChunkUploadException {
        DocumentType type = DocumentType.typeFor(uploadForm.getFileType());
        if (!isSourceDocumentType(type)) {
            throw new ChunkUploadException(Status.BAD_REQUEST, "The type \""
                    + uploadForm.getFileType()
                    + "\" specified in form parameter 'type' "
                    + "is not valid for a source file on this server.");
        }
    }

    private boolean isSourceDocumentType(DocumentType type) {
        return isPotType(type) || isAdapterType(type);
    }

    private boolean isPotType(DocumentType type) {
        return type == DocumentType.GETTEXT_PORTABLE_OBJECT_TEMPLATE;
    }

    private boolean isAdapterType(DocumentType type) {
        return translationFileServiceImpl.hasAdapterFor(type);
    }

    private static Response sourceUploadSuccessResponse(boolean isNewDocument,
            int acceptedChunks) {
        Response response;
        ChunkUploadResponse uploadResponse = new ChunkUploadResponse();
        uploadResponse.setAcceptedChunks(acceptedChunks);
        uploadResponse.setExpectingMore(false);
        if (isNewDocument) {
            uploadResponse
                    .setSuccessMessage("Upload of new source document successful.");
            response =
                    Response.status(Status.CREATED).entity(uploadResponse)
                            .build();
        } else {
            uploadResponse
                    .setSuccessMessage("Upload of new version of source document successful.");
            response =
                    Response.status(Status.OK).entity(uploadResponse).build();
        }
        return response;
    }

    private void processAdapterFile(@Nonnull File tempFile,
            GlobalDocumentId id, DocumentFileUploadForm uploadForm) {
        String name =
                id.getProjectSlug() + ":" + id.getVersionSlug() + ":"
                        + id.getDocId();
        try {
            virusScanner.scan(tempFile, name);
        } catch (VirusDetectedException e) {
            log.warn("File failed virus scan: {}", e.getMessage());
            throw new ChunkUploadException(Status.BAD_REQUEST,
                    "Uploaded file did not pass virus scan");
        }

        HDocument document;
        Optional<String> params;
        params =
                Optional.fromNullable(Strings.emptyToNull(uploadForm
                        .getAdapterParams()));
        if (!params.isPresent()) {
            params =
                    documentDAO.getAdapterParams(id.getProjectSlug(),
                            id.getVersionSlug(), id.getDocId());
        }
        try {
            Resource doc =
                    translationFileServiceImpl.parseUpdatedAdapterDocumentFile(
                            tempFile.toURI(), id.getDocId(),
                            uploadForm.getFileType(), params);
            doc.setLang(LocaleId.EN_US);
            // TODO Copy Trans values
            document =
                    documentServiceImpl.saveDocument(id.getProjectSlug(),
                            id.getVersionSlug(), doc,
                            Collections.<String> emptySet(), false);
        } catch (SecurityException e) {
            throw new ChunkUploadException(Status.INTERNAL_SERVER_ERROR,
                    e.getMessage(), e);
        } catch (ZanataServiceException e) {
            throw new ChunkUploadException(Status.INTERNAL_SERVER_ERROR,
                    e.getMessage(), e);
        }

        String contentHash = uploadForm.getHash();
        DocumentType documentType =
                DocumentType.typeFor(uploadForm.getFileType());

        persistRawDocument(document, tempFile, contentHash, documentType,
                params);

        translationFileServiceImpl.removeTempFile(tempFile);
    }

    private void persistRawDocument(HDocument document, File rawFile,
            String contentHash, DocumentType documentType,
            Optional<String> params) {
        HRawDocument rawDocument = new HRawDocument();
        rawDocument.setDocument(document);
        rawDocument.setContentHash(contentHash);
        rawDocument.setType(documentType);
        rawDocument.setUploadedBy(identity.getCredentials().getUsername());
        filePersistService.persistRawDocumentContentFromFile(rawDocument,
                rawFile);
        if (params.isPresent()) {
            rawDocument.setAdapterParameters(params.get());
        }
        documentDAO.addRawDocument(document, rawDocument);
        documentDAO.flush();
    }

    private void parsePotFile(InputStream potStream, GlobalDocumentId id,
            DocumentFileUploadForm uploadForm) {
        // real upload filename not available, but the service only cares about
        // the suffix.
        String uploadFileName = "." + uploadForm.getFileType();
        Resource doc = translationFileServiceImpl.parseUpdatedPotFile(potStream,
                        id.getDocId(), uploadFileName,
                        useOfflinePo(id));
        doc.setLang(LocaleId.EN_US);
        // TODO Copy Trans values
        documentServiceImpl.saveDocument(id.getProjectSlug(),
                id.getVersionSlug(), doc,
                new StringSet(ExtensionType.GetText.toString()), false);
    }

    private boolean useOfflinePo(GlobalDocumentId id) {
        return !util.isNewDocument(id)
                && !translationFileServiceImpl
                        .isPoDocument(id.getProjectSlug(), id.getVersionSlug(),
                                id.getDocId());
    }

}
TOP

Related Classes of org.zanata.file.SourceDocumentUpload

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.