Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
rhbz980658 move code that accesses blobs into blob services
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmason committed Jul 22, 2013
1 parent 82271ba commit 184dfa4
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 46 deletions.
Expand Up @@ -23,14 +23,11 @@
import static org.zanata.rest.dto.stats.TranslationStatistics.StatUnit.WORD;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -45,7 +42,6 @@
import lombok.Getter;
import lombok.Setter;

import org.hibernate.LobHelper;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
Expand All @@ -69,6 +65,8 @@
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.exception.VirusDetectedException;
import org.zanata.exception.ZanataServiceException;
import org.zanata.file.FilePersistService;
import org.zanata.file.GlobalDocumentId;
import org.zanata.model.HAccount;
import org.zanata.model.HAccountRole;
import org.zanata.model.HDocument;
Expand All @@ -83,7 +81,6 @@
import org.zanata.rest.dto.stats.ContainerTranslationStatistics;
import org.zanata.rest.dto.stats.TranslationStatistics;
import org.zanata.rest.dto.stats.TranslationStatistics.StatUnit;
import org.zanata.rest.service.FileService;
import org.zanata.rest.service.StatisticsResource;
import org.zanata.rest.service.VirusScanner;
import org.zanata.security.SecurityFunctions;
Expand Down Expand Up @@ -127,6 +124,9 @@ public class ProjectIterationFilesAction implements Serializable
@In
private LocaleDAO localeDAO;

@In("blobPersistService")
private FilePersistService filePersistService;

@In
private ProjectIterationDAO projectIterationDAO;

Expand Down Expand Up @@ -407,31 +407,19 @@ else if (docId.contains("/"))
rawDocument.setAdapterParameters(params.get());
}

FileInputStream tempFileStream = null;
try
{
tempFileStream = new FileInputStream(tempFile);
try
{
String name = projectSlug+":"+iterationSlug+":"+docId;
virusScanner.scan(tempFile, name);
Blob fileContents = documentDAO.getLobHelper().createBlob(tempFileStream, (int) tempFile.length());
rawDocument.setContent(fileContents);
documentDAO.addRawDocument(document, rawDocument);
documentDAO.flush();
}
catch (VirusDetectedException e)
{
log.warn("File failed virus scan: {}", e.getMessage());
FacesMessages.instance().add(Severity.ERROR, "uploaded file did not pass virus scan");
}

String name = projectSlug+":"+iterationSlug+":"+docId;
virusScanner.scan(tempFile, name);
}
catch (FileNotFoundException e)
catch (VirusDetectedException e)
{
log.error("Failed to open stream from temp source file", e);
FacesMessages.instance().add(Severity.ERROR, "Error saving uploaded document {0} on server, download in original format may fail.", documentFileUpload.getFileName());
log.warn("File failed virus scan: {}", e.getMessage());
FacesMessages.instance().add(Severity.ERROR, "uploaded file did not pass virus scan");
}
filePersistService.persistRawDocumentContentFromFile(rawDocument, tempFile);
documentDAO.addRawDocument(document, rawDocument);
documentDAO.flush();
}

translationFileServiceImpl.removeTempFile(tempFile);
Expand Down Expand Up @@ -521,10 +509,10 @@ public boolean isPoDocument(String docId)
return translationFileServiceImpl.isPoDocument(projectSlug, iterationSlug, docId);
}

// line not found
public boolean hasOriginal(String docPath, String docName)
{
return translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, docPath, docName);
GlobalDocumentId id = new GlobalDocumentId(projectSlug, iterationSlug, docPath + docName);
return filePersistService.hasPersistedDocument(id);
}

public String extensionOf(String docPath, String docName)
Expand Down
22 changes: 22 additions & 0 deletions zanata-war/src/main/java/org/zanata/file/BlobPersistService.java
Expand Up @@ -25,6 +25,7 @@
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.SQLException;

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

Expand All @@ -39,6 +40,7 @@
import org.jboss.seam.annotations.Scope;
import org.zanata.dao.DocumentDAO;
import org.zanata.exception.ChunkUploadException;
import org.zanata.model.HDocument;
import org.zanata.model.HDocumentUploadPart;
import org.zanata.model.HRawDocument;

Expand Down Expand Up @@ -82,4 +84,24 @@ public void persistRawDocumentContentFromFile(HRawDocument rawDocument, File raw
rawDocument.setContent(fileContents);
}

@Override
public InputStream getRawDocumentContentAsStream(HRawDocument document)
{
try
{
return document.getContent().getBinaryStream();
}
catch (SQLException e)
{
throw new RawDocumentContentAccessException(e);
}
}

@Override
public boolean hasPersistedDocument(GlobalDocumentId id)
{
HDocument doc = documentDAO.getByProjectIterationAndDocId(id.getProjectSlug(),
id.getVersionSlug(), id.getDocId());
return doc.getRawDocument() != null;
}
}
10 changes: 10 additions & 0 deletions zanata-war/src/main/java/org/zanata/file/FilePersistService.java
Expand Up @@ -21,6 +21,7 @@
package org.zanata.file;

import java.io.File;
import java.io.InputStream;

import org.zanata.model.HRawDocument;

Expand All @@ -29,4 +30,13 @@ public interface FilePersistService

public void persistRawDocumentContentFromFile(HRawDocument rawDocument, File rawFile);

// TODO damason: parsing code only needs a file URI for this. Change to return
// uri when files are persisted to server.
// Other implementations may need a way to specify that they are finished with the
// document resource and cleanup is possible, in case temp files were generated.
public InputStream getRawDocumentContentAsStream(HRawDocument document)
throws RawDocumentContentAccessException;

boolean hasPersistedDocument(GlobalDocumentId id);

}
@@ -0,0 +1,40 @@
/*
* 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;

@SuppressWarnings("serial")
public class RawDocumentContentAccessException extends RuntimeException
{
public RawDocumentContentAccessException(String message)
{
super(message);
}

public RawDocumentContentAccessException(Throwable cause)
{
super(cause);
}

public RawDocumentContentAccessException(String message, Throwable cause)
{
super(message, cause);
}
}
32 changes: 22 additions & 10 deletions zanata-war/src/main/java/org/zanata/rest/service/FileService.java
Expand Up @@ -26,7 +26,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -56,7 +55,9 @@
import org.zanata.common.ContentState;
import org.zanata.common.LocaleId;
import org.zanata.dao.DocumentDAO;
import org.zanata.file.FilePersistService;
import org.zanata.file.GlobalDocumentId;
import org.zanata.file.RawDocumentContentAccessException;
import org.zanata.file.SourceDocumentUpload;
import org.zanata.file.TranslationDocumentUpload;
import org.zanata.model.HDocument;
Expand Down Expand Up @@ -106,6 +107,9 @@ public class FileService implements FileResource
@In(value = "translationDocumentUploader", create = true)
private TranslationDocumentUpload translationUploader;

@In("blobPersistService")
private FilePersistService filePersistService;

@Override
@GET
@Path(ACCEPTED_TYPES_RESOURCE)
Expand Down Expand Up @@ -185,9 +189,9 @@ public Response downloadSourceFile( @PathParam("projectSlug") String projectSlug
InputStream fileContents;
try
{
fileContents = document.getRawDocument().getContent().getBinaryStream();
fileContents = filePersistService.getRawDocumentContentAsStream(document.getRawDocument());
}
catch (SQLException e)
catch (RawDocumentContentAccessException e)
{
e.printStackTrace();
return Response.status(Status.INTERNAL_SERVER_ERROR)
Expand Down Expand Up @@ -249,6 +253,7 @@ public Response downloadTranslationFile( @PathParam("projectSlug") String projec
@PathParam("fileType") String fileType,
@QueryParam("docId") String docId )
{
GlobalDocumentId id = new GlobalDocumentId(projectSlug, iterationSlug, docId);
// TODO scan (again) for virus
final Response response;
HDocument document = this.documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);
Expand Down Expand Up @@ -278,7 +283,7 @@ else if ("po".equals(fileType) || FILE_TYPE_OFFLINE_PO.equals(fileType))
}
else if (FILETYPE_TRANSLATED_APPROVED.equals(fileType) || FILETYPE_TRANSLATED_APPROVED_AND_FUZZY.equals(fileType) )
{
if (!translationFileServiceImpl.hasPersistedDocument(projectSlug, iterationSlug, document.getPath(), document.getName()))
if (!filePersistService.hasPersistedDocument(id))
{
return Response.status(Status.NOT_FOUND).build();
}
Expand All @@ -299,27 +304,33 @@ else if (FILETYPE_TRANSLATED_APPROVED.equals(fileType) || FILETYPE_TRANSLATED_AP
}

HDocument hDocument = documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);
URI uri;
InputStream inputStream;
try
{
File tempFile = translationFileServiceImpl.persistToTempFile(hDocument.getRawDocument().getContent().getBinaryStream());
String name = projectSlug+":"+iterationSlug+":"+docId;
virusScanner.scan(tempFile, name);
uri = tempFile.toURI();
inputStream = filePersistService.getRawDocumentContentAsStream(hDocument.getRawDocument());
}
catch (SQLException e)
catch (RawDocumentContentAccessException e)
{
return Response.status(Status.INTERNAL_SERVER_ERROR)
.entity(e)
.build();
}
File tempFile = translationFileServiceImpl.persistToTempFile(inputStream);
String name = projectSlug+":"+iterationSlug+":"+docId;
// TODO damason: this file is not transmitted, but used to generate a file later
// the generated file should be scanned instead
virusScanner.scan(tempFile, name);
URI uri = tempFile.toURI();
FileFormatAdapter adapter = translationFileServiceImpl.getAdapterFor(hDocument.getRawDocument().getType());
String rawParamString = hDocument.getRawDocument().getAdapterParameters();
Optional<String> params = Optional.<String>fromNullable(Strings.emptyToNull(rawParamString));
StreamingOutput output = new FormatAdapterStreamingOutput(uri, translations, locale, adapter, params);
response = Response.ok()
.header("Content-Disposition", "attachment; filename=\"" + document.getName() + "\"")
.entity(output).build();
// TODO damason: remove more immediately, but make sure response has finished with the file
// Note: may not be necessary when file storage is on disk.
tempFile.deleteOnExit();
}
else
{
Expand Down Expand Up @@ -475,6 +486,7 @@ public FormatAdapterStreamingOutput(URI originalDoc, Map<String, TextFlowTarget>
@Override
public void write(OutputStream output) throws IOException, WebApplicationException
{
// FIXME should the generated file be virus scanned?
adapter.writeTranslatedFile(output, original, translations, locale, params);
}
}
Expand Down
Expand Up @@ -152,8 +152,6 @@ Resource parseUpdatedAdapterDocumentFile(URI documentFile, String docId, String
*/
void removeTempFile(File tempFile);

boolean hasPersistedDocument(String projectSlug, String iterationSlug, String docPath, String docName);

String getFileExtension(String projectSlug, String iterationSlug, String docPath, String docName);

/**
Expand Down
Expand Up @@ -394,13 +394,6 @@ public void removeTempFile(File tempFile)
}
}

@Override
public boolean hasPersistedDocument(String projectSlug, String iterationSlug, String docPath, String docName)
{
HDocument doc = documentDAO.getByProjectIterationAndDocId(projectSlug, iterationSlug, docPath+docName);
return doc.getRawDocument() != null;
}

@Override
public String getFileExtension(String projectSlug, String iterationSlug, String docPath, String docName)
{
Expand Down

0 comments on commit 184dfa4

Please sign in to comment.