diff --git a/zanata-war/src/main/java/org/zanata/action/ProjectIterationFilesAction.java b/zanata-war/src/main/java/org/zanata/action/ProjectIterationFilesAction.java index dddb280b8d..3a56ee3fb0 100644 --- a/zanata-war/src/main/java/org/zanata/action/ProjectIterationFilesAction.java +++ b/zanata-war/src/main/java/org/zanata/action/ProjectIterationFilesAction.java @@ -124,7 +124,7 @@ public class ProjectIterationFilesAction implements Serializable @In private LocaleDAO localeDAO; - @In("blobPersistService") + @In("fileSystemPersistService") private FilePersistService filePersistService; @In @@ -326,6 +326,7 @@ private void uploadPotFile() } // TODO add logging for disk writing errors + // TODO damason: unify this with Source/TranslationDocumentUpload private void uploadAdapterFile() { String fileName = documentFileUpload.getFileName(); diff --git a/zanata-war/src/main/java/org/zanata/dao/DocumentDAO.java b/zanata-war/src/main/java/org/zanata/dao/DocumentDAO.java index 40e220364c..0f39dca4f6 100644 --- a/zanata-war/src/main/java/org/zanata/dao/DocumentDAO.java +++ b/zanata-war/src/main/java/org/zanata/dao/DocumentDAO.java @@ -21,6 +21,7 @@ import org.zanata.common.LocaleId; import org.zanata.common.TransUnitCount; import org.zanata.common.TransUnitWords; +import org.zanata.file.GlobalDocumentId; import org.zanata.model.HDocument; import org.zanata.model.HLocale; import org.zanata.model.HProjectIteration; @@ -325,6 +326,11 @@ public Map getStatistics(long docId, L return returnStats; } + public HDocument getByGlobalId(GlobalDocumentId id) + { + return getByProjectIterationAndDocId(id.getProjectSlug(), id.getVersionSlug(), id.getDocId()); + } + public HDocument getByProjectIterationAndDocId(final String projectSlug, final String iterationSlug, final String docId) { // TODO caching might be better with getByDocIdAndIteration(ProjectIterationDAO.getBySlug(), docId) diff --git a/zanata-war/src/main/java/org/zanata/file/BlobPersistService.java b/zanata-war/src/main/java/org/zanata/file/BlobPersistService.java index 8d99a3851d..6997596831 100644 --- a/zanata-war/src/main/java/org/zanata/file/BlobPersistService.java +++ b/zanata-war/src/main/java/org/zanata/file/BlobPersistService.java @@ -124,8 +124,7 @@ private InputStream getRawDocumentFromTemporaryBlobTable(String locator) @Override public boolean hasPersistedDocument(GlobalDocumentId id) { - HDocument doc = documentDAO.getByProjectIterationAndDocId(id.getProjectSlug(), - id.getVersionSlug(), id.getDocId()); + HDocument doc = documentDAO.getByGlobalId(id); return doc.getRawDocument() != null; } } diff --git a/zanata-war/src/main/java/org/zanata/file/FilePersistService.java b/zanata-war/src/main/java/org/zanata/file/FilePersistService.java index c108a33ab1..fa1e45d26e 100644 --- a/zanata-war/src/main/java/org/zanata/file/FilePersistService.java +++ b/zanata-war/src/main/java/org/zanata/file/FilePersistService.java @@ -27,6 +27,7 @@ public interface FilePersistService { + // TODO damason: add persistRawDocumentContentFromStream(HRawDocument, InputStream) public void persistRawDocumentContentFromFile(HRawDocument rawDocument, File rawFile); diff --git a/zanata-war/src/main/java/org/zanata/file/FileSystemPersistService.java b/zanata-war/src/main/java/org/zanata/file/FileSystemPersistService.java new file mode 100644 index 0000000000..753530a668 --- /dev/null +++ b/zanata-war/src/main/java/org/zanata/file/FileSystemPersistService.java @@ -0,0 +1,150 @@ +/* + * 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 java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import lombok.extern.slf4j.Slf4j; + +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.AutoCreate; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; +import org.zanata.ApplicationConfiguration; +import org.zanata.dao.DocumentDAO; +import org.zanata.model.HDocument; +import org.zanata.model.HProject; +import org.zanata.model.HProjectIteration; +import org.zanata.model.HRawDocument; +import org.zanata.rest.service.VirusScanner; + +import com.google.common.io.Files; + +@Name("fileSystemPersistService") +@Scope(ScopeType.STATELESS) +@AutoCreate +@Slf4j +public class FileSystemPersistService implements FilePersistService +{ + + private static final String RAW_DOCUMENTS_SUBDIRECTORY = "documents"; + + @In("applicationConfiguration") + private ApplicationConfiguration appConfig; + @In + private DocumentDAO documentDAO; + @In + private VirusScanner virusScanner; + + @Override + public void persistRawDocumentContentFromFile(HRawDocument rawDocument, File fromFile) + { + String fileName = generateFileNameFor(rawDocument); + rawDocument.setContentLocation(fileName); + + File newFile = getFileFor(fileName); + try + { + Files.copy(fromFile, newFile); + } + catch (IOException e) + { + // FIXME damason: throw something more specific and handle at call sites + throw new RuntimeException(e); + } + + GlobalDocumentId globalId = getGlobalId(rawDocument); + log.info("Persisted raw document {} to file {}", globalId, newFile.getAbsolutePath()); + virusScanner.scan(newFile, globalId.toString()); + } + + private File getFileFor(String fileName) + { + File docsPath = ensureDocsDirectory(); + File newFile = new File(docsPath, fileName); + return newFile; + } + + private File ensureDocsDirectory() + { + String basePathStringOrNull = appConfig.getDocumentFileStorageLocation(); + if (basePathStringOrNull == null) + { + throw new RuntimeException("Document storage location is not configured in JNDI."); + } + File docsDirectory = new File(basePathStringOrNull, RAW_DOCUMENTS_SUBDIRECTORY); + docsDirectory.mkdirs(); + return docsDirectory; + } + + private static String generateFileNameFor(HRawDocument rawDocument) + { + // Could change to use id of rawDocument, and throw if rawDocument has no id yet. + String idAsString = rawDocument.getDocument().getId().toString(); + String extension = rawDocument.getType().getExtension(); + return idAsString + "." + extension; + } + + // TODO damason: put this in a more appropriate location + private static GlobalDocumentId getGlobalId(HRawDocument rawDocument) + { + HDocument document = rawDocument.getDocument(); + HProjectIteration version = document.getProjectIteration(); + HProject project = version.getProject(); + + GlobalDocumentId id = new GlobalDocumentId( + project.getSlug(), + version.getSlug(), + document.getDocId()); + + return id; + } + + @Override + public InputStream getRawDocumentContentAsStream(HRawDocument document) throws RawDocumentContentAccessException + { + File rawFile = getFileFor(document.getContentLocation()); + try + { + return new FileInputStream(rawFile); + } + catch (FileNotFoundException e) + { + // FIXME damason: throw more specific exception and handle at call sites + throw new RuntimeException(e); + } + } + + @Override + public boolean hasPersistedDocument(GlobalDocumentId id) + { + HDocument doc = documentDAO.getByGlobalId(id); + HRawDocument rawDocument = doc.getRawDocument(); + return rawDocument != null + && getFileFor(rawDocument.getContentLocation()).exists(); + } + +} diff --git a/zanata-war/src/main/java/org/zanata/file/GlobalDocumentId.java b/zanata-war/src/main/java/org/zanata/file/GlobalDocumentId.java index c3db46b357..e7803d1024 100644 --- a/zanata-war/src/main/java/org/zanata/file/GlobalDocumentId.java +++ b/zanata-war/src/main/java/org/zanata/file/GlobalDocumentId.java @@ -17,4 +17,9 @@ public GlobalDocumentId(String projectSlug, String versionSlug, String docId) this.docId = docId; } + @Override + public String toString() + { + return projectSlug + ":" + versionSlug + ":" + docId; + } } diff --git a/zanata-war/src/main/java/org/zanata/file/SourceDocumentUpload.java b/zanata-war/src/main/java/org/zanata/file/SourceDocumentUpload.java index 9715b3a20f..75db4f4d56 100644 --- a/zanata-war/src/main/java/org/zanata/file/SourceDocumentUpload.java +++ b/zanata-war/src/main/java/org/zanata/file/SourceDocumentUpload.java @@ -72,7 +72,7 @@ public class SourceDocumentUpload @In(create = true, value = "documentUploadUtil") private DocumentUploadUtil util; - @In("blobPersistService") + @In("fileSystemPersistService") private FilePersistService filePersistService; @In private ZanataIdentity identity; diff --git a/zanata-war/src/main/java/org/zanata/rest/service/FileService.java b/zanata-war/src/main/java/org/zanata/rest/service/FileService.java index d61a77b399..aa78285068 100644 --- a/zanata-war/src/main/java/org/zanata/rest/service/FileService.java +++ b/zanata-war/src/main/java/org/zanata/rest/service/FileService.java @@ -107,7 +107,7 @@ public class FileService implements FileResource @In(value = "translationDocumentUploader", create = true) private TranslationDocumentUpload translationUploader; - @In("blobPersistService") + @In("fileSystemPersistService") private FilePersistService filePersistService; @Override diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDocumentListHandler.java b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDocumentListHandler.java index 85f77a35ca..258c78a50b 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDocumentListHandler.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/GetDocumentListHandler.java @@ -43,7 +43,7 @@ public class GetDocumentListHandler extends AbstractActionHandler